+2

Hệ thống phần mềm vi dịch vụ

1.1 Giới thiệu về hệ thống vi dịch vụ

1.1.1 Đặc điểm của kiến trúc hệ thống vi dịch vụ

Hệ thống vi dịch vụ (Microservice System – MS) đã nổi lên trong vài năm qua để mô tả một cách đặc biệt của thiết kế các ứng dụng phần mềm như là một hệ thống các dịch vụ được triển khai độc lập và giao tiếp với nhau qua mạng. Trên thực tế, vẫn chưa có định nghĩa chính xác về MS. [1] đã nêu lên một số đặc điểm chung về giao dịch qua mạng, triển khai tự động, thiết bị đầu cuối thông minh, và kiểm soát phân cấp của ngôn ngữ và dữ liệu. Nhờ đó, ở chương này, nghiên cứu và đưa ra định nghĩa các đặc điểm của hệ thống vi dịch vụ một cách chặt chẽ hơn

a, Được cấu thành từ các dịch vụ

James Lewwis, tác giả [1] cùng nhóm nghiên cứu của ông đã nêu ra: Từ khi được tham gia vào ngành công nghiệp phần mềm, họ đã có một mong muốn xây dựng hệ thống phần mềm bằng cách kết hợp các thành phần lại với nhau, giống như cách mà ta tạo nên các đồ vật trong thế giới vật lý. Vậy “thành phần” được hiểu như thế nào? Tác giả đã đưa ra định nghĩa như sau: “một thành phần là một đơn vị của phần mềm mà có thể thay thế và nâng cấp một cách độc lập”.

Kiến trúc vi dịch vụ sử dụng các thư viện, nhưng cách thức cơ bản của nó để tạo ra các “thành phần” là tách nhỏ phần mềm thành các khối dịch vụ. Mỗi thư viện được coi là một thành phần được liên kết với chương trình chính và được gọi trong các bộ nhớ chức năng. Trong khi các thành phần ngoài sẽ giao tiếp thông qua cơ chế như yêu cầu một dịch vụ web, hoặc gọi thủ tục từ xa.

Lý do chính để sử dụng các dịch vụ như các thành phần (chứ không phải là các thư viện) là các dịch vụ được triển khai một cách độc lập. Giả sử, có một ứng dụng [4], ứng dụng này gồm nhiều thư viện trong một tiến trình đơn, một sự thay đổi nhỏ ở bất kỳ thành phần riêng lẻ nào cũng bắt buộc phải triển khai lại toàn bộ ứng dụng. Nhưng nếu ứng dụng đó bị phân tách ra thành nhiều khối dịch vụ, thì khi thay đổi thành phần nào đó thì chỉ có dịch vụ đó cần phải triển khai lại. Điều này không phải tuyệt đối, có một số thay đổi sẽ làm thay đổi giao diện của dịch vụ dẫn đến việc thay đổi của một số các dịch vụ liên quan, nhưng mục đích của một kiến trúc vi dịch vụ tốt là một kiến trúc đảm bảo giảm thiểu những yếu điểm trên.

Một đặc điểm khác của việc sử dụng các dịch vụ như các thành phần của một hệ thống là các thành phần có giao diện rõ ràng hơn. Hầu hết các ngôn ngữ không có cơ chế để xác định giao diện một cách rõ ràng. Thường thì chỉ có cách đưa ra tài liệu và các nguyên tắc rõ ràng mới có thể ngăn chặn máy khách không vi phạm quy tắc đóng gói các thành phần, dẫn đến khớp nối quá chặt chẽ giữa các thành phần. Các dịch vụ tránh điều này bằng cách sử dụng các cơ chế cuộc gọi từ xa một cách rõ ràng. Sử dụng dịch vụ như thế này không có nhược điểm.

b, Được tổ chức dựa trên các giao dịch

Khi tìm cách để chia nhỏ một ứng dụng lớn thành nhiều phần, thường phải quản lý tập trung vào các tầng công nghệ, dẫn đến việc hình thành các đội UI, các đội phía máy chủ logic, và các đội cơ sở dữ liệu. Khi đội được tách ra theo cách này, thì thậm chí thay đổi đơn giản cũng có thể dẫn đến việc tốn thời gian của các đội khác và tốn ngân sách. Nhóm thông minh sẽ tối ưu hóa việc này vừa đảm bảo thời gian vừa đảm bảo chi phí, đó là chỉ cần đội tập trung vào máy chủ logic, như vậy họ có thể truy cập bất cứ ứng dụng nào. Đây chính là luật [5] Conway [5] được mô tả cụ thể như hình dưới đây:

    Hình  I.1 Phương thức hoạt động của luật Conway [15]

