Bài viết trước mình đã so sánh kiến trúc xây dựng và kiến trúc phần mềm, đến hẹn lại lên, với bài viết này mình sẽ đi sâu hơn về quá trình hình thành của các kiến trúc phần mềm dẫn tới sự ra đời của kiến trúc Microservice

Sự tiến hóa của kiến trúc phần mềm
Chắc hẳn bạn đã từng nghe đến những thông tin những cỗ máy tính đời đầu, nó chẳng có màn hình mà chỉ có những mảnh đục lỗ tượng trưng cho 0 và 1. Rồi nó phát triển lên một chút là những hệ điều hành đen sì mà bạn chỉ có thể gõ và giao tiếp với nó bằng câu lệnh. Khi này những phần mềm ứng dụng trên Terminal ra đời đánh dấu thời điểm khởi nguyên cho sự phát triển của phần mềm sau này.

Rồi con người thấy bất tiện khi công trình của họ nằm giữa đồng không mông quạnh, chẳng có cái cửa nào. Khi đó UI ra đời, những giao diện người dùng đầu tiên phát triển, chúng được giao tiếp với nhau qua những con đường thô sơ mang tên Request - Response. Bước tiến hóa này đánh dấu mốc son cho kiểu kiến trúc Client - Server Architecturera đời.

Câu chuyện đẹp đẽ là vậy, hạnh phúc là vậy khi server có thể xử lý và trả về đúng yêu cầu cho client, nhưng đời không như là mơ, khi trách nhiệm của server ngày càng cao, nghiệp vụ logic ngày càng nhiều, ứng dụng sẽ trở nên chậm dần, chậm dần,... Bạn không thể nào chờ cả tiếng đồng hồ để nhận được một phản hồi đặt bánh đúng không? Lại một giải pháp sinh ra từ thực tế khi chi nhỏ các tầng xử lý để có thể trả về những thứ cần, không xử lý những thứ không cần. Và N-Tier Architecture đã ra đời để giải quyết vấn đề này, nó giúp cho server của bạn chia nhỏ những trách nhiệm bạn cần xử lý, xử lý nó trước và trả về tức nhanh hơn, cải thiện được vấn đề nảy sinh ban đầu.


Cùng thời điểm này, một người anh em cùng cha khác ông nội cũng được ra đời. Khi N-Tier Architecture chia thành các tầng để xử lý theo mô hình trên - dưới thì một kiến trúc khác cũng tương tự là Onion Architecture thì xử lý theo mô hình từ ngoài vào trong. Kiến trúc này còn có tên gọi khác là Clean Architecture hay kiến trúc củ hành. Đơn giản là các lớp của 2 kiến trúc này được xếp lại từ trong ra ngoài giống như một củ hành vậy



Như bạn đã thấy 2 hình vẽ của mô hình N-Tier Architecture và Clean Architecture thì bạn cũng thấy sự giao tiếp giữa các lớp trong 2 mô hình. Sự khác nhau ở 2 kiến trúc này chính là hướng của dấu mũi tên. Sự phụ thuộc giữa các lớp của kiến trúc tăng lên khi N-Tier Architecture có 2 mũi tên 2 chiều, điều này bạn hiểu rằng khi một request được gọi xuống thì bạn phải đi xuyên qua từng lớp để lấy dữ liệu và quay trở lại xuyên qua từng lớp để hiển thị. Clean Architecture thì cải tiến hơn được một chút khi nó chỉ có 1 chiều mũi tên khi lớp các lớp được kiêm cả công việc gọi tới và trả về. Ví dụ lớp vỏ ngoài cùng thì kiêm cả việc giao tiếp với UI và DB. Điều này sẽ giảm bớt sự phụ thuộc và có thể tái sử dụng.
Tuy nhiên chỉ là giảm bớt mà thôi, sự phụ thuộc các lớp lẫn nhau vẫn xảy ra và bạn khó có thể thay thế các thành phần của nó trong cùng một lớp của củ hành. Khi này một kiến trúc khác sinh ra để giải quyết vấn đề phụ thuộc này. Đó là Hexagonal Architecture. Đối với kiến trúc này thì các cạnh của đa giác sẽ đóng một vai trò giao tiếp giữa các lớp riêng. Việc này sẽ giúp cho bạn thay thế các thành phần trong cùng một lớp sẽ dễ dàng hơn.


Như bạn đã thấy khi bắt đầu của sự tiến hóa các vấn đề được phát sinh và có những giải pháp để khắc phục. Khi công nghệ trở thành một con đường của cuộc sống thì chúng ta sẽ phải xử lý nhiều hơn những vấn đề hiện tại. Bằng cách này hay cách kia thì nó cũng giúp cho chũng ta phát triển. Đó là quy luật của sự tiến hóa. Rồi một ngày kia, dữ liệu càng ngày càng lớn, thì vấn đề nảy sinh đối với hiện tại và tương lai chính là khả năng mở rộng (scalability) và thời gian phản hồi (response time) được quan tâm. Dù ý tưởng nào từ thời điểm này tiến hóa đi chăng nữa thì bạn sẽ gặp đâu đó những điểm chung cho giải pháp quản lý dữ liệu với định lý này.
Định lý CAP (CAP Theorem) - Consistency, Availability, Partition Tolerance
In theoretical computer science, the CAP theorem, also named Brewer's theorem after computer scientist Eric Brewer, states that it is impossible for a distributed data store to simultaneously provide more than two out of the following three guarantees:
- Consistency: Every read receives the most recent write or an error
- Availability: Every request receives a (non-error) response, without the guarantee that it contains the most recent write
- Partition tolerance: The system continues to operate despite an arbitrary number of messages being dropped (or delayed) by the network between nodes


Đơn giản là hiện tại cũng như tương lại việc kiến trúc không còn là việc giao tiếp giữa các tầng với nhau nữa mà còn phải quan tâm đến việc quản lý dữ liệu của chúng. Thời đại bùng nổ thông tin thì việc quản lý cần đảm bảo các giá trị cốt lõi của nó mà định lý CAP đã nêu trên.
Đến đây vấn đề quản lý dữ liệu bắt đầu trở thành chủ đề mà các công trình sư quan tâm hàng đầu rồi. Khi này khi nhiều người dùng cùng truy cập và cố gắng lấy và thêm dữ liệu sao cho nhanh nhất và đồng bộ nhất. Kết hợp với ý tưởng Hexagonal Architecture bên trên thì một trong những kiến trúc mà giúp để phân tách hoàn toàn quá trình đọc và quá trình ghi dữ liệu để đảm bảo sự độc lập của chúng. Đó chính là CQRS - Command Query Responsibility Segregation


Việc chia nhiệm vụ của quá trình đọc và ghi dữ liệu độc lập giúp cho quá trình phản hồi diễn ra nhanh hơn, bạn sẽ không phải chờ hiển thị danh sách bánh khi có một người khác đang đặt bánh vào hệ thống. Chưa kể là khi một quá trình này xảy ra sự cố thì quá trình kia không bị ảnh hưởng.


Khi vấn đề dữ liệu và response time được xử lý ổn thỏa, các công trình sư thông thái lại đi sang hướng Partition. Vấn đề chia để trị là một vấn đề có từ xa xưa, mình đã có một bài viết riêng về vấn đền này. Bạn đọc có thể xem lại tại đây
Với ý tưởng chia để trị vấn đề tách nhỏ còn giúp cho hệ thống dễ dàng phát triển, dễ dàng tương thích khi có thay đổi, dễ dàng mở rộng, và dễ dàng kiểm thử cũng như deploy phát hành.
Tại thời điểm hoang sơ đến bây giờ, chúng ta vẫn có một khối thống nhất, tuy rằng chia thành nhiều tầng và nhiều lớp với các nhiệm vụ khác nhau. Điều này có một tên gọi chung tại thời điểm hiện tại, đó chính là Monolithic Architecture. Việc phát triển kiến trúc này vẫn đảm bảo định lý CAP và CQRS. Thật chẳng có gì để nói khi chúng ta chỉ biết chấp nhận điều hiện tại. Vấn đề sẽ được phát sinh trong quá trình phát triển ứng dụng Monolithic như: Phức tạp (Complexity), Phát triển chậm (Slow development), Phát hành một phiên bản mới khó khăn (Commit to deployment), Khó mở rộng (Difficulty in scaling), Độ tin cậy thấp và tốn quá nhiều công sức trong quá trình kiểm thử (Reliability) và Lỗi thời (Obsolete)
Vấn đề chồng chất vấn đề, khó khăn chồng chất khó khăn, và các nhà thông thái đã giải quyết các vấn đề trên bằng SOA - Service-oriented Architecture. Kiến trúc này khắc phục gần như các nhược điểm nêu trên. Điều này đã giúp chúng ta có thể có nhứng ứng dụng tuyệt vời với thời kỳ 3.0

Nhưng chưa phải dừng lại ở đó, khi cloud xuất hiện những nhà thông thái lại có những phát minh bước ngoặt đáng để chúng ta coi nó là sự tiến hóa vượt bậc.
Từ việc chia nhỏ các service, các tầng mỗi service như kiến trúc SOA đã đưa ra giải pháp thì các kiến trúc sư đã đi thêm một bước nữa là chia mỗi service thành một endpoint hay server riêng để có thể đưa chúng lên mây. Microservice Architecture (MSA) ra đời dựa trên ý tưởng này.

Vậy là các service từ độc lập về mặt Logical giờ đây nó lại độc lập cả Physical nữa rồi. Thật sự thú vị đúng không?
Tất nhiên quá trình tiến hóa chưa dừng ở đây, và đây mới là thời điểm khởi đầu cho kỷ nguyên số với lượng thông tin ngày một bùng nổ.
Chúng ta hãy cùng chờ đón xem có những kiến trúc nào phát triển tiếp theo trong tương lai nhé!