Tìm hiểu về microservice và các vấn đề thường gặp

I. Khái niệm

Microservice là kiến trúc phần mềm trong đó ứng dụng lớn sẽ được chia thành các service nhỏ độc lập, mỗi service sẽ có chức năng cụ thể. Các service giao tiếp với nhau qua HTTP, Message boroker, gRPC(google Remote Procedure Call)…

II. Kiến trúc Microservice ra đời để giải quyết vấn đề gì?

Kiển trúc Microservice ra đời nhằm giải quyết các hạn chế mà kiến trúc Monolithic chưa thể xử lý. Trước khi Microservice ra đời ứng dụng thường sẽ được phát triển theo kiến trúc Monolithic có nghĩa là tất cả các thành phần được gói gọn trong một khối bao gồm view, business logic, database. Bây giờ chúng ta sẽ cùng tìm hiểu qua một số mục chính sau:

– Khó khăn trong việc scale hệ thống: Ví dụ đối với kiến trúc Monolithic khi scale ta sẽ cần phải scale cả project trong khi trường hợp thức tế ta chỉ cần scale một số chức năng nhất định dẫn đến lãng phí tài nguyên không cần thiết. Còn đối với kiến trúc Microservice thì ta sẽ chia nhỏ từng service ra và chỉ scale các service cần thiết.

Độ phức tạp của hệ thống: Kiến trúc Monolithic khi hệ thống lớn mã nguồn trở lên phức tạp do tất cả các tính năng đều trong cùng một source code. Còn đối với Microservice mỗi service sẽ có source riêng và vai trò riêng của nó từ đó giảm được đáng kế sự phức tạp của hệ thống. Còn thực tế khi hệ thống lớn thì Monolithic hay Microservice cũng đều phức tạp nhưng Microservice sẽ dễ quản lý hơn rất nhiều

Quá trình triển khai CI/CD(Continuous Integration/Continuous Deployment): Kiến trúc Monolithic khi deployment tính năng mới sẽ phải CI/CD toàn bộ project điểu đó là không cần thiết trong khi đối với kiến trúc Microservice có tính năng mới ở “service A” và không liên quan đến các service khác thì sẽ chỉ CI/CD ở “service A”

Khả năng chịu lỗi: Kiến trúc Monolithic nếu gặp sự cố có thể cả hệ thống sẽ ngừng hoạt động, trong khi kiến trúc Microservice sẽ chỉ ảnh hưởng đến service gặp sự cố(Trong thực tế có thể sẽ ảnh hưởng đến các service liên quan đến nó).

Khó khăn trong việc phát triển: Kiến trúc Monolithic nhiều team sẽ phải làm việc trong cùng source code rất dễ bị conflict code và phụ thuộc lần nhau, trong khi kiến trúc Microservice mỗi service sẽ có source code riềng tránh được tình trạng conflict code giữa các team quá trình phất triển cũng giảm được sự phụ thuộc.

Phụ thuộc công nghệ: Kiến trúc Monolithic toàn bộ project sẽ được xây được trên nền tảng duy nhất ví dụ PHP. Còn trong Microservice do chia nhỏ ra thành nhiều service nên các service sẽ có công nghệ độc lập và lưa chọn các công nghệ phù hợp đối với từng service. Ví dụ “service A” dùng PHP, “service B” dùng Golang.

Tốc độ phát triển và bảo trì: Trong kiến trúc Monolithic, quá trình phát triển và bảo trì thường tốn nhiều thời gian hơn do độ phức tạp của toàn hệ thống. Ngược lại, kiến trúc Microservices chia nhỏ ứng dụng thành các service độc lập, giúp giảm thiểu độ phức tạp và từ đó làm cho việc phát triển và bảo trì trở nên nhanh chóng và dễ dàng hơn.

III Ưu nhược điểm của kiến trúc Microservice

1. Ưu điểm

– Độc lập vì mỗi service tự quản lý và xử lý tác vụ riêng, thêm nữa khá linh hoạt khi mỗi service có thể sử dụng bất kì công nghệ nào miễn sao phù hợp với yêu cầu của bài toán.

– Dễ bảo trì vì kiến trúc microservice đã chia nhỏ hệ thống thành các service nên khi cần sửa lỗi hoặc nâng cấp chỉ xử lý các dịch vụ liên quan đến task.