Nói tóm lại, hệ thống vi dịch vụ là hệ thống được tổ chức dựa trên các giao dịch giữa các thành phần độc lập của hệ thống.

c, Vi dịch vụ là một sản phẩm không phải là một dự án

Hầu hết các ứng dụng được phát triển thì đều sử dụng một mô hình nào đó: mục đích là để cung cấp một số phần đã hoàn thiện của phần mềm, các phần này kết hợp với nhau thành một phần hoàn chỉnh. Sau khi sản phẩm phần mềm được hoàn thành thì nó được bàn giao cho khách hàng rồi đến các nhóm bảo trì và kết thúc dự án.

Hệ thống vi dịch vụ có xu hướng phát triển tránh mô hình này, thay vào đó thì đội dự án cần sở hữu sản phẩm này xuyên suốt vòng đời của nó. Điều này mang lại cho các nhà phát triển liên hệ theo ngày với người dùng cuối để biết được phần mềm của họ hoạt động như thế nào, điều này cũng đồng thời làm tăng mối liên kết cũng như giao tiếp giữa nhà phát triển và người dùng cuối.

Chính vì thế, các hệ thống vi dịch vụ được coi là một sản phẩm phần mềm hơn là một dự án phầm mềm.

d, Dữ liệu được quản lý không tập trung (Decentralized)

Tất cả các dịch vụ có dữ liệu lưu trữ của riêng nó, tách biệt hoàn toàn với các phần khác của hệ thống. Điều này thường dẫn tới kết quả là các lược đồ cơ sở dữ liệu thường đơn giản và nhỏ, riêng biệt, điều này rất tốt bởi nó sẽ đảm bảo dễ dàng có cái nhìn tổng quan về một lược đồ. Dữ liệu sẽ theo một cách khác cũng được tách riêng, và như vậy có thể yêu cầu cùng một dữ liệu được lưu trữ ở các vị trí khác nhau.

    Hình  I 2 Microservice application database [15]

e, Đa ngôn ngữ

Một microservice có thể được hiện thực bằng bất kỳ ngôn ngữ lập trình nào với bất kỳ công nghệ lưu trữ dữ liệu nào mà nhóm ưa thích. Nghĩa là microservice không bị giới hạn về công nghệ so với phần còn lại của hệ thống.

f, Triển khai liên tục

Các microservice có thể được xây dựng, triển khai và thử nghiệm độc lập với nhau.

g, Khép kín

Mỗi dịch vụ có chứa logic nghiệp vụ kinh doanh của riêng mình và được triển khai riêng biệt. Điều này giúp cho nó có thể thay đổi và dần dần mở rộng với các tính năng mới mà không làm ảnh hưởng tới phần còn lại của hệ thống. Đặc tính khép kín (self-contained) cũng hỗ trợ việc lựa chọn công nghệ phù hợp nhất cho một dịch vụ cụ thể linh hoạt hơn rất nhiều. Công nghệ sẽ không bị giới hạn trong một tập các công nghệ được xác định trước hoặc một framework cụ thể nào đó.

h, Liên lạc ngoài dịch vụ

Một dịch vụ được chạy dưới tiến trình chứa nó và chỉ có thể giao tiếp/liên lạc thông qua hệ thống nhắn tin như RabbitMQ và thường sử dụng giao thức request/reply.

i, Nguyên tắc chuyên biệt

Một microservice nên thực hiện một chức năng kinh doanh duy nhất, bao gồm các thành phần có gắn kết chặt chẽ với nhau. Điều này nghĩa là một dịch vụ sẽ phải chịu trách nhiệm cho một lĩnh vực nào đó và lĩnh vực này là duy nhất.

