Sách dịch: Building Microservices: Designing Fine-Grained Systems – Chương 3 Mô hình hóa các dịch vụ

by son
325 views
This entry is part [part not set] of 3 in the series Building Microservices: Designing Fine-Grained Systems

CHƯƠNG 3 Mô hình hóa các dịch vụ

Lập luận của đối thủ khiến tôi nhớ đến một kẻ ngoại đạo, người, khi được hỏi về thế giới đang đứng trên cái gfi, đã trả lời: "Trên một con rùa." Nhưng con rùa đứng trên cái gì? "Trên một con rùa khác."

—Joseph Barker (1854)

Vì vậy, bạn biết microservices là gì và hy vọng hiểu được những lợi ích chính của chúng. Bây giờ có lẽ bạn đang háo hức muốn đi và bắt đầu tạo ra chúng, phải không? Nhưng bắt đầu từ đâu? Trong chương này, chúng ta sẽ xem xét cách suy nghĩ về ranh giới của các microservice của bạn, hy vọng sẽ tối đa hóa những ưu điểm và tránh một số nhược điểm tiềm ẩn. Nhưng trước tiên, chúng ta cần một cái gì đó để làm việc cùng nó.

Giới thiệu về MusicCorp

Sách về ý tưởng hoạt động tốt hơn với các ví dụ. Nếu có thể, tôi sẽ chia sẻ những câu chuyện từ các tình huống thực tế, nhưng tôi nhận thấy rằng việc có một lĩnh vực hư cấu để hoạt động cũng rất hữu ích. Xuyên suốt cuốn sách, chúng ta sẽ quay trở lại lĩnh vực này, xem khái niệm microservices hoạt động như thế nào trong thế giới này.

Vì vậy, chúng ta hãy chuyển sự chú ý của chúng ta đến một trong những nhà bán lẻ trực tuyến tiên tiến nhất hiện nay – MusicCorp. MusicCorp gần đây là một nhà bán lẻ truyền thống, nhưng sau khi công ty từ bỏ mảng kinh doanh máy hát, mảng kinh doanh nền tảng của MusicCorp, họ ngày càng tập trung nhiều hơn vào việc kinh doanh trực tuyến. Công ty có một trang web, nhưng cảm thấy rằng bây giờ là lúc để tăng gấp đôi doanh số trên các nền tảng trực tuyến. Xét cho cùng, những chiếc iPod đó chỉ là một mốt nhất thời (rõ ràng là Zunes tốt hơn nhiều) và những người hâm mộ âm nhạc đang khá vui khi chờ đĩa CD được chuyển tới nhà của họ. Chất lượng bao giờ cũng hơn sự tiện lợi, phải không? Và trong khi chúng ta đang ở đó, điều mà mọi người vẫn tiếp tục về Spotify này là gì — một nền tảng hướng đến đối tượng thanh thiếu niên?

Mặc dù đi sau một chút so với phần còn lai, nhưng MusicCorp lại có tham vọng lớn. May mắn thay, họ đã quyết định rằng cơ hội tốt nhất để chiếm lấy thị phần là đảm bảo rằng nó có thể thực hiện những thay đổi dễ dàng nhất có thể. Microservices giành chiến thắng!

Điều gì tạo nên một dịch vụ tốt?

Trước khi nhóm từ MusicCorp thay đổi chính mình, tạo ra dịch vụ này đến dịch vụ khác trong nỗ lực cung cấp loại băng 8 bản nhạc cho tất cả mọi người và một vài thứ khác, hãy bắt đầu và nói một chút về ý tưởng cơ bản quan trọng nhất mà chúng ta cần ghi nhớ. Điều gì tạo nên một dịch vụ tốt? Nếu bạn vẫn sống sót sau một lần deploy SOA không thành công, bạn có thể có một số ý tưởng về nơi tiếp theo mà tôi nói đến. Nhưng đề phòng trong trường hợp bạn không phải là kẻ may mắn hoặc giả sử bạn chính là kẻ may mắn, tôi muốn bạn tập trung vào hai khái niệm chính: liên kết lỏng lẻotính liên kết cao (loose coupling and high cohesion). Chúng tôi sẽ nói chi tiết trong suốt cuốn sách về những ý tưởng và thực tiễn khác, nhưng chúng đều vô ích nếu chúng tôi làm sai hai điều này.