– Khả năng mở rộng cái này không phải ưu điểm thì còn cái nào nữa =)), service nào có truy cập nhiệu scale service đó không nói nhiều, do đã chia nhỏ hệ thống thành các service nhỏ nên khi service cần scale ta cũng đỡ tốn tài nguyên.

– Chịu lỗi tốt do chia nhỏ service nên khi service A gặp vấn đề service B không liên quan gì đến service A vẫn cứ hoạt động thôi chứ không rủ nhau làm bừa được

2. Nhược điểm

– Quản lý phức tạp vì khi có nhiều service ta cần triển khai khá nhiều phương pháp để các service giao tiếp với nhau làm sao cho phù hợp với bài toán và cũng cần thêm các công cụ theo dõi đảm bảo hệ thống mượt mà

– Giao tiếp giữa các dịch vụ cũng là một nhược điểm khi mà chúng ta sẽ cần triển khai giao tiếp giữa các dịch vụ như qua HTTP, message queue… trong mô hình giao tiếp giữa các dịch vụ cần đảm bảo tốt về kết nối và an toàn bảo mật và xử lý lỗi khi giao tiếp gặp sự cố

– Khó khăn trong viêc jkiểm tra và gỡ lỗi do các service có thể lựa chọn các công nghệ khác nhau thêm nữa các service cũng có thể ở các server khác nhau.

– Khó triển khai đồng bộ vì nếu service A phụ thuộc vào service B và có yêu cầu deployment đồng thời 2 service cùng thời điểm, thêm nữa do đa dạng công nghệ nên mỗi service có thể có cách triển khai riêng… Nhưng mà không sao cái gì khó có các anh DevOps, System lo =))

IV Các vấn đề thường gặp khi triển khi Microservice và cách giải quyết

1. Độ phức tạp về hệ thống

Trường hợp số lượng service lớn sẽ xảy ra tình trạng khó quản lý, theo dõi cũng như bảo mật

– Cách giải quyết cho trường hợp này thường sẽ là sử dụng API Gateway: Chúng ta sẽ thêm một service với vai trò trung gian giữa client và các service. Nó giống như khi người dùng request yêu dữ liệu từ service A và service B thì API Gateway sẽ tìm thông tin IP port của các service và tiến hành gọi đến service để lấy kết quả sau đó trả ra cho người dùng. Nhờ API Gateway ta cũng sẽ dễ dàng quản lý khi mà tất cả yêu cầu từ người dùng sẽ đều cần gọi đến API Gateway từ đó ta cũng sẽ dễ dàng hơn trong việc bảo mật ứng dụng. Thông thường API Gateway sẽ cần setup Load Balancing vì tất cả request đều gọi đến API Gateway.

2. Quản lý thông tin các service

Hãy tưởng tượng hiện tại kiến trúc Microservice sử dụng API Gateway câu hỏi đặt ra là làm sao API Gateway có thể gọi API trực tiếp đến service được trong khi IP của service thường là dynamic. Trong thực tế khi triển khai số lượng service sẽ auto scale cho nên khi người dùng truy cập nhiều, hệ thống sẽ tự động thêm instance của service => sẽ có IP mới vậy API Gateway lấy thông tin của service từ đâu.

Cách xử lý cho trường hợp này thường là sử dụng Service Registry: Vai trò của Service Registry là lưu thông tin của các service trong hệ thống như IP, Port và các thông tin cần thiết của từng service đồng thời nó cũng cung cấp thông tin của service khi có yêu cầu. Như vậy nó sẽ có 2 giai đoạn chính là đăng ký và tra cứu trong đó:

+ Service Registration(Đăng ký dịch vụ): Khi một instance của service khởi động nó sẽ tiến hành đăng ký với Service Registry những thông tin cần thiết

+ Service Discovery(Tra cứu dịch vụ): Khi một service muốn giao tiếp với một service khác trong hệ thống đã đăng ký sẽ tiến hành tra cứu Service Registry để lấy thông tin service đó.

3. Cấu hình

Câu hỏi đặt ra trong trường hợp này là bây giờ các service của hệ thống đều cần dùng 1 config giống nhau vậy ta sẽ setup ở tất cả các service hay như nào?

– Thông thường để thuận tiện trong quá trình phát triển trong trường hợp này ta sẽ thêm một service quản lý config tập trung về lâu về dài sẽ dễ dàng bảo trì và phát triển hơn.

