Hiện đại hóa hệ thống kế thừa dựa trên mẫu Strangler Fig
1. Tổng quan
Định nghĩa: Mẫu Strangler Fig (cây sung bóp cổ) là chiến lược hiện đại hóa trong đó, thay vì loại bỏ và viết lại toàn bộ hệ thống kế thừa (legacy) cùng một lúc, ta đặt một lớp trung gian ở bên ngoài, chuyển dần các chức năng nghiệp vụ sang hệ thống mới theo từng đơn vị nhỏ, rồi loại bỏ từng bước những phần legacy đã chuyển xong.
Các hệ thống thông tin quy mô lớn tích lũy quy tắc nghiệp vụ, dữ liệu, batch, liên kết bên ngoài và quy trình vận hành trong thời gian dài, nên chỉ dịch mã nguồn sang ngôn ngữ mới thì không thể coi là đã hiện đại hóa. Trong các chức năng đang chạy có lẫn những quy tắc và ngoại lệ không được tài liệu hóa, nhiều phòng ban dùng chung một cơ sở dữ liệu và giao diện, và ngay cả các thao tác xử lý thủ công khi xảy ra sự cố cũng đã trở thành một phần của quy trình nghiệp vụ. Vì vậy, viết lại toàn bộ tuy trông hấp dẫn để áp dụng công nghệ mới, nhưng tiềm ẩn rủi ro lớn là bỏ sót yêu cầu ẩn hoặc buộc phải dừng cải tiến nghiệp vụ hiện có trong suốt thời gian chuyển đổi kéo dài.
Tên gọi Strangler Fig bắt nguồn từ cách sinh trưởng của cây sung bóp cổ, loài cây mọc bao quanh cây chủ. Trong phần mềm, ta không "giết" hệ thống cũ ngay lập tức mà bắt đầu chức năng mới ở rìa của hệ thống cũ, và mỗi khi một chức năng được kiểm chứng thì mở rộng phạm vi của phần triển khai mới. Ban đầu người dùng và các hệ thống bên ngoài vẫn dùng cùng một giao diện, còn lớp định tuyến sẽ chọn gửi yêu cầu đến legacy hoặc hệ thống mới. Cuối cùng, khi mọi chức năng nghiệp vụ và dữ liệu đã được chuyển và các phụ thuộc vào legacy đã bị loại bỏ, ta dọn dẹp cả lớp trung gian lẫn hệ thống legacy.
Bản chất của mẫu này nằm ở "kỹ thuật làm cho đơn vị thay đổi trở nên nhỏ mà không làm gián đoạn nghiệp vụ" hơn là "kỹ thuật xây dựng hệ thống mới". Mỗi bước phải được triển khai và quan sát một cách độc lập, đồng thời phải có đường quay lui cho những lần chuyển đổi sai. Tiến độ hiện đại hóa cũng nên được đo bằng năng lực nghiệp vụ đã chuyển, độ ổn định, giá trị cho người dùng và mức giảm phụ thuộc vào legacy, chứ không phải bằng số dòng mã.
1.1 Bối cảnh ra đời và sự cần thiết
Thứ nhất, hệ thống legacy vừa là đối tượng cần thay thế vừa là nền tảng vận hành cốt lõi của nghiệp vụ. Vì không thể dừng hệ thống hiện có cho đến khi hệ thống thay thế hoàn thành, cách làm chốt toàn bộ yêu cầu rồi vài năm sau chuyển đổi một lần không phù hợp với sự thay đổi nghiệp vụ hiện tại. Cách tiếp cận tuần tự cho phép cải tiến các chức năng có độ ưu tiên cao trước trong khi hệ thống hiện có vẫn tiếp tục phục vụ.
Thứ hai, rất khó nắm bắt đầy đủ hành vi thực tế của hệ thống legacy. Chỉ dựa vào mã nguồn và tài liệu thiết kế thì khó phát hiện các giá trị đặc biệt trong dữ liệu vận hành, các liên kết không chính thức với cơ quan bên ngoài hay các thủ tục hiệu chỉnh do nhân viên nghiệp vụ thực hiện. Khi đưa một chức năng nhỏ vào luồng nghiệp vụ thực tế, đội ngũ có thể học được các quy tắc ẩn trong quá trình chuyển đổi và điều chỉnh kế hoạch chuyển đổi tiếp theo.
Thứ ba, cần xác nhận đầu tư và kết quả theo từng giai đoạn. Viết lại toàn bộ đòi hỏi bỏ ra nhiều chi phí trước và chỉ đến cuối mới biết thành bại, còn Strangler Fig tạo ra kết quả chạy được ở mỗi bước. Nhờ đó ban lãnh đạo có thể định kỳ đánh giá sự thay đổi về rủi ro, chi phí, giá trị cho người dùng và lựa chọn tiếp tục, dừng lại hay chuyển hướng.
1.2 Mục tiêu và nguyên tắc thiết kế
Mục tiêu thứ nhất của Strangler Fig là chuyển đổi không gián đoạn hoặc gián đoạn thấp. Vì phải thay đổi phần triển khai bên trong trong khi vẫn giữ các hợp đồng và trải nghiệm người dùng hiện có, ta tách biệt giao diện bên ngoài với ranh giới dịch vụ bên trong.
Mục tiêu thứ hai là khả năng đảo ngược theo từng chức năng. Phải có khả năng hoàn nguyên định tuyến để sự cố của chức năng mới không lan ra toàn bộ dịch vụ, và các thay đổi dữ liệu phải có thủ tục khôi phục và xử lý lại.
Mục tiêu thứ ba là làm rõ ranh giới. Xác định đơn vị chuyển đổi dựa trên năng lực nghiệp vụ, quyền sở hữu dữ liệu và phạm vi giao dịch, đồng thời đặt ranh giới chuyển đổi để hệ thống mới không kéo theo nguyên vẹn cấu trúc dữ liệu và thuật ngữ của legacy.
Mục tiêu thứ tư là loại bỏ hoàn toàn legacy. Nếu để lớp trung gian trở thành độ phức tạp vĩnh viễn, hệ thống sẽ biến thành một khối monolith mới kết hợp giữa legacy và hệ thống mới. Vì vậy ngay từ đầu cần định nghĩa điều kiện hoàn thành, thời điểm loại bỏ, người phụ trách và ngân sách, đồng thời gán điều kiện hết hạn cho các adapter và quy tắc định tuyến tạm thời.
2. Cấu trúc và các thành phần cốt lõi
Mẫu Strangler Fig không chỉ là việc thêm một proxy. Nó bao gồm đồng thời lớp định tuyến giữa client và hệ thống, các dịch vụ cung cấp chức năng mới, lớp chuyển đổi giữa legacy và hệ thống mới, hệ thống đồng bộ và kiểm chứng dữ liệu, cùng các chức năng quan sát và kiểm soát chuyển đổi.
flowchart LR
U[Người dùng·Hệ thống bên ngoài] --> F[Facade / API Gateway]
F --> R{Định tuyến theo chức năng}
R --> L[Ứng dụng legacy]
R --> N[Dịch vụ·Mô-đun mới]
N --> ACL[Anti-corruption Layer]
ACL --> L
L --> DBL[(DB legacy)]
N --> DBN[(DB miền)]
DBL <-->|CDC·Đồng bộ·Kiểm chứng| DBN
F --> O[Log·Chỉ số·Truy vết]
N --> O
L --> O
O --> G[Cổng chuyển đổi·Quyết định rollback]
2.1 Lớp mặt tiền hoặc lớp định tuyến (Facade)
Facade tách biệt điểm tiếp xúc mà client hiện có nhìn thấy với vị trí của phần triển khai bên trong. Ban đầu phần lớn yêu cầu được chuyển tới legacy, chỉ những yêu cầu thuộc chức năng đã chuyển xong mới được gửi sang dịch vụ mới. Nhờ vậy có thể dịch chuyển quyền sở hữu chức năng bên trong mà client không cần đổi địa chỉ gọi.
Tiêu chí định tuyến không chỉ giới hạn ở URL. Có thể kết hợp chức năng, phiên bản, tenant, khu vực, nhóm người dùng, tỷ lệ lưu lượng và feature flag; các thay đổi rủi ro cao bắt đầu từ nhân viên nội bộ hoặc một phần lưu lượng. Tuy nhiên, nếu quy tắc định tuyến lẫn với quy tắc nghiệp vụ thì facade sẽ trở thành một hệ thống khổng lồ mới, nên phải tách trách nhiệm định tuyến kỹ thuật với phán định nghiệp vụ.
Facade dễ trở thành điểm lỗi đơn và nút thắt cổ chai. Cần mở rộng ngang ở dạng không trạng thái (stateless), quản lý phiên bản triển khai quy tắc và cách vô hiệu hóa cache, đồng thời định nghĩa đường mặc định an toàn khi bản thân facade gặp sự cố. Mọi quyết định định tuyến cần ghi log phiên bản đích, phiên bản quy tắc và phạm vi ảnh hưởng người dùng để khi có sự cố có thể tái hiện yêu cầu nào đã đi tới hệ thống nào.
2.2 Dịch vụ mới và lát cắt chức năng
Đơn vị chuyển đổi nên được cắt theo năng lực nghiệp vụ chứ không phải theo tầng kỹ thuật. Ví dụ, trong hệ thống đặt hàng, thay vì chuyển cùng lúc màn hình, controller, service và bảng, hãy định nghĩa một luồng mà người dùng hiểu được như "thay đổi địa chỉ giao hàng" hay "tra cứu trạng thái đơn hàng" thành một lát cắt. Lát cắt chức năng bao gồm đồng thời hợp đồng đầu vào, hợp đồng đầu ra, quyền sở hữu dữ liệu, xử lý lỗi và chỉ số vận hành.
Không nhất thiết phải chia mọi miền thành microservice ngay từ đầu. Phần triển khai mới có thể là modular monolith hoặc các dịch vụ độc lập theo chức năng. Tiêu chí quan trọng là ranh giới triển khai và sở hữu có rõ ràng hay không, và có cản trở đơn vị chuyển đổi tiếp theo hay không.
2.3 Lớp chống hư hại (Anti-corruption Layer)
Legacy và hệ thống mới có thể dùng cùng một từ nhưng khác nhau về ý nghĩa và định dạng dữ liệu.
Legacy có thể lưu hang_khach_hang=3 còn hệ thống mới dùng kiểu liệt kê tường minh SILVER, và một trạng thái đơn hàng của legacy có thể được tách thành nhiều trạng thái trong hệ thống mới.
Lớp chống hư hại chuyển đổi những khác biệt này để cấu trúc dữ liệu, mã lỗi và thói quen giao dịch của legacy không làm "ô nhiễm" mô hình của hệ thống mới.
Lớp này vượt ra ngoài ánh xạ DTO đơn thuần, bao gồm chuyển đổi hợp đồng, chuyển đổi đơn vị và múi giờ, chuyển đổi ý nghĩa lỗi, retry và timeout, xử lý tính lũy đẳng (idempotency). Quy tắc chuyển đổi được quản lý bằng mã có thể kiểm thử và hợp đồng có phiên bản, đồng thời dùng kiểm tra tĩnh để phát hiện thuật ngữ legacy có bị dùng trực tiếp bên trong hệ thống mới hay không.
2.4 Kho dữ liệu và đồng bộ
Dù đã chuyển chức năng ứng dụng, nếu dữ liệu vẫn nằm ở cơ sở dữ liệu legacy trung tâm thì sự ràng buộc của hệ thống vẫn tiếp diễn. Tuy nhiên, nếu tách cơ sở dữ liệu ngay từ đầu thì vấn đề đồng bộ và nhất quán sẽ tăng vọt, nên cần dịch chuyển trách nhiệm đọc và ghi theo từng giai đoạn.
Ở giai đoạn đầu, dịch vụ mới có thể đọc bảng legacy, nhưng phải giới hạn thời gian mã mới phụ thuộc trực tiếp vào lược đồ legacy. Ở giai đoạn tiếp theo, sao chép dữ liệu miền sang kho mới và kiểm chứng số bản ghi, tổng, hash và các bất biến nghiệp vụ giữa dữ liệu nguồn và dữ liệu sao chép. Khi kiểm chứng xong, chỉ định kho mới làm hệ thống ghi nhận gốc (system of record) và chỉ cung cấp cho legacy phần dữ liệu tương thích cần thiết.
| Thành phần | Trách nhiệm chính | Kiểm soát cốt lõi |
|---|---|---|
| Facade·Gateway | Phân phối yêu cầu tới legacy và hệ thống mới | Phiên bản quy tắc, đường vòng khi sự cố, kiểm soát truy cập |
| Lát cắt chức năng mới | Thực thi năng lực nghiệp vụ đã chuyển | Kiểm thử hợp đồng, feature flag, triển khai độc lập |
| Lớp chống hư hại | Chuyển đổi mô hình, hợp đồng, ý nghĩa lỗi | Phiên bản ánh xạ, kiểm thử chuyển đổi, lũy đẳng |
| Pipeline đồng bộ | Truyền dữ liệu giữa kho nguồn và kho mới | CDC, xử lý lại, kiểm soát thứ tự·trùng lặp |
| Lớp quan sát | Đo kết quả chuyển đổi và rủi ro vận hành | Truy vết phân tán, SLO, so sánh theo chức năng |
| Kế hoạch loại bỏ | Chấm dứt phụ thuộc vào legacy | Xác nhận mức sử dụng bằng 0, phê duyệt lưu giữ·hủy bỏ |
Các hạng mục trong bảng không phải danh sách sản phẩm độc lập mà cùng tạo nên một mặt phẳng kiểm soát chuyển đổi. Ví dụ, nếu định tuyến đã chuyển sang dịch vụ mới mà không đo độ trễ đồng bộ dữ liệu thì người dùng có thể nhận được kết quả tra cứu đã cũ. Ngược lại, dù dữ liệu đã được tách trước, nếu quy tắc chuyển đổi của facade chưa sẵn sàng thì không thể đưa kết quả của kho mới vào nghiệp vụ thực tế. Vì vậy, với từng chức năng cần đánh giá đồng thời mức sẵn sàng của định tuyến, chuyển đổi, dữ liệu và khả năng quan sát.
3. Quy trình chuyển đổi tuần tự
3.1 Xác định mục tiêu và chẩn đoán hiện trạng
Trước khi hiện đại hóa, cần định nghĩa sẽ cải thiện kết quả nghiệp vụ nào, chứ không phải "sẽ thay đổi công nghệ". Xác định thứ tự ưu tiên giữa thời gian phản hồi, chu kỳ phát hành, thời gian khôi phục sự cố, đáp ứng quy định, chi phí vận hành, khả năng mở rộng, và thiết lập đường cơ sở có thể định lượng.
Không chỉ ước đoán quan hệ gọi và luồng dữ liệu của legacy bằng phân tích tĩnh, mà cần bổ sung bằng log, trace, lịch sử batch thực tế và phỏng vấn người phụ trách. Đánh giá đồng thời mức sử dụng theo chức năng, ảnh hưởng đến doanh thu và quy định, độ khó thay đổi, mức độ ràng buộc và độ nhạy cảm của dữ liệu sẽ giúp xác định thứ tự ưu tiên của các ứng viên chuyển đổi.
3.2 Xác định ranh giới và chọn lát cắt đầu tiên
Đối tượng chuyển đổi đầu tiên nên là chức năng có hiệu quả học hỏi cao và phạm vi thất bại hạn chế, thay vì chức năng phức tạp nhất. Chọn chức năng có giá trị nghiệp vụ rõ ràng, có thể quan sát được ranh giới gọi và có thể giải thích được quyền sở hữu dữ liệu. Những lĩnh vực có chi phí thất bại lớn như giao dịch nguyên tử của thanh toán cốt lõi chỉ nên xử lý sau khi đã có đủ hàng rào bảo vệ (guardrail).
Khi chọn chức năng, tiêu chí "một màn hình" là không đủ. Cần xác nhận xem kiểm tra đầu vào, phân quyền, thay đổi dữ liệu, sự kiện bất đồng bộ, thông báo, log kiểm toán và xử lý batch tiếp theo có nằm trong cùng một năng lực nghiệp vụ hay không. Nếu ranh giới sai, một chức năng sẽ gọi đi gọi lại cả hai hệ thống, và rốt cuộc sinh ra giao dịch phân tán còn phức tạp hơn trước.
3.3 Đưa vào facade và hợp đồng
Lắp đặt facade giữa client và legacy, nhưng ban đầu chuyển mọi yêu cầu tới legacy để kiểm chứng hành vi không thay đổi. Giai đoạn này không phải chuyển chức năng mà là xây nền tảng cho khả năng quan sát và kiểm soát. So sánh lược đồ yêu cầu/phản hồi, chủ thể xác thực, độ trễ, tỷ lệ lỗi, số lần retry với đường cơ sở.
Tiếp theo, định nghĩa hợp đồng của dịch vụ mới. Hợp đồng không chỉ là danh sách trường JSON mà còn bao gồm ý nghĩa trường, tính bắt buộc, đơn vị, sắp xếp và phân trang, mã lỗi, tính lũy đẳng và quy tắc che (masking) thông tin cá nhân. Thông qua kiểm thử hợp đồng hướng người tiêu dùng (consumer-driven contract test) và kiểm tra tương thích, bảo đảm việc triển khai của một bên không làm hỏng lời gọi của bên kia.
3.4 Triển khai chức năng và kiểm chứng song song
Chức năng mới sử dụng dữ liệu và dịch vụ legacy cần thiết thông qua adapter, nhưng không sao chép nguyên các lời gọi nội bộ của legacy. Khi triển khai xong, dùng lưu lượng bóng (shadow traffic) hoặc so sánh đọc để đối chiếu kết quả mới với kết quả legacy trước khi hiển thị cho người dùng. Không được đánh giá chỉ bằng khớp chuỗi tuyệt đối, mà phải phân biệt xem có tương đương về nghiệp vụ không và có phải là sai khác làm tròn hay sắp xếp có thể chấp nhận hay không.
Chức năng ghi rủi ro hơn chức năng đọc. Ban đầu có thể để dịch vụ mới chỉ thực hiện kiểm tra và tính toán còn legacy đảm nhiệm ghi thực tế, hoặc dùng ghi kép (dual write) nhưng phải xử lý trùng lặp và đảo thứ tự. Ghi kép có tiêu chí thành công là cả hai hệ thống đều đã ghi, nên nếu không thiết kế tác vụ bù trừ và hàng đợi vận hành cho thất bại cục bộ thì nợ nhất quán sẽ tích lũy.
3.5 Chuyển lưu lượng và ổn định
Chuyển đổi không phải là một lần bật công tắc mà là mở rộng theo từng giai đoạn. Có thể mở rộng theo thứ tự người dùng nội bộ, tenant thử nghiệm, lưu lượng nhỏ, khu vực cụ thể, toàn bộ lưu lượng, với thời gian quan sát giữa các giai đoạn. Mỗi giai đoạn có tiêu chí dừng về tỷ lệ lỗi, độ trễ, tỷ lệ thành công nghiệp vụ và tỷ lệ bất nhất dữ liệu có thể chấp nhận.
Feature flag hỗ trợ chuyển đổi và rollback nhanh, nhưng flag không hết hạn sẽ làm phức tạp mã và đường vận hành. Cần quản lý người sở hữu flag, ngày hết hạn, giá trị mặc định, quyền tắt khẩn cấp và log kiểm toán thay đổi, và nhất định phải gỡ bỏ sau khi chuyển đổi xong.
3.6 Loại bỏ legacy và kiểm chứng sau cùng
Không xóa ngay bảng và mã legacy chỉ vì hệ thống mới chạy bình thường. Cần xác nhận lượng gọi bằng 0 trong một khoảng thời gian nhất định, không còn batch, liên kết bên ngoài hay công cụ quản trị nào sót lại, và nghĩa vụ kiểm toán, lưu giữ đã được đáp ứng. Trước khi xóa, kiểm chứng khả năng khôi phục bản sao lưu và rollback, đồng thời cùng bộ phận pháp chế và bảo vệ dữ liệu cá nhân phân loại dữ liệu cần lưu giữ và dữ liệu cần hủy.
Sau khi loại bỏ, vẫn cần xác nhận người dùng và đội vận hành hiểu được các chỉ số của đường mới. Hoàn thành hiện đại hóa không phải là khoảnh khắc xóa mã, mà là trạng thái trong đó người chịu trách nhiệm, quy trình vận hành, ứng phó sự cố và kiểm soát bảo mật đã được chuyển sang hệ thống mới.
sequenceDiagram
participant C as Client
participant F as Facade/Bộ định tuyến
participant L as Legacy
participant N as Dịch vụ mới
participant D as Kiểm chứng dữ liệu
participant M as Giám sát
C->>F: Yêu cầu nghiệp vụ
F->>L: Đường mặc định ban đầu
L-->>F: Phản hồi hiện có
F-->>C: Phản hồi tương thích
F->>N: Lưu lượng bóng hoặc giới hạn
N->>L: Lời gọi phụ thuộc đã chuyển đổi
N->>D: So sánh kết quả·dữ liệu
D-->>M: Chỉ số bất nhất·chất lượng
F->>N: Mở rộng lưu lượng theo giai đoạn
N-->>F: Phản hồi mới
F-->>C: Phản hồi mới
M-->>F: Rollback khi vượt tiêu chí dừng
F->>L: Quay về đường legacy
4. Hiện đại hóa dữ liệu và thiết kế tính nhất quán
4.1 Rủi ro của cơ sở dữ liệu dùng chung
Khi nhiều dịch vụ trực tiếp đọc/ghi cùng một bảng, cấu trúc bảng trên thực tế trở thành một API công cộng. Nếu hệ thống mới sửa bảng legacy, các batch và báo cáo khác sẽ bị ảnh hưởng, và khó truy vết dịch vụ nào đã thay đổi giá trị. Vì vậy, trong quá trình chuyển đổi cần bao bọc dần việc truy cập bảng bằng API dịch vụ hoặc sự kiện, và quản lý danh sách truy cập trực tiếp cùng lịch loại bỏ.
Ngay cả khi không thể tách ngay cơ sở dữ liệu dùng chung, vẫn có thể xác định chủ sở hữu việc đọc và ghi. Nếu chỉ một hệ thống đảm nhận ghi cho một miền cụ thể còn các hệ thống khác truy cập qua sự kiện hoặc mô hình đọc, có thể thu hẹp nguyên nhân xung đột. Khi đó phải nêu rõ mục tiêu độ mới của dữ liệu và việc nghiệp vụ có chấp nhận bất nhất tạm thời hay không.
4.2 CDC và đồng bộ dựa trên sự kiện
Thu thập dữ liệu thay đổi (CDC - Change Data Capture) là cách đọc log cơ sở dữ liệu hoặc sự kiện thay đổi rồi chuyển tới kho mới. So với việc rải logic đồng bộ khắp mã ứng dụng, cách này có thể dễ giám sát thiếu sót và xử lý lại hơn, nhưng phải kiểm soát đồng thời việc lan truyền thao tác xóa, thay đổi lược đồ, thứ tự giao dịch và thông tin nhạy cảm.
Trong đồng bộ dựa trên sự kiện, ý nghĩa và lược đồ của sự kiện được quản lý phiên bản. Bên tiêu thụ phải áp dụng chỉ một lần ngay cả khi nhận sự kiện trùng lặp, và các nghiệp vụ coi trọng thứ tự phải có chính sách về thứ tự theo khóa và xử lý sự kiện đến muộn. Nếu retry vô hạn các sự kiện thất bại, sự cố sẽ lan rộng, nên cần có hàng đợi cách ly và thủ tục xử lý lại do người vận hành thực hiện.
4.3 Đọc kép·Ghi kép
Đọc kép hữu ích để so sánh kết quả của hai hệ thống, nhưng làm tăng độ trễ và tải của yêu cầu người dùng. Yêu cầu so sánh nên thực hiện bất đồng bộ hoặc lấy mẫu, và kết quả chứa thông tin cá nhân phải được che hoặc băm để không để lại nguyên văn trong log so sánh.
Ghi kép giúp xác nhận tính nhất quán dữ liệu nhưng không phải là giao dịch phân tán. Nếu một bên ghi thành công rồi bên kia thất bại, cần có sự kiện bù trừ, hàng đợi xử lý lại, xác nhận của người vận hành và kịch bản khôi phục lấy hệ thống nguồn làm chuẩn. Nếu có thể, cấu trúc giữ một nguồn duy nhất và cập nhật các kho dẫn xuất bằng sự kiện sẽ làm rõ ranh giới trách nhiệm.
| Giai đoạn dữ liệu | Đường đọc | Đường ghi | Độ khó rollback | Mục đích áp dụng |
|---|---|---|---|---|
| Quan sát ban đầu | Legacy | Legacy | Thấp | Nắm đường cơ sở·quan hệ gọi |
| Kiểm chứng bóng | So sánh legacy+mới | Legacy | Thấp~Trung bình | Kiểm chứng kết quả·hiệu năng |
| Chuyển đổi giới hạn | Ưu tiên mới, legacy khi thất bại | Nguồn đơn hoặc ghi kép có kiểm soát | Trung bình | Học từ lưu lượng thực |
| Chuyển quyền sở hữu miền | Mới | Mới | Trung bình~Cao | Xác lập hệ thống mới là system of record |
| Loại bỏ legacy | Mới | Mới | Cao | Chấm dứt phụ thuộc và cắt giảm chi phí |
Ở mỗi giai đoạn, định nghĩa rollback chỉ là "quay về định tuyến trước" là chưa đủ. Phải quyết định cả việc các thay đổi đã ghi vào kho mới có cần quay về legacy hay không, xử lý lại yêu cầu đã hiển thị thành công cho người dùng có an toàn không, và sự kiện có bị phát hành trùng không. Đặc biệt, sau khi chuyển quyền sở hữu dữ liệu nguồn, khôi phục theo chiều tiến (forward recovery) thường an toàn hơn rollback, nên cần phân biệt khả năng đảo ngược và mục tiêu khôi phục theo từng giai đoạn.
5. So sánh với các chiến lược chuyển đổi truyền thống
Viết lại toàn bộ (Big Bang) là cách hoàn thiện hệ thống mới rồi thay thế trong một lần. Khi cấu trúc đơn giản, thời hạn chuyển đổi ngắn và legacy ít phụ thuộc bên ngoài, cách này có thể dễ quản lý. Tuy nhiên, trong thời gian phát triển dài rất khó xác nhận phản hồi người dùng qua vận hành thực tế, và ở lần chuyển đổi cuối sẽ phải đối mặt cùng lúc với các khác biệt ẩn và vấn đề dữ liệu.
Vận hành song song (Parallel Run) là cách chạy đồng thời hệ thống cũ và mới trong một khoảng thời gian để so sánh kết quả. Hữu ích khi việc kiểm chứng kết quả với cùng đầu vào là quan trọng, như tính toán rủi ro hay báo cáo theo quy định, nhưng chi phí cấp đầu vào cho hai hệ thống và đối soát kết quả là lớn. Strangler Fig có thể tận dụng một phần vận hành song song, nhưng không phải chạy song song sau khi hoàn thiện toàn bộ hệ thống mà áp dụng ở phạm vi nhỏ theo từng chức năng.
Lift and Shift là cách chỉ di chuyển hạ tầng mà không thay đổi nhiều cấu trúc hiện có. Có thể giảm gián đoạn vận hành và rủi ro hạ tầng lỗi thời, nhưng mức ràng buộc của ứng dụng và nút thắt triển khai có thể vẫn còn. Ngược lại, Strangler Fig có thể đồng thời thúc đẩy di chuyển hạ tầng và thiết kế lại ranh giới ứng dụng·dữ liệu, nhưng cấu trúc tạm thời và độ phức tạp vận hành tăng lên.
| Tiêu chí | Viết lại toàn bộ | Lift and Shift | Strangler Fig |
|---|---|---|---|
| Đơn vị chuyển đổi | Toàn bộ hệ thống | Đơn vị hạ tầng·triển khai | Đơn vị chức năng nghiệp vụ·miền |
| Giá trị ban đầu | Phát sinh muộn | Ngay sau khi di chuyển hạ tầng | Phát sinh khi hoàn thành mỗi lát cắt |
| Rủi ro gián đoạn nghiệp vụ | Cao | Trung bình | Tương đối thấp |
| Độ phức tạp tạm thời | Lớn trong thời gian phát triển | Tương đối thấp | Cao do facade·đồng bộ |
| Học yêu cầu ẩn | Dồn vào giai đoạn cuối | Hạn chế | Học ở mỗi giai đoạn |
| Thay đổi thiết kế dữ liệu | Thực hiện một lần | Hầu như không | Thực hiện tuần tự |
| Điều kiện thành công | Hoàn thiện toàn bộ·kiểm chứng một lần | Ổn định sau di chuyển | Ranh giới·quan sát·kế hoạch loại bỏ |
Trong phép so sánh này, Strangler Fig không phải lúc nào cũng vượt trội. Khi cần thay thế nhanh một hệ thống nhỏ và độc lập, hoặc khi luật pháp yêu cầu phải hủy bỏ ngay hệ thống gốc, việc cùng tồn tại tuần tự có thể lại bất lợi. Ngược lại, trong môi trường như hệ thống nghiệp vụ quy mô lớn có chi phí gián đoạn cao và yêu cầu liên tục thay đổi, lý do để chấp nhận chi phí tạm thời ban đầu càng lớn.
6. Trường hợp áp dụng: Chuyển đổi từng giai đoạn nền tảng đặt hàng·giao hàng
Sau đây không phải là kết quả thực tế của một doanh nghiệp cụ thể mà là kịch bản ví dụ phục vụ viết bài thi Kỹ sư chuyên nghiệp (Professional Engineer). Giả định một nền tảng đặt hàng·giao hàng đang dùng ứng dụng monolith cũ và một cơ sở dữ liệu quan hệ duy nhất, và cần nhanh chóng hỗ trợ kênh di động mới cùng quy tắc giao hàng theo khu vực.
Ở giai đoạn đầu, đội ngũ lắp đặt facade và quan sát lưu lượng tra cứu đơn hàng. Việc tạo đơn hàng vẫn để ở legacy, chỉ các yêu cầu tra cứu được chuyển theo kiểu bóng sang dịch vụ tra cứu mới để so sánh kết quả trạng thái, số tiền và che địa chỉ giao hàng. Lúc này, trước khi chuyển chức năng, lấy phân bố thời gian phản hồi thực tế và loại lỗi của legacy làm đường cơ sở.
Ở giai đoạn thứ hai, xây dựng mô hình đọc cho tra cứu đơn hàng ở kho mới. Truyền các thay đổi của bảng đơn hàng legacy bằng CDC và ghi lại thời điểm sự kiện cuối cùng và phiên bản của từng đơn hàng. Nếu kết quả tra cứu mới bị trễ hoặc bất nhất thì không hiển thị cho người dùng mà giữ đường legacy, đồng thời gửi các bản ghi bất nhất vào hàng đợi vận hành.
Ở giai đoạn thứ ba, chuyển chức năng thay đổi địa chỉ giao hàng. Dịch vụ mới thực hiện chuẩn hóa địa chỉ, kiểm tra quyền và phán định khu vực có thể giao, còn thay đổi trạng thái đơn hàng gọi đường ghi duy nhất của legacy thông qua hợp đồng đã được nêu rõ. Không để hệ thống mới sửa trực tiếp bảng nội bộ của legacy, qua đó tạo ranh giới để sau này có thể chuyển quyền sở hữu ghi của miền đơn hàng.
Ở giai đoạn thứ tư, chuyển dần lưu lượng tạo đơn hàng cho các khu vực mới. Để ngăn đơn hàng trùng, dùng cả khóa yêu cầu của client và khóa nghiệp vụ làm khóa lũy đẳng, bảo đảm việc retry của bộ định tuyến không tạo cùng một đơn hàng hai lần. Truyền ID tương quan (correlation ID) của kết quả tạo đơn, phê duyệt thanh toán, trừ tồn kho và sự kiện giao hàng xuyên suốt mọi chặng.
Ở giai đoạn thứ năm, thực hiện chèn lỗi và diễn tập khôi phục. Xây dựng kịch bản về trễ CDC, sự cố kho mới, lỗi quy tắc bộ định tuyến, timeout khi gọi legacy và trùng lặp sự kiện để đo thời gian rollback và thời gian khôi phục dữ liệu thực tế. Nếu kết quả đo đạt mục tiêu thì mở rộng khu vực và phạm vi lưu lượng; nếu không đạt thì hoàn nguyên feature flag rồi khắc phục nguyên nhân.
Cuối cùng, xác nhận mức sử dụng bảng tra cứu đơn hàng legacy và các batch liên quan bằng 0, lưu riêng dữ liệu kiểm toán·lưu giữ rồi hủy bỏ bảng miền. Gỡ bỏ phần mã liên quan đến đơn hàng còn sót trong ứng dụng legacy và các quy tắc facade, tránh trạng thái hoàn thành giả kiểu "được định tuyến sang dịch vụ mới nhưng bên trong vẫn gọi legacy".
7. Yếu tố rủi ro và biện pháp kiểm soát
7.1 Cấu trúc tạm thời trở thành vĩnh viễn
Facade và lớp chống hư hại giúp việc chuyển đổi khả thi, nhưng nếu không có lịch loại bỏ, chúng sẽ trở thành chi phí dịch vĩnh viễn và điểm phát sinh sự cố. Mọi cấu phần tạm thời đều được gắn thẻ người sở hữu, ngày tạo, chức năng phụ thuộc, điều kiện loại bỏ và ngày hết hạn. Trong các buổi rà soát kiến trúc hằng quý, xác nhận lưu lượng thực tế và tham chiếu mã để quản lý công việc loại bỏ với độ ưu tiên ngang bằng phát triển chức năng thông thường.
7.2 Bất nhất dữ liệu và rollback thất bại
Nếu hệ thống mới trả về phản hồi thành công nhưng đồng bộ dữ liệu thất bại, người dùng có thể thấy kết quả khác sau khi truy cập lại. Cần xác định một chủ sở hữu dữ liệu duy nhất, xử lý thứ tự, trùng lặp và trễ của sự kiện, đồng thời kiểm toán các chỉ số nhất quán và kết quả xử lý lại. Tài liệu hóa theo từng miền cho đến thời điểm nào có thể hoàn nguyên định tuyến và sau đó sẽ thực hiện hiệu chỉnh theo chiều tiến nào.
7.3 Nút thắt hiệu năng và lan truyền sự cố
Nếu facade kiểm tra và chuyển đổi mọi yêu cầu, độ trễ sẽ cộng dồn, và các yêu cầu so sánh gọi cả legacy lẫn hệ thống mới làm tải tăng gấp đôi. Áp dụng timeout, circuit breaker, bulkhead và so sánh bất đồng bộ theo từng đường, và kiểm tra số yêu cầu đồng thời tối đa cùng tải đỉnh bằng thử nghiệm dung lượng ở mỗi giai đoạn chuyển đổi. Khả năng quan sát được thiết kế xoay quanh độ trễ theo phân vị và tỷ lệ thất bại nghiệp vụ chứ không phải giá trị trung bình.
7.4 Đứt gãy kiểm soát bảo mật·thông tin cá nhân
Nếu khi chuyển chức năng sang dịch vụ mới mà bỏ sót xác thực, phân quyền, masking và log kiểm toán của legacy, chức năng vẫn chạy nhưng mức kiểm soát bị hạ thấp. Kiểm tra ngay từ giai đoạn thiết kế việc phân loại dữ liệu, đặc quyền tối thiểu, quản lý bí mật, mã hóa, log truy cập của dịch vụ mới, và kiểm thử xem quyết định phân quyền của legacy và hệ thống mới có cùng ý nghĩa hay không. Không để lại nguyên văn các giá trị nhạy cảm như số định danh cá nhân hay thông tin thanh toán trong log lưu lượng bóng.
7.5 Không nhất quán giữa tổ chức và trách nhiệm
Việc chuyển chức năng làm thay đổi quyền sở hữu giữa các đội và quy trình nghiệp vụ. Nếu chỉ đội phát triển thực hiện hiện đại hóa còn vận hành, bảo mật, dữ liệu và nghiệp vụ tham gia muộn, sau khi chuyển đổi xong sẽ phát sinh nút thắt trong ứng phó sự cố và phê duyệt thay đổi. Sắp xếp quyền quyết định của product owner, người phụ trách miền, đội nền tảng, người quản lý dữ liệu và người phụ trách bảo mật·kiểm toán bằng RACI, và đặt các chỉ số thành công chung.
8. Chuyên sâu: Danh mục hiện đại hóa và hệ thống đo lường
Nếu chỉ quản lý Strangler Fig như lịch trình của một dự án, rất dễ tập trung vào việc tăng số lượng chức năng được chuyển. Từ góc nhìn Kỹ sư chuyên nghiệp (Professional Engineer), cần đánh giá danh mục (portfolio) đối tượng hiện đại hóa theo các trục giá trị, rủi ro, mức ràng buộc, quy định và tần suất thay đổi, rồi liên kết kiến trúc mục tiêu của từng miền với thứ tự chuyển đổi.
Độ ưu tiên của chức năng không đơn thuần theo độ khó. Chức năng có giá trị khách hàng cao và thay đổi thường xuyên mang lại hiệu quả học hỏi lớn cho hệ thống mới, nhưng nếu mức ràng buộc quá cao thì có thể không phù hợp làm ứng viên đầu tiên. Ngược lại, chức năng có tính độc lập cao nhưng giá trị thấp có thể dùng làm đối tượng luyện tập để giảm rủi ro, nên cần cân bằng giữa học hỏi và giá trị trên toàn danh mục.
Chỉ số vận hành được tổ chức thành bốn tầng. Thứ nhất là chỉ số kỹ thuật: tính sẵn sàng, tỷ lệ lỗi, độ trễ, thông lượng. Thứ hai là chỉ số dữ liệu: độ trễ đồng bộ, số bản ghi bất nhất, sự kiện trùng lặp, tỷ lệ xử lý lại thành công. Thứ ba là chỉ số nghiệp vụ: tỷ lệ đặt hàng thành công, độ chính xác quyết toán, thời gian xử lý nghiệp vụ, tỷ lệ người dùng rời bỏ. Thứ tư là chỉ số chuyển đổi: tỷ lệ gọi legacy, tỷ lệ chức năng mới, số adapter tạm thời, số bảng·batch đã loại bỏ.
Các chỉ số này được gom vào một dashboard nhưng phải dùng mẫu số có cùng ý nghĩa. Ví dụ, không thể coi là thành công chỉ vì tỷ lệ lỗi của hệ thống mới thấp, mà phải xem đồng thời tỷ lệ yêu cầu bộ định tuyến gửi sang hệ thống mới bị chuyển thành retry trên legacy và tỷ lệ thành công nghiệp vụ cuối cùng. Tiêu chí dừng của giai đoạn chuyển đổi được thống nhất trước, và khi vượt tiêu chí thì thực hiện rollback tự động hoặc dựa trên phê duyệt.
Hồ sơ quyết định kiến trúc (ADR) ghi lại lý do chọn chức năng này trước, mô hình quyền sở hữu dữ liệu và tính nhất quán nào đã được chấp nhận, và khi nào sẽ loại bỏ facade. Hồ sơ này giúp xác nhận lại ý đồ và các đánh đổi của quá trình chuyển đổi khi đội ngũ thay đổi hoặc khi xảy ra sự cố vận hành. Ngoài ra, phản ánh các nguyên tắc chung và quy tắc cấm vào kiểm tra mã và rà soát thiết kế để dịch vụ mới không tái tạo mức ràng buộc giống legacy.
9. Lưu ý và hàm ý
9.1 Thiết kế ưu tiên ranh giới nghiệp vụ
Nếu cắt theo tầng kỹ thuật hoặc cơ cấu đội ngũ, quyền sở hữu dữ liệu và giao dịch sẽ tiếp tục đan xen. Cần xác định ranh giới dựa trên năng lực nghiệp vụ và lý do thay đổi, và chỉ định người chịu trách nhiệm cùng chỉ số thành công cho từng ranh giới.
9.2 Phân biệt khả năng đảo ngược và khôi phục theo chiều tiến
Nếu giả định mọi thay đổi đều có thể hoàn nguyên, ta sẽ đánh giá thấp thực tế sau khi di chuyển dữ liệu. Rollback định tuyến, rollback mã, rollback dữ liệu và xử lý bù trừ nghiệp vụ là những phương tiện khác nhau, nên cần thử nghiệm phạm vi khả thi ở từng giai đoạn và chuẩn bị thủ tục hiệu chỉnh theo chiều tiến cho trường hợp không thể hoàn nguyên.
9.3 Không chuyển đổi tuần tự khi thiếu khả năng quan sát
Nếu tăng lưu lượng chỉ dựa vào đánh giá của nhà phát triển rằng hệ thống mới chạy tốt, có thể bỏ sót lỗi thực tế của người dùng và độ trễ dữ liệu. Truy vết phân tán, log có cấu trúc, SLO theo chức năng, kiểm chứng nhất quán dữ liệu và KPI nghiệp vụ phải được chuẩn bị từ trước khi chuyển đổi.
9.4 Quản lý vòng đời của cấu phần tạm thời
Facade, adapter, ghi kép và pipeline đồng bộ có thể trở thành nợ kỹ thuật, nên cần đăng ký như tài sản thông thường và quản lý ngày hết hạn cùng điều kiện loại bỏ. Đưa việc xóa mã legacy và gỡ quy tắc định tuyến vào rà soát hoàn thành hiện đại hóa để phân biệt "đã thêm hệ thống mới" với "đã thay thế legacy".
9.5 Bảo đảm tương đương về bảo mật và thông tin cá nhân
Khi chức năng chuyển sang hệ thống mới, mức kiểm soát về xác thực, phân quyền, mã hóa, masking và kiểm toán không được giảm xuống. So sánh chính sách của hai hệ thống, chặn lộ thông tin nhạy cảm trong dữ liệu kiểm thử và log bóng, đồng thời phản ánh nghĩa vụ lưu giữ·hủy dữ liệu vào kế hoạch chuyển đổi.
9.6 Thay đổi đồng thời mô hình tổ chức·vận hành
Nếu chỉ đưa vào kiến trúc mới mà giữ nguyên quyền triển khai của đội, cách ứng phó sự cố và cấu trúc ra quyết định sản phẩm, các nguyên nhân của legacy có thể lặp lại. Thiết kế đồng thời quyền sở hữu hướng miền, triển khai và kiểm thử tự động, vòng phản hồi vận hành để hiện đại hóa trở thành cách làm việc bền vững chứ không phải một dự án một lần.
9.7 Đánh giá tình huống không phù hợp để áp dụng
Nếu không có điểm tiếp xúc để chặn yêu cầu, không có thời gian cho phép legacy và hệ thống mới cùng tồn tại, hoặc hệ thống nhỏ và độc lập, thì thay thế toàn bộ có thể hợp lý hơn. Đừng chọn mẫu này như một kiến trúc thời thượng, mà hãy quyết định sau khi so sánh thời gian chuyển đổi, rủi ro dữ liệu, chi phí gián đoạn và khả năng loại bỏ cuối cùng.
Tài liệu tham khảo
- Martin Fowler, “Strangler Fig”: https://martinfowler.com/bliki/StranglerFigApplication.html
- Microsoft Azure Architecture Center, “Strangler Fig pattern”: https://learn.microsoft.com/en-us/azure/architecture/patterns/strangler-fig
- AWS Prescriptive Guidance, “Strangler Fig pattern”: https://docs.aws.amazon.com/prescriptive-guidance/latest/modernization-strangler-fig-pattern/introduction.html
Tóm tắt một câu: Mẫu Strangler Fig là chiến lược hiện đại hóa thay thế dần legacy mà không gián đoạn nghiệp vụ thông qua facade, lát cắt chức năng, kiểm chứng dữ liệu và chuyển đổi có thể đảo ngược, và cuối cùng loại bỏ cả các cấu trúc tạm thời.