Mặc dù thực tế là hai thuật ngữ này được sử dụng rất nhiều, đặc biệt là trong ngữ cảnh của các hệ thống hướng đối tượng, nhưng điều đáng bàn về ý nghĩa của chúng đối với microservices là gì.

Liên kết lỏng lẻo

Khi các dịch vụ được kết hợp một cách lỏng lẻo, một sự thay đổi đối với một dịch vụ không yêu cầu thay đổi một dịch vụ khác. Toàn bộ quan điểm của microservice là có thể thực hiện thay đổi đối với một dịch vụ và deploy nó mà không cần thay đổi bất kỳ phần nào khác của hệ thống. Điều này thực sự khá quan trọng.

Những thứ gì gây ra sự kết hợp chặt chẽ? Một sai lầm cổ điển là chọn một phong cách tích hợp liên kết chặt chẽ giữa dịch vụ này với dịch vụ khác, khiến những thay đổi bên trong dịch vụ đòi hỏi nhưng nơi sử dụng nó phải thay đổi. Chúng ta sẽ thảo luận sâu hơn về cách tránh điều này trong Chương 4.

Một dịch vụ được kết hợp một cách lỏng lẻo cần biết rất ít về những dịch vụ mà nó cộng tác cùng. Điều này cũng có nghĩa là chúng tôi có thể muốn giới hạn số lượng các loại yêu cầu/gọi chức năng khác nhau từ dịch vụ này sang dịch vụ khác, bởi vì ngoài vấn đề tiềm tàng về hiệu suất, giao tiếp kiểu này có thể dẫn đến kết nối chặt chẽ.

Độ gắn kết cao

Chúng tôi muốn hành vi liên quan thi đi cùng nhau và hành vi không liên quan nên ở nơi khác. Tại sao? Vâng, nếu chúng ta muốn thay đổi hành vi, chúng ta muốn có thể thay đổi nó ở một nơi và giải phóng thay đổi đó càng sớm càng tốt. Nếu chúng tôi phải thay đổi hành vi đó ở nhiều nơi khác nhau, chúng tôi sẽ phải release nhiều dịch vụ khác nhau (có thể cùng một lúc) để thực hiện thay đổi đó. Việc thực hiện các thay đổi ở nhiều nơi khác nhau sẽ chậm hơn và việc deploy nhiều dịch vụ cùng một lúc là rất rủi ro — cả hai điều này chúng tôi đều muốn tránh.

Vì vậy, chúng tôi muốn tìm các ranh giới của các vấn đề trong lĩnh vực của mình để giúp đảm bảo rằng hành vi liên quan sẽ ở cùng một nơi và giao tiếp với các ranh giới khác một cách lỏng lẻo nhất có thể.

Bối cảnh có giới hạn

Cuốn sách của Eric Evans về Thiết kế theo hướng lĩnh vực – Domain-Driven Design (Addison-Wesley) tập trung vào cách tạo hệ thống mô hình hóa các lĩnh vực trong thế giới thực. Cuốn sách chứa đầy những ý tưởng tuyệt vời như sử dụng ngôn ngữ phổ biến, sự trừu tượng của kho lưu trữ, và những thứ tương tự, nhưng có một khái niệm rất quan trọng mà Evans giới thiệu lúc đầu đã hoàn toàn lướt qua tôi: bối cảnh có giới hạn. Ý tưởng ở đây là bất kỳ lĩnh vực cụ thể nào đều bao gồm nhiều bối cảnh có giới hạn và nằm trong mỗi bối cảnh là những thứ (Eric sử dụng mô hình – model từ rất nhiều, có lẽ tốt hơn là những thứ – things) không cần giao tiếp với bên ngoài cũng như những thứ được chia sẻ ra bên ngoài với các bối cảnh có giới hạn khác. Mỗi bối cảnh có giới hạn có một giao diện rõ ràng, nơi nó quyết định những mô hình nào sẽ chia sẻ với các bối cảnh khác.