4. Giao tiếp giữa các dịch vụ

Nên lựa chọn kiểu giao tiếp nào? Có 2 loại chính là: Sync(đồng bộ) và Async(bất đồng bộ) chúng ta có thể dùng cả 2 loại giao tiếp này cho hệ thống khi có nhu cầu.

Giao tiếp đồng bộ thường dùng: HTTP, GraphQL, gRPC… đối với giao tiếp đồng bộ khi hệ thống gặp vấn đề sẽ dễ dàng xử lý. Tuy nhiên, nhược điểm của chúng tạo ra sự phụ thuộc, vì một service phải chờ phản hồi từ service khác. Trong các giao tiếp trên gRPC là một lựa chọn phổ biến vì hiệu suất của nó khá ok, mặc dù nó khó triển khai hơn. Nguyên nhân gRPC có hiệu suất tốt chủ yếu là do sử dụng “Protocol Buffers” để mã hóa dữ liệu truyền tải thay vì JSON và hỗ trợ HTTP/2 có thể gửi nhiều yêu cầu chỉ trong 1 kết nối.

Giao tiếp bất đồng bộ thường dùng: Message Queue, Event (Pub/Sub) thường sử dụng Apache Kafka hoặc RabbitMQ… kiểu giao tiếp này phức tạp hơn giao tiếp Sync vì cần quản lý các event và đồng bộ dữ liệu nhưng lại giảm tải được cho service, không phụ thuộc vào thời gian thực do sử dụng giao tiếp Async nên hoàn toàn có thể xử lý được các công việc cùng một thời điểm

Khi lựa chọn kiểu giao tiếp ta thường sẽ phụ thuộc vào yêu cầu hiệu suất, độ phức tạp và khả năng chịu lỗi cấu hình của hệ thống.

5. Quản lý data

Thông thường khi triển khai kiến trúc Microservice mỗi service sẽ có cơ sở dữ liệu riêng. Một số vấn đề gặp phải và cần xử lý là:

* Phân mảnh dữ liệu (Data partitioning): Chúng ta sẽ thấy khó khăn hơn trong việc thao tác CRUD vì sẽ có những request không chỉ thao tác dữ liệu từ một service mà là nhiều service. Các giải pháp cho vấn đề này là:

– Sử dụng API hoặc message queue để lấy dữ liệu từ các service

– Sử dụng Event sourcing để xử lý dữ liệu theo event đồng thời lưu lại các event trong Event Store từ đó khi hệ thống gặp vấn đề ta có thể khôi phục lại bằng cách replay các event từ Event Store.

– Để tối ưu truy vấn: Trường hợp hệ thống có yêu cầu ghi và đọc không đồng đều bạn có thể sử dụng CQRS (Command Query Responsibility Segregation) tách biệt phần ghi và đọc. Ở phần này thường bạn sẽ ghi dữ liệu vào mysql/mongodb sau khi ghi xong sẽ create event để đồng bộ dữ liệu vào redis/elasticsearch để dùng cho truy vấn đọc, trong thực tế bạn hoàn toàn có thể sử dụng cùng một loại database cho cả phần ghi và đọc. Đối với một số trường hợp tính năng cần khả năng khôi phục và không có yêu cầu truy xuất dữ liệu tức thì bạn có thể dùng CQRS kết hợp với Event Sourcing, khi đó thay vì dùng database ghi ta sẽ chỉ cần sử dụng Event store lưu trữ các event từ đó khi kích hoạt các event có thể cập nhật database đọc.

* Quản lý giao dịch phân tán(Distributed Transactions): Ở kiến trúc Monolithic xử lý giao dịch khá đơn giản, còn đối với Microservice thì phức tạp hơn. Hiện nay trong Microservice có 3 mô hình phổ biến được sử dụng đến quản lý giao dịch phân tán là:

2PC (Two – Phase Commit): Đối với mô hình 2PC sẽ có 2 giai đoạn chính là Prepare(Chuẩn bị) và Commit/Abort(Cam kết hoặc hủy bỏ) 2 giai đoạn này sẽ đều được thực hiện bởi Coordinator (Điều phối viên). Coordinator nó có thể là một service hoặc là một thành phần trong service. Trong đó Coordinator và các service đều có trạng thái riêng để quản lý transaction cùng với đó là thời gian timeout. Tiếp nữa mỗi một giao dịch phân tán sử dụng 2PC sẽ có một transaction id để quản lý và phân biệt giữa các transaction.