1.1.2 Ưu điểm của kiến trúc hệ thống vi dịch vụ

  • Giảm thiểu sự gia tăng phức tạp rối rắm hệ thống lớn
  • Chia nhỏ ứng dụng một khối cồng kềnh thành các dịch vụ nhỏ dễ quản lý, bảo trì nâng cấp, tự do chọn, nâng cấp công nghệ mới
  • Mỗi dịch vụ nhỏ sẽ định ra ranh giới rõ ràng dưới dạng RPC hay API hướng thông điệp
  • Microservice thúc đẩy tách rạch ròi các khối chức năng (loose coupling - high cohesion), điều rất khó thực hiện với ứng dụng một khối. Nếu muốn loose coupling - high cohesion trong ứng dụng một khối, sẽ phải thiết kế theo Design Pattern (Gang Of Four) và liên tục tái cấu trúc (refactor)
  • Mỗi dịch vụ nhỏ sẽ phát triển dễ hơn, nhanh hơn, dễ viết mã kiểm thử tự động.
  • Một số dịch vụ có thuê ngoài phát triển mà vẫn bảo mật hệ thống - mã nguồn phần dịch vụ còn lại. Đội phát triển có nhiều lựa chọn công nghệ mới, framework, CSDL mới, đa dạng để nâng cấp từng dịch vụ nhỏ, chọn môi trường tối ưu nhất để chạy. Các dịch vụ có thể bật tắt để kiểm nghiệm so sánh A|B, tăng tốc quá trình cải tiến giao diện. Triển khai đều đặn khả thi với microservice. Dịch vụ nhỏ đóng gói trong Docker container có thể chuyển từ môi trường phát triển sang môi trường chạy thật không phải cấu hình thủ công lại, không phải copy file quá lớn.

1.1.3 Nhược điểm của kiến trúc hệ thống vi dịch vụ

Nhược điểm đầu tiên của microservices cũng chính từ tên gọi của nó. Microservice nhấn mạnh kích thước nhỏ gọn của dịch vụ. Một số lập trình đề xuất dịch vụ siêu nhỏ cỡ dưới 100 dòng code. Chia quá nhiều sẽ dẫn đến manh mún, vụn vặt, khó kiểm soát. Việc lưu dữ liệu cục bộ bên trong những dịch vụ quá nhỏ sẽ khiến dữ liệu phân tán quá mức cần thiết.

Nhược điểm tiếp của microservice đến từ đặc điểm hệ thống phân tán (distributed system):

  • Phải xử lý sự cố khi kết nối chậm, lỗi khi thông điệp không gửi được hoặc thông điệp gửi đến nhiều đích đến vào các thời điểm khác nhau.
  • Đảm bảo giao dịch phân tán (distributed transaction) cập nhật dữ liệu đúng đắn (all or none) vào nhiều dịch vụ nhỏ khác nhau khó hơn rất nhiều, đôi khi là không thể so với đảm bảo giao dịch cập nhật vào nhiều bảng trong một cơ sở dữ liệu trung tâm
  • Theo nguyên tắc CAP (CAP theorem) thì giao dịch phân tán sẽ không thể thỏa mãn cả 3 điều kiện: consistency (dữ liệu ở điểm khác nhau trong mạng phải giống nhau), availablity (yêu cầu gửi đi phải có phúc đáp), partition tolerance (hệ thống vẫn hoạt động được ngay cả khi mạng bị lỗi). Những công nghệ cơ sở dữ liệu phi quan hệ (NoSQL) hay môi giới thông điệp (message broker) tốt nhất hiện nay cũng chưa vượt qua nguyên tắc CAP.
  • Triển khai dịch vụ microservices nếu làm thủ công theo cách đã làm với ứng dụng một khối phức tạp hơn rất nhiều. Ứng dụng một khối bổ xung các server mới giống hệt nhau đằng sau bộ cần bằng tại. Trong khi ở kiến trúc microservice, các dịch vụ nhỏ nằm trên nhiều máy ảo hay Docker container khác nhau, hoặc một dịch vụ có nhiều thực thể phân tán ra nhiều. Theo Adrian Crockcroft, Hailo có 160 dịch vụ, NetFlix có hơn 600 dịch vụ. Trong dịch vụ đám mây, các máy ảo, docker container, thực thể có thể linh động bật tắt, dịch chuyển. Vậy cần thiết phải có một cơ chế phát hiện dịch vụ (service discovery mechanism) để cập nhật tự động địa chỉ IP và cổng, mô tả, phiên bản của mỗi dịch vụ.

1.2 So sánh kiến trúc vi dịch vụ với kiến trúc hệ thống nguyên khối (Monilithic System)