Một định nghĩa khác về bối cảnh có giới hạn mà tôi thích là "một trách nhiệm cụ thể được thực thi bởi các ranh giới rõ ràng." Nếu bạn muốn thông tin từ bối cảnh có giới hạn hoặc muốn đưa ra các yêu cầu về chức năng trong bối cảnh có giới hạn, bạn giao tiếp với các ranh giới rõ ràng của nó bằng cách sử dụng các mô hình. Trong cuốn sách của mình, Evans sử dụng một định nghĩa tương tự của các tế bào, nơi mà "[c]ells (tế bào) có thể tồn tại bởi vì màng của chúng xác định những gì ra/vào và xác định những gì có thể đi qua."

Hãy quay lại một chút với công việc kinh doanh của MusicCorp. Lĩnh vực của chúng tôi là toàn bộ hoạt động kinh doanh mà chúng tôi có. Nó bao gồm tất cả mọi thứ từ nhà kho đến bàn tiếp tân, từ tài chính đến đặt hàng. Chúng tôi có thể hoặc không thể mô hình hóa tất cả những điều đó trong phần mềm của mình, nhưng đó vẫn là thứ mà chúng tôi đang điều hành. Chúng ta hãy nghĩ về các phần của lĩnh vực đó trông giống như bối cảnh có giới hạn mà Evans đề cập đến. Tại MusicCorp, kho hàng của chúng tôi là một tổ hợp nhiều hoạt động — quản lý các đơn hàng được chuyển đi (và trả lại), nhận hàng mới, tổ chức các cuộc đua xe nâng, v.v. Ở những nơi khác, bộ phận tài chính có lẽ ít thú vị hơn, nhưng vẫn có một chức năng rất quan trọng trong tổ chức của chúng tôi. Những nhân viên này quản lý bảng lương, giữ các tài khoản của công ty và đưa ra các báo cáo quan trọng. Rất nhiều báo cáo. Chúng có lẽ cũng có những món đồ chơi trên bàn thú vị.

Các mô hình được chia sẻ và mô hình ẩn

Đối với MusicCorp, chúng ta có thể coi bộ phận tài chính và kho hàng là hai bối cảnh có giới hạn riêng biệt. Cả hai đều có giao diện rõ ràng với thế giới bên ngoài (về báo cáo hàng tồn kho, phiếu thanh toán, v.v.) và chúng có thông tin chi tiết mà chỉ họ cần biết (xe nâng, máy tính).

Giờ đây, bộ phận tài chính không cần biết về hoạt động chi tiết bên trong của nhà kho. Tuy nhiên, nó cần phải biết một số điều — ví dụ như nó cần biết về lượng hàng tồn kho để giữ cho các tài khoản được cập nhật. Hình 3-1 cho thấy một ví dụ về sơ đồ bối cảnh (context diagram). Chúng tôi thấy các khái niệm nội bộ của nhà kho, như Người chọn (người chọn đơn hàng), giá đang chứa hàng hóa, v.v. Tương tự như vậy, sổ cái tổng của công ty là không thể thiếu đối với tài chính nhưng không được chia sẻ ra bên ngoài ở đây.

Hình 3-1. Mô hình chia sẻ giữa bộ phận tài chính và kho hàng

Tuy nhiên, để có thể xác định giá trị của công ty, các nhân viên tài chính cần thông tin về cổ phiếu mà chúng tôi nắm giữ. Mặt hàng tồn kho sau đó trở thành một mô hình được chia sẻ giữa hai bối cảnh. Tuy nhiên, lưu ý rằng chúng ta không cần phải tiết lộ mọi thứ về mặt hàng trong kho từ bối cảnh kho hàng một cách mù quáng. Ví dụ: mặc dù nội bộ chúng tôi lưu giữ hồ sơ về một mặt hàng trong kho về nơi nó sẽ được đặt trong nhà kho, nhưng mặt hàng đó không cần phải được tiết lộ thông tin đó trong mô hình dùng chung. Vì vậy, sẽ có sự phân biệt giữa đại diện chỉ bên trong và đại diện bên ngoài mà chúng tôi đưa ra. Theo nhiều cách, điều này báo trước về cuộc thảo luận xung quanh REST trong Chương 4.

Đôi khi chúng ta có thể bắt gặp các mô hình có cùng tên nhưng có ý nghĩa rất khác nhau trong các bối cảnh khác nhau. Ví dụ: chúng ta có thể có khái niệm trả lại, đại diện cho việc khách hàng gửi lại thứ gì đó. Trong bối cảnh của khách hàng, trả lại là tất cả những gì liên quan đến việc in nhãn vận chuyển, gửi một gói hàng và chờ hoàn lại tiền. Đối với nhà kho, điều này có thể đại diện cho một gói hàng sắp được chuyển đến và một mặt hàng trong kho cần được bổ sung. Sau đó, trong kho chúng tôi lưu trữ thông tin bổ sung liên quan đến việc trả lại liên quan đến các nhiệm vụ sẽ được thực hiện; ví dụ: chúng tôi có thể tạo một yêu cầu khôi phục lại. Kết quả của mô hình chia sẻ là các quy trình khác nhau sẽ trở nên liên kết và hỗ trợ các thực thể trong mỗi bối cảnh có giới hạn, nhưng đó là mối quan tâm nội bộ trong chính bối cảnh đó.

Mô-đun và Dịch vụ

Bằng cách suy nghĩ rõ ràng về những mô hình nào nên được chia sẻ và không chia sẻ các đại diện nội bộ của chúng tôi, chúng tôi tránh được một trong những cạm bẫy tiềm ẩn có thể dẫn đến kết hợp chặt chẽ (ngược lại với những gì chúng tôi muốn). Chúng tôi cũng đã xác định một ranh giới trong lĩnh vực của chúng tôi, nơi tất cả các khả năng kinh doanh có cùng chí hướng sẽ tồn tại, mang lại cho chúng tôi sự gắn kết cao mà chúng tôi mong muốn. Những bối cảnh có giới hạn này, sau đó, tự cho mình là những ranh giới sáng tác cực kỳ tốt.

Như chúng ta đã thảo luận trong Chương 1, chúng ta có tùy chọn sử dụng các mô-đun trong một ranh giới quy trình để giữ các đoạn mã nguồn liên quan lại với nhau và cố gắng giảm sự ghép nối với các mô-đun khác trong hệ thống. Khi bạn bắt đầu trên một mã nguồn cơ sở mới, đây có là một khởi đầu tốt. Vì vậy, khi bạn đã tìm thấy các bối cảnh trong lĩnh vực của mình, hãy đảm bảo rằng chúng được mô hình hóa trong mã nguồn cơ sở của bạn dưới dạng mô-đun, với các mô hình được chia sẻ và ẩn.

Các ranh giới mô-đun này sau đó trở thành ứng viên xuất sắc cho các microservice. Nói chung, microservices cần phù hợp trong bối cảnh nhất định. Một khi bạn đã trở nên rất thành thạo, bạn có thể quyết định bỏ qua bước giữ cho bối cảnh có giới hạn được sử dụng như một mô-đun trong một hệ thống monolithic hơn và chuyển thẳng sang tạo ra một dịch vụ riêng biệt. Tuy nhiên, khi bắt đầu, hãy giữ một hệ thống mới ở khía cạnh gần giống monolithic hơn; việc sai lầm trong việc nhìn nhận ranh giới của các dịch vụ có thể gây hậu quả tốn kém, vì vậy hãy chờ đợi mọi thứ ổn định cho đến khi khi bạn nắm bắt được lĩnh vực mới, đó một là điều hợp lý. Chúng ta sẽ thảo luận thêm về vấn đề này trong Chương 5, cùng với các kỹ thuật giúp tách các hệ thống hiện có thành các microservice.

Vì vậy, nếu các ranh giới dịch vụ của chúng tôi phù hợp với các bối cảnh được giới hạn trong lĩnh vực của chúng tôi và microservices của chúng tôi đại diện cho các bối cảnh, chúng tôi đã có một khởi đầu tuyệt vời trong việc đảm bảo rằng các microservice của chúng tôi được liên kết lỏng lẻo và gắn kết chặt chẽ.

Phân rã sớm

Tại ThoughtWorks, bản thân chúng tôi đã trải qua những thách thức khi cố gắng phân chia các microservice quá nhanh. Bên cạnh việc tư vấn, chúng tôi cũng tạo ra một vài sản phẩm. Một trong số đó là SnapCI, một công cụ tích hợp liên tục (Continuous Integration) được cài đặt và phân phối liên tục (Continuous Delivery – Sau đây cũng viết là Continuous Delivery hoặc CD) (chúng ta sẽ thảo luận về các khái niệm đó sau trong Chương 6). Trước đây, nhóm đã làm việc trên một công cụ tương tự khác, Go-CD, một công cụ Continuous Delivery mã nguồn mở hiện có thể được deploy cục bộ thay vì được cài đạt trên nền tảng điện toán đám mây.

Mặc dù đã có một số mã nguồn được sử dụng lại từ rất sớm giữa các dự án SnapCI và Go-CD, nhưng cuối cùng SnapCI lại trở thành một mã nguồn cơ sở hoàn toàn mới. Tuy nhiên, kinh nghiệm trước đây của nhóm trong lĩnh vực công cụ CD khuyến khích họ tiến nhanh hơn trong việc xác định ranh giới và xây dựng hệ thống của họ như một tập hợp của các microservice.

Tuy nhiên, sau một vài tháng, rõ ràng là các trường hợp sử dụng của SnapCI đã khác nhau một cách tinh tế đến mức việc tiếp nhận các ranh giới dịch vụ ban đầu là không hoàn toàn đúng. Điều này dẫn đến nhiều thay đổi được thực hiện trên các dịch vụ và tất nhiên chi phí cho sự thay đổi cùng gia tăng. Cuối cùng, nhóm đã hợp nhất các dịch vụ trở lại thành một hệ thống monolithic, cho họ thời gian để hiểu rõ hơn về ranh giới nên tồn tại. Một năm sau, nhóm nghiên cứu đã có thể tách hệ thống monolithic thành các microservices, có ranh giới ổn định hơn nhiều. Đây không phải là ví dụ duy nhất về tình huống này mà tôi đã thấy. Việc phân ra sớm một hệ thống thành microservices có thể tốn kém, đặc biệt nếu bạn là người mới tham gia vào lĩnh vực. Theo nhiều cách, việc có một codebase tồn tại mà bạn muốn phân rã thành microservice dễ dàng hơn nhiều so với việc cố gắng xây dựng microservice ngay từ đầu.

Năng lực liên quan đến công việc kinh doanh

Khi bạn bắt đầu nghĩ về các bối cảnh và của chúng giới hạn tồn tại trong tổ chức của mình, bạn không nên nghĩ theo cách dữ liệu được chia sẻ, mà là về khả năng mà các bối cảnh đó cung cấp cho phần còn lại của lĩnh vực. Ví dụ, nhà kho có thể cung cấp khả năng có được danh sách hàng tồn kho hiện tại hoặc bối cảnh tài chính có thể hiển thị các tài khoản cuối tháng hoặc cho phép bạn thiết lập bảng lương cho một đợt tuyển dụng mới. Những khả năng này có thể yêu cầu trao đổi thông tin — các mô hình được chia sẻ — nhưng tôi đã thấy một cách quá thường xuyên việc suy nghĩ về dữ liệu dẫn đến các dịch vụ không có hoạt động gì liên quan đến việc hoạt động của công ty, và chỉ dựa trên các CRUD (tạo, đọc, cập nhật, xóa). Vì vậy, trước tiên hãy đặt hỏi "Bối cảnh này làm gì?", Sau đó là "Vậy nó cần dữ liệu gì để làm điều đó?"

Khi được mô hình hóa dưới dạng dịch vụ, các khả năng này trở thành các hoạt động chính sẽ được hiển thị qua một đường dây với các thành phần khác

Một vấn đề lặp lại vô tận

Nguyên văn: Turtles All the Way Down là một câu thể hiện một vấn đề lặp lại một cách vô tận. https://en.wikipedia.org/wiki/Turtles_all_the_way_down

Khi bắt đầu, bạn có thể sẽ xác định được các bối cảnh một cách chi tiết. Nhưng những bối cảnh này đến lượt nó có thể chứa những bối cảnh khác. Lấy ví dụ, bạn có thể phân chia bối cảnh của nhà kho thành các khả năng liên quan đến hoàn thành đơn đặt hàng, quản lý hàng tồn kho hoặc nhận hàng hóa. Khi xem xét ranh giới của các microservice, trước tiên hãy nghĩ đến các bối cảnh lớn hơn, ít chi tiết hơn, sau đó chia nhỏ theo các bối cảnh lồng nhau này khi bạn đang tìm kiếm lợi ích của việc tách các đường nối giữa chúng ra.

Tôi đã gặp các bối cảnh lồng nhau vẫn bị ẩn trong các bối cảnh khác, hãy kết hợp các microservice với nhau để tạo ra hiệu quả tuyệt vời. Đối với thế giới thực, họ vẫn đang sử dụng các năng lực mà nhà kho cung cấp, nhưng họ không biết rằng các yêu cầu của họ đang thực sự được ánh xạ một cách minh bạch tới hai hoặc nhiều dịch vụ riêng biệt, như bạn có thể thấy trong Hình 3-2. Đôi khi, bạn sẽ quyết định rằng sẽ hợp lý hơn khi bối cảnh giới hạn cấp cao hơn không được mô hình hóa một cách rõ ràng như một ranh giới dịch vụ, như trong Hình 3-3, vì vậy thay vì một ranh giới trong bối cảnh nhà kho duy nhất, thay vào đó bạn có thể chia nhỏ ra thành hàng tồn kho, thực hiện đơn đặt hàng, và nhận hàng hóa.

Hình 3-2. Microservices đại diện cho các bối cảnh được giới hạn lồng nhau ẩn bên trong nhà kho
Hình 3-3. Các bối cảnh giới hạn bên trong nhà kho được bật lên thành bối cảnh cấp cao nhất của riêng chúng

Nói chung, không có quy tắc nào quá nghiêm ngặt về cách tiếp cận nào phù hợp nhất. Tuy nhiên, việc bạn chọn cách tiếp cận lồng vào nhau hay tiếp cận theo cách tách biệt hoàn toàn phải dựa trên cơ cấu tổ chức của bạn. Nếu việc thực hiện đơn hàng, quản lý hàng tồn kho và nhận hàng được quản lý bởi các nhóm khác nhau, thì họ có thể nên được coi là microservice cấp cao nhất. Mặt khác, nếu tất cả chúng được quản lý bởi một nhóm, thì mô hình lồng nhau sẽ có ý nghĩa hơn. Điều này là do sự tác động lẫn nhau của cấu trúc tổ chức và kiến trúc phần mềm, mà chúng ta sẽ thảo luận ở phần cuối của cuốn sách trong Chương 10.

Một lý do khác để cách tiếp cận lồng nhau được ưa thích hơn có thể là chia nhỏ kiến trúc của bạn để đơn giản hóa việc kiểm thử. Ví dụ: khi kiểm thử các dịch vụ sử dụng dịch vụ kho hàng, tôi không phải phân tích từng dịch vụ bên trong bối cảnh của kho hàng, mà chỉ là nhưng API ít chi tiết hơn. Điều này cũng có thể cung cấp cho bạn một đơn vị cô lập khi xem xét các bài kiểm thử trên phạm vi lớn hơn. Ví dụ: tôi có thể quyết định thực hiện các kiểm thử từ đầu đến cuối trong đó tôi khởi chạy tất cả các dịch vụ bên trong bối cảnh kho hàng, nhưng đối với tất cả các service liên quan khác, tôi có thể bỏ qua chúng. Chúng ta sẽ khám phá thêm về kiểm thử và cách ly trong Chương 7.

Vấn đề giao tiếp trong các hoạt động của doanh nghiệp

Những thay đổi mà chúng tôi thực hiện đối với hệ thống của mình thường là những thay đổi mà doanh nghiệp muốn thực hiện về cách hệ thống hoạt động. Chúng tôi đang thay đổi chức năng — khả năng — được hiển thị cho khách hàng của chúng tôi. Nếu hệ thống của chúng tôi được phân tách theo các bối cảnh có giới hạn đại diện cho lĩnh vực của chúng tôi, thì những thay đổi chúng tôi muốn thực hiện có nhiều khả năng bị tách biệt trong một ranh giới microservice duy nhất. Điều này làm giảm số lượng điểm mà chúng tôi cần thực hiện thay đổi và cho phép chúng tôi deploy thay đổi đó một cách nhanh chóng.

Điều quan trọng nữa là phải nghĩ đến sự giao tiếp giữa các dịch vụ nhỏ này theo cùng một cách hiểu về hoạt động trong doanh nghiệp. Việc mô hình hóa phần mềm của bạn và sau đó là toàn bộ công việc kinh doanh không nên dừng lại ở ý tưởng về các bối cảnh có giới hạn. Các định nghĩa và ý tưởng giống nhau được chia sẻ giữa các bộ phận trong tổ chức của bạn phải được phản ánh trong các giao diện. Có thể hữu ích khi nghĩ về các biểu mẫu được gửi giữa các dịch vụ nhỏ này, giống như các biểu mẫu được trong cả tổ chức

Ranh giới về kỹ thuật

Việc xem xét những gì có thể xảy ra khi các dịch vụ được mô hình hóa không chính xác là việc làm hữu ích. Trước đây, tôi cùng một số đồng nghiệp đã làm việc với một khách hàng ở California, giúp công ty áp dụng một số phương pháp lập trình rõ ràng hơn và hướng tới tự động kiểm thử nhiều hơn. Chúng tôi đã bắt đầu với một số công việc đơn giản và có đã kết quả, chẳng hạn như phân tích dịch vụ, khi đó chúng tôi nhận thấy điều gì đó đáng lo ngại hơn nhiều. Tôi không thể đi quá chi tiết về những gì ứng dụng đã làm, nhưng đó là một ứng dụng công khai với lượng lớn khách hàng toàn cầu.

Đội ngũ và hệ thống đã ngày càng lớn mạnh. Ban đầu chỉ là tầm nhìn của một người, hệ thống đã sử dụng ngày càng nhiều tính năng và ngày càng có nhiều người dùng hơn. Cuối cùng, tổ chức quyết định nâng cao năng lực của nhóm bằng cách để một nhóm các developer mới có trụ sở tại Brazil đảm nhận một số công việc. Hệ thống được tách ra, với nửa phía trước của ứng dụng về cơ bản là stateless, deploy một trang web công khai, như trong Hình 3-4. Phần còn lại đơn giản là sử dụng kĩ thuật gọi thủ tục từ xa (RPC) trên một kho dữ liệu. Về cơ bản, hãy tưởng tượng bạn đã sử dụng một lớp kho lưu trữ (repository layer) trong mã nguồn cơ sở của mình và biến đây thành một dịch vụ riêng biệt.

Hình 3-4. Ranh giới dịch vụ được phân chia qua đường nối kỹ thuật

Các thay đổi thường xuyên phải được thực hiện cho cả hai dịch vụ. Cả hai dịch vụ đều nói chuyện với nhau qua các lệnh gọi phương thức kiểu RPC cấp thấp, mà kiểu kết nối này rất cứng nhắc nhưng dễ đứt gãy (chúng ta sẽ thảo luận về vấn đề này trong Chương 4). Giao diện dịch vụ cũng được sử dụng theo cách rất tùy tiện, dẫn đến vấn đề về hiệu suất. Điều này dẫn đến nhu cầu về các cơ chế xử lý RPC theo lô rất phức tạp. Tôi gọi đây là kiến trúc củ hành (onion architecture), vì nó có rất nhiều lớp và khiến tôi phải khóc khi phải cắt qua nó.

Bây giờ về mặt nổi của nó, ý tưởng tách hệ thống monolithic trước đây dưa trên các nhóm địa lý/tổ chức là hoàn toàn hợp lý, vì chúng tôi sẽ mở rộng trong Chương 10. Tuy nhiên, ở đây, thay vì thực hiện theo chiều dọc, tập trung vào các công việc của nghiệp vụ thông qua ngăn xếp, nhóm đã chọn những gì trước đây là đã được tạo ra thành API và tạo ra một lát cắt ngang.

Không phải lúc nào cũng đưa ra quyết định để lập mô hình ranh giới dịch vụ dọc theo các đường nối kỹ thuật cũng sai lầm. Tôi chắc chắn đã thấy điều này rất có ý nghĩa khi một tổ chức đang tìm cách đạt được các mục tiêu hiệu suất nhất định, chẳng hạn. Tuy nhiên, việc tìm kiếm các đường nối này chỉ là động lực phụ của bạn chứ không phải mục tiêu chính.

Tóm tắt

Trong chương này, bạn đã tìm hiểu một chút về điều gì tạo nên một dịch vụ tốt và cách tìm các đường nối trong không gian vấn đề của chúng tôi, mang lại cho chúng tôi lợi ích kép của cả khớp nối lỏng và tính liên kết cao. Các bối cảnh có giới hạn là một công cụ quan trọng giúp chúng ta tìm ra các đường nối này và bằng cách sắp xếp các microservice của chúng ta theo các ranh giới này, chúng ta cần đảm bảo rằng hệ thống cuối cùng có mọi cơ hội để giữ nguyên các tính năng đó. Chúng ta cũng đã có một gợi ý về cách chúng ta có thể chia nhỏ các microservice của mình hơn nữa, điều gì đó chúng ta sẽ khám phá sâu hơn sau. Và chúng ta cũng đã giới thiệu MusicCorp, lĩnh vực ví dụ mà chúng ta sẽ sử dụng trong suốt cuốn sách này.

Những ý tưởng được trình bày trong Thiết kế theo hướng lĩnh vực – DDD của Eric Evans rất hữu ích cho chúng ta trong việc tìm ra ranh giới hợp lý cho các dịch vụ và tôi mới chỉ sơ lược ở đây. Tôi giới thiệu cuốn sách Implementing Domain-Driven Design (Addison- Wesley) của Vaughn Vernon để giúp bạn hiểu tính thực tiễn của phương pháp này.

Mặc dù chương này chủ yếu là những thứ mang tính tổng quát, nhưng chúng ta cần đi sâu vào các kỹ thuật hơn trong các chương tiếp theo. Có rất nhiều cạm bẫy liên quan đến việc deploy giao diện giữa các dịch vụ, mà chúng có thể dẫn đến tất cả các loại rắc rối và chúng ta sẽ phải đi sâu vào chủ đề này nếu muốn giữ cho hệ thống của mình không trở thành một gã khổng lồ, rối rắm lộn xộn.

Series NavigationSách dịch: Building Microservices: Designing Fine-Grained Systems – Chương 2 Sự tiến hoá của kiến trúc phần mềm >>

Leave a Comment

* By using this form you agree with the storage and handling of your data by this website.

You may also like