+ Prepare Phase(Giai đoạn chuẩn bị): Coordinator sẽ gửi yêu cầu đến các service để chuẩn bị, tùy vào nhu cầu của mỗi action ở giai đoạn này các service thường sẽ validate data, chuẩn bị data, create hoặc update data nhưng chưa commit…

+ Commit/Abort Phase(Giai đoạn cam kết hoặc hủy bỏ): Coordinator sẽ gửi commit khi tất cả các service ở giai đoạn Perpare đều OK, ngược lại khi một service gặp vấn đề Coordinator sẽ gửi abort đến các service để tiến hành xóa bỏ các bản ghi tạm thời nếu có hoặc khôi phục lại trạng thái ban đầu, các thao tác này sẽ tùy theo giai đoạn Prepare đã làm những gì thì hoàn nguyên lại. Ở giai đoạn này thường ta sẽ phải xử lý nhiều vì sẽ còn rất nhiều trường hợp xảy ra dẫn đến việc dữ liệu không nhất quán như có 4 ông thì commit 3 ông OK 1 ông thì gặp vấn đề hay hệ thống gặp sự cố, ông Coordinator do làm việc quá sức nên lăn ra ngủ… ta làm sao để phục hồi? Nghĩ thôi đã thấy nhiều việc rồi đây =)))

Lưu ý ví dụ ở MYSQL để sử dụng transaction thì bạn cần sử dụng giao dịch phân tán trong MYSQL có hỗ trợ là XA(eXtended Architecture) các bạn có thể dùng keyword này tìm hiểu nhé “mysql xa transaction”

3PC (Three – Phase Commit): Mô hình 2PC (Two-Phase Commit) có những hạn chế, và 3PC ra đời nhằm khắc phục những vấn đề mà 2PC không thể xử lý. Cụ thể, trong 2PC, khi Coordinator gặp sự cố khi gửi lệnh commit cho tất cả các service, các service này sẽ không biết phải làm gì tiếp theo. Chúng không biết liệu tất cả các service khác đã hoàn tất giai đoạn Prepare hay chưa, dẫn đến tình huống mà các service không thể tự quyết định liệu nên rollback hay commit. Với 3PC, một giai đoạn bổ sung gọi là Pre-Commit được thêm vào. Giai đoạn này cho phép các service xác định tình trạng giao dịch và đưa ra quyết định rollback hay commit khi gặp sự cố. Nếu tất cả các service đều đồng ý trong giai đoạn Pre-Commit, chúng có thể tự quyết định commit, ngay cả khi Coordinator gặp sự cố không thể gửi lệnh commit.

Saga pattern: Đối với mô hình Saga pattern thì có 2 cách triển khai chính

+ Orchestration: trong cách triển khai này sẽ có coordinator(Điều phối viên). Ví dụ có 2 service và coordinator, bây giờ giả sử có một người đặt hàng. Hệ thống kích hoạt coordinator sau đó bắt đầu xử lý giao dịch.

  • Bước 1: coordinator gọi đến service 1, sau khi service 1 xử lý xong sẽ báo lại cho coordinator
  • Bước 2: coordinator nhận được thông tin service 1 xử ly xong bước tiếp theo yêu cầu gọi đến service 2 xử lý, sau khi service 2 xử lý xong sẽ báo lại cho coordinator và hoàn thành giao dịch

+ Choreography: Thay vì có coordinator thì ta sẽ không cần nữa chỉ các service giao tiếp với nhau xong thì tiến hành bước tiếp theo luôn không phải báo cáo với coordinator. Bây giờ giả sử khi người dùng đặt hàng hệ thống cần tạo đơn hàng

  • Bước 1: service 1 tạo đơn hàng, sau khi xử lý xong báo cho service 2
  • Bước 2: service 2 nhận thông tin service 1 xử lý xong tiến hành xử lý công việc ở giai đoạn của mình sau khi xử lý xong báo lại hệ thống hoàn thành giao dịch.

– Ở cả 2 cách triển khai trên trường hợp lỗi ở bất kì bước nào ta cần phải xử lý các hành động bù trừ để hoàn tác lại các thao tác trước đó. Mỗi cách triển khai có sẽ có nhược điểm riêng như Orchestration thì lại là nút thắt đúng kiểu ở bước nào xong cũng cần báo cáo để ông(coordinator) quyết định xem làm gì tiếp theo, nếu hôm nào ông nghỉ thì hệ thống cũng không cần xử lý giao dịch gì hết =)). Còn Choreography khi hệ thống lớn thì sẽ khó quán lý và tăng độ phức tạp cho hệ thống.

Trong kiến trúc microservice thường được khuyến cáo không nên sử dụng 2PC và 3PC vì hiệu suất thấp, khả năng chịu lỗi kém và tính sẵn sàng không cao. Thường thay vì ưu tiên tính nhất quán tức thì ta sẽ ưu tiên tính nhất quán sau cùng. Và theo mình thấy khi lựa chọn dùng vẫn là chọn sự phù hợp và đánh đổi kiểu như đáng ra bài toán cần sự nhất quán tức thì, nhưng hệ thống không phù hợp vậy ta đặt ra một vài câu hỏi đánh đổi xem có chấp nhận không? Kiểu thay vì xử lý tức thì ta chuyển sang không tức thì, gặp vấn đề gì có đánh đổi chấp nhận được không? Như vậy có phù hợp không? Kiêu trong đầu lúc nào cũng có các giả thuyết =)) Từ đó cũng giúp chúng ta hiểu rõ hơn về sản phẩm tại sao phải xử lý như vậy…

* Nhất quán dữ liệu(Data Consistency): Đối với kiến trúc microservice việc nhất quán data là rất quan trọng nhờ những phương pháp xử lý giao dịch phân tán ở trên hay sử dụng event sourcing đã phần lớn giải quyết được vấn đề nhất quán data. Theo như mình tìm hiểu được có pattern phổ biến xử lý cho trường hợp này là “Outbox pattern” vậy cách nó xử lý để nhất quán data như nào?

– Mình sẽ ví dụ trường hợp như sau: Hãy tưởng tượng hệ thống micorservice chúng ta sử dụng event để giao tiếp giữa các service, ví dụ bạn có request tạo order thì khi áp dụng Outbox pattern khi bạn lưu order vào table orders đồng thời bạn cũng lưu event “CreatedOrder” vào table outboxes các thao tác này của bạn sẽ cùng transaction đảm bảo khi lưu được order vào database thì event “CreatedOrder” cũng vậy. Chúng ta sẽ có một worker theo dõi các event đã lưu trong outboxes nó sẽ có nhiệm vụ là đọc các events và push event ví dụ push vào RabbitMQ hoặc Kafka… Tất nhiên sau khi push event thành công thì event trong table outboxes cũng sẽ được đánh dấu để tránh phát lại event. Từ đó ta có thể tránh được 1 số trường hợp không nhất quản data như

+ Logic xử lý gửi sự kiện trước khi thêm mới order mà gửi sự kiện thành công còn thêm mới order lại bị lỗi.

+ Ngược lại thì thêm mới order thành công nhưng gửi sự kiện bị lỗi.

+ Trong một số trường hợp, service A gửi event cho service B, nhưng khi service B đọc database của service A để lấy thông tin order, nó không thấy dữ liệu vì việc gửi event và tạo order không cùng transaction.

6. Bảo mật

– Authentication & Authorization

Trong microservice để bảo mật hiện nay thường có một số phương pháp triển khai như. Xử lý authentication(xác thực) và authorization(cấp quyền) tại API Gateway hoặc sẽ có service identity provider để xử lý authentication và authorization. Thường thì authorization sẽ có ở các service khi authorization cần chi tiết hơn như người dùng chỉ được thao tác với tài nguyên của chính họ, còn authorization đơn giản theo router thì API Gateway hoàn toàn có thể xử lý ngay tại đầu vào. Ví dụ các bước thao tác người dùng để authentication và authorization sử dụng JWT:

+ Bước 1: Client gửi thông tin đăng nhập lên API Gateway đối với trường hợp xử lý tại Gateway thì sau khi xác thực thành công API Gateway sẽ trả về cho client JWT token, còn sử dụng service identity provider thì thay vì xác thực tại Gateway thì Gateway sẽ gọi sang service identity provider để xác thực sau khi thành công service identity provider sẽ trả về JWT token cho Gateway và Gateway trả về cho client.

+ Bước 2: Client request đến router lấy thông tin bài viết của họ API Gateway nhận thông tin và tiến hành authorization xem client có được phép truy cập router không nếu có thì gọi đến service, service kiểm tra xem người dùng này có quyền xem bài viết khồng nếu có thì trả về (Như vậy trong trường hợp này cả API Gateway và service đều cần authorization).

– Trong trường hợp thông tin đường dẫn của service bị lộ và service có thể truy cập từ bất kỳ đâu, chúng ta có thể áp dụng một số biện pháp bảo mật để hạn chế quyền truy cập từ bên ngoài. Theo mình tìm hiểu được chúng ta có thể sử dụng firewall để chỉ cho phép một số địa chỉ IP nhất định được phép truy cập. Ta cũng có thể setup VPN cho phép các service giao tiếp nhau một cách an toàn trong mạng riêng.

7. Quản lý log và error

– Quản lý log tập trung

Trong microservice khi nhắc đến log thì chúng ta nghĩ ngay đến quản lý log tập trung sử dụng Elastic Stack (ELK) là một lựa chọn khá phổ biến Gồm Elasticsearch, LogstashKibana, ELK nó thường đi kèm với Filebeat để thu thập logs. Quy trình làm việc của nó khá rõ ràng Filebeat sẽ thu thập logs từ các service có thể là server hoặc container theo các config prospectors sau đó gửi đến Logstash, Logstash nhận xử lý dữ liệu và gửi dữ liệu lên Elasticsearch, Elasticsearch chúng ta thường biết đến nó với vai trò mạnh mẽ trong việc tìm kiếm, phân tích và thống kê. Còn Kibana thì cung cấp cho ta giao diện trực quan giúp ta có thể dễ dang tìm kiềm ngoài ra nó còn cùng cấp khá nhiều loại biểu đổ giúp ta có thể phân tích và theo dõi. Nếu bạn muốn có Dashboard tùy chỉnh các biểu đồ mà bạn muốn theo dõi thì Kibana có thể làm điều đó.

Mô hình quản lý log khá ok nó sẽ bao gồm các thông tin log của nginx, apache, service, hệ thống… đối với hệ thống nếu bạn muốn có thông tin RAM và CPU nhưng không có file log thì bạn hoàn toàn có thể tạo 1 file log lưu thông tin CPU và RAM thông qua 1 lệnh script nào đó và output sẽ ghi vào file log thế là filebeat có thể thu thập log từ file này hoặc bạn có thể dùng một số công cụ khác chuyên về theo dõi hệ thống.

– Đối với Error mình sẽ chỉ nói về các error của service liên quan đến code, phổ biến hiện nay là sử dụng Sentry, vậy những gì Sentry của thể làm là gì?

Nó có thể ghi nhận thông báo lỗi thời gian thực, đồng thời cung cấp thông tin chi tiết về lỗi, phân tích và phân loại lỗi, gửi thông báo cho chúng ta qua email, slack… Mình vẫn nhớ có lỗi liên quan đến API sản phẩm mình đang phát triển nhưng mà client gửi lên thông tin chưa chính xác dẫn đến có event lên sentry nhưng mình không quan tâm kiểu lỗi không phải ở API, nhưng điều đó là sai lầm để hệ thống hay sản phẩm hoạt động tốt chúng ta cần theo dõi những gì mà log cung cấp từ đó ta có thể phán đoán hoặc biết nguyên nhân ở đâu mà có phương hướng xử lý giải quyết vấn đề.

Thường sẽ có khá nhiều cân do đong đếm ở đây theo mình thấy để triển khai quản lý log nó còn tùy thược vào hệ thống, tài nguyên, nhu cầu sử dụng nhiều hay ít thì mới quyết định xem có cần thiết triển khai hay không.

VI Kết luận

Trên đây là những gì mình đã tìm hiểu về microservices. Qua việc phân tích ưu và nhược điểm, chúng ta có thể nhận thấy rằng microservices mang lại rất nhiều lợi ích, nhưng cũng không thiếu những thách thức. Đặc biệt, trong môi trường DevOps, thách thức lớn nhất là quản lý hạ tầng phân tán, đảm bảo bảo mật giữa các service và giám sát toàn bộ hệ thống khi quy mô ngày càng mở rộng và độ phức tạp tăng lên. Hy vọng qua bài viết này, chúng ta sẽ có cái nhìn rõ ràng hơn về kiến trúc microservices và những vấn đề cần lưu ý khi triển khai.

Cảm ơn các bạn đã đọc!

Related Posts