Hệ thống Monilithic hay một hệ thống nguyên khối là một chương trình thực thi logic đơn. Bất kỳ một thay đổi được thực hiện với một phần của một hệ thống nguyên khối đều liên quan tới xây dựng và triển khai một phiên bản mới của toàn bộ hệ thống. Mặc dù Alm Brand hiện đang hướng tới các thành phần tái sử dụng, tuy nhiên họ đã nhiều lần thỏa hiệp với một giải pháp chung cho một sản phẩm cụ thể. Điều này đã dẫn tới một số hệ thống theo kiến trúc nguyên khối, với một số đặc điểm chung được liệt kê dưới đây.

a, Một cơ sở mã nguồn

Toàn bộ hệ thống thường nằm trong một cơ sở mã nguồn lớn. Khi ứng dụng mở rộng đồng nghĩa với việc mở rộng kích thước mã nguồn. Nhóm phát triển có thể duy trì tương đối tốt.

b, Ngôn ngữ cụ thể

Do đặc điểm hệ thống chỉ có một cơ sở mã nguồn nên toàn bộ hệ thống thường được xây dựng trên một ngôn ngữ lập trình duy nhất.

c, Mở rộng ngang

Điều này không đồng nghĩa với việc có thể mở rộng bất kỳ một thành phần nào trong ứng dụng nguyên khối. Toàn bộ ứng dụng nguyên khối sẽ được mở rộng hoặc không gì cả. Mở rộng được hoàn thành sử dụng cân bằng tải với một vài thể hiện (instances) của ứng dụng nguyên khối.

d, Kiến trúc 3 lớp

Lớp 1: Giao diện người dùng (client-side) gồm các trang HTML, Javascript chạy trên trình duyệt trên máy tính người dùng;
Lớp 2: Cơ sở dữ liệu thường là các hệ quản trị cơ sở dữ liệu quan hệ; Lớp 3: Máy chủ ứng dụng (server-side)

e, Tiến trình đơn

Một hệ thống nguyên khối như máy chủ ứng dụng được nêu ở trên thường được chạy trong một tiến trình đơn.

f, Các thành phần đan xen

Các thành phần trong một hệ thống nguyên khối không có một chủ sở hữu rõ ràng, thường dẫn tới ràng buộc giữa các thành phần.

g, Vòng đời triển khai dài

Việc bảo trì và mở rộng các chức năng ứng dụng nguyên khối tiêu tốn nhiều thời gian. Ngay cả các thay đổi nhỏ nhất cũng có thể dẫn tới nhu cầu phải xây dựng, triển khai và thử nghiệm toàn bộ ứng dụng.

TÀI LIỆU THAM KHẢO

Tài liệu Tiếng Anh

[1] Alain Abran, J W Moore, P Bourque, R Dupuis, and L L Tripp. “Software Engineering Body of Knowledge”. In: IEEE Computer Society, Angela Burgess (2004). [2] Akka Framework of distributed transactions (Accessed on 25/04/2015) URL: www.Akka.io [3] Apache Kafka & Zookeeper introduction (Accessed on 21/02/2015) [4] Apache Zookeeper (Accessed on 21/02/2015) [5] Apache Kafka (Framework) (Accessed on 22/02/2015) [6] Apache Kafka: Next Generation Distributed Messaging System (Accessed on 22/02/2015) [7] Clarifying the Saga Pattern (Accessed on 21/02/2015) [8] Development/Maintenance ratio (Accessed on 03/05/2015) [9] Illinois Institute of Technology (Accessed on 02/02/2015) [10] J. Kreps LinkedIn Corp, N. Narkhede LinkedIn Corp, J. Rao LinkedIn Corp. Apache Kafka: a Distributed Messaging System for Log Processing (Accessed on 25/02/2015) [11] L. Bass, P. Clements & R. Kazman - Software Architecture in Practice (2nd Edition), 2003 [12] Martin Fowler and James Lewis. Microservices (Accessed on 03/02/2015). [13] Monolithic Design (Accessed on 04/02/2015) [14] Scalability Best Practices: Lessons from eBay (Accessed 08/06/2015)

Website tham khảo

[15] http://martinfowler.com/articles/microservices.html

[16] http://omega.cs.iit.edu/~ipro329/methodology.html [17] http://hosteddocs.ittoolbox.com/PM043004.pdf [18] http://www.sei.cmu.edu/library/assets/whitepapers/SOA_Terminology.pdf [19] http://www.w3.org/TR/ws-arch/#service_oriented_architecture [20] http://c2.com/cgi/wiki?MonolithicDesign


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí