Nền tảng doanh nghiệp · TVT Group, 2021–2024

Chuyển đổi dần (Strangler migration) từ khối monolith .NET Framework

Bóc tách từng mảng nghiệp vụ từ khối monolith .NET sang service mới ngay khi production vẫn đang chạy. Thời gian deploy rút ngắn từ khoảng 2 giờ thao tác thủ công xuống khoảng 15 phút.

.NET 7 · RabbitMQ · PostgreSQL · AWS EC2

Kết quả: Rút ngắn thời gian deploy từ ~2 giờ xuống ~15 phút nhờ tự động hóa CI/CD và tách nhỏ service; bóc tách thành công domain service đầu tiên mà không cần đập đi xây lại (big-bang rewrite).

Bài toán thực tế

Toàn bộ hệ thống nằm chung trong một khối monolith .NET Framework 4.7 khiến mỗi đợt release đều tiềm ẩn rủi ro lan truyền sang mọi mảng nghiệp vụ, và mỗi lần deploy đầy đủ mất khoảng 2 giờ thao tác thủ công.

Không được phép ngắt luồng truy cập production để đóng băng tính năng và viết lại từ đầu.
Các module đang dùng chung một cơ sở dữ liệu (shared database coupling) khiến việc tách vội vàng rất dễ gây lỗi dây chuyền.
Nhiều khách hàng doanh nghiệp (enterprise accounts) đòi hỏi cam kết phản hồi và xử lý sự cố khắt khe.
Các dự án mới lúc đó vẫn đang dựng hạ tầng AWS thủ công, thiếu nhất quán.

Kiến trúc hệ thống

flowchart LR
  subgraph legacy ["Legacy monolith"]
    legacy_0[".NET Framework 4.7 monolith"]
    legacy_1["Manual deploy pipeline"]
  end
  subgraph extract ["Strangler cut"]
    extract_0["First domain service on .NET 7"]
    extract_1["Traffic router or gateway"]
    extract_2[("Shared DB phase")]
  end
  subgraph platform ["Event and ops"]
    platform_0[["RabbitMQ event bus"]]
    platform_1["CI build and test"]
    platform_2["Automated deploy to EC2"]
    platform_3["AWS standard template"]
  end
  legacy_0 --> extract_1
  extract_1 --> extract_0
  extract_0 --> extract_2
  extract_0 --> platform_0
  platform_1 --> platform_2
  platform_3 --> platform_2

Các quyết định kiến trúc then chốt

Bóc tách dần theo mảng nghiệp vụ (Strangler pattern), không đập đi xây lại

Triển khai các service .NET 7 mới chạy song song cạnh khối monolith và điều hướng lưu lượng truy cập (traffic) sang dần.

Đóng băng hệ thống để viết lại từ đầu sẽ làm đình trệ việc sửa lỗi và phát triển tính năng cho các khách hàng đang trả phí.

Phương án đã loại bỏ: Đập đi xây lại toàn bộ (big-bang rewrite) — loại bỏ vì rủi ro đứt gãy vận hành và thời gian chờ đợi quá lớn.

Đánh đổi: Chấp nhận chi phí vận hành song song hai hệ thống (dual-run) và dùng chung database tạm thời cho đến bước tách dữ liệu tiếp theo.

Chuyển sang bất đồng bộ (async end-to-end) trên các luồng nặng về I/O

Áp dụng async xuyên suốt từ tầng Web API xuống tầng truy xuất dữ liệu trên các luồng tải cao (hot paths); loại bỏ phụ thuộc vào session cố định trên từng máy chủ (session affinity) ở những nơi có thể.

Hiện tượng cạn kiệt luồng xử lý (thread pool starvation) khi tải tăng cao là điểm nghẽn kinh niên của khối monolith cũ.

Phương án đã loại bỏ: Gọi chặn đồng bộ (.Result / .Wait) bọc ngoài các hàm cũ — loại bỏ hoàn toàn trên các service mới sau nhiều lần gây deadlock trên .NET Framework.

Đánh đổi: Cần đào tạo lại thói quen viết code cho đội ngũ và rà soát kỹ các điểm gọi hàm còn nằm lại trong khối monolith.

Chuẩn hóa bộ khung AWS và CI/CD cho dự án mới

Đóng gói sẵn cấu hình EC2, security group, Docker Compose và danh mục kiểm tra CI thành một bộ template chuẩn để nhân bản cho mỗi dự án mới.

Trước đó mỗi dự án mới đều tự cấu hình lại chứng chỉ TLS và kịch bản deploy theo một kiểu khác nhau.

Phương án đã loại bỏ: Thiết kế hạ tầng tùy biến riêng lẻ cho từng dự án — loại bỏ sau khi liên tục làm chậm tiến độ khởi tạo dự án hàng tuần liền.

Đánh đổi: Cần có người chịu trách nhiệm duy trì và cập nhật template chung; mọi trường hợp ngoại lệ đều phải ghi rõ lý do kỹ thuật.

Phần tôi chịu trách nhiệm, trực tiếp viết và phân công

Chịu trách nhiệm (Own)

  • Chiến lược chuyển đổi (migration strategy) và lựa chọn mảng nghiệp vụ đầu tiên để bóc tách
  • Chuẩn hóa quy trình CI/CD và bộ template hạ tầng AWS cho việc khởi tạo các dự án mới
  • Đầu mối kỹ thuật chính (technical point of contact) cho 5 khách hàng doanh nghiệp trong suốt giai đoạn chuyển đổi

Trực tiếp viết (Write)

  • Các service .NET 7 đầu tiên được tách ra và lớp tích hợp ngược lại với khối monolith còn lại
  • Các luồng giao tiếp bất đồng bộ (event-driven) qua RabbitMQ ở những nghiệp vụ cần tách rời

Phân công (Delegate)

  • Đàm phán thương mại và quản lý tài khoản khách hàng (account management)

Quy mô vận hành

  • Thời gian deploy khối monolith giảm từ ~2 giờ thao tác thủ công xuống ~15 phút sau khi có CI/CD và tách nhỏ service
  • Thời gian dựng hạ tầng AWS cho dự án mới rút ngắn từ vài tuần xuống còn vài ngày nhờ bộ template chuẩn
  • Trực tiếp làm đầu mối kỹ thuật xử lý sự cố cho 5 khách hàng doanh nghiệp lớn

Ranh giới phạm vi

  • Khả năng chịu tải được cải thiện qua nhiều lớp kết hợp (chuyển sang async I/O, đưa session state ra ngoài tiến trình, bổ sung cache, tối ưu index và nâng cấp runtime), không đến từ một phép thử đơn lẻ nào.
  • Quá trình chuyển đổi lưu lượng (cutover) không phải lúc nào cũng là zero-downtime rolling deploy cho toàn bộ mọi service.

Các chỉ số giám sát khi vận hành

Tổng thời gian deploy từ lúc merge code đến khi phục vụ traffic trên productionTỷ lệ lỗi (error rate) trong các khung giờ điều hướng lưu lượng sang service mớiĐộ sâu hàng đợi (queue depth) khi khối monolith và service mới cùng đẩy sự kiện đồng thời

Nguyên tắc bất di bất dịch trong thiết kế

  • Việc deploy một mảng nghiệp vụ riêng lẻ không bao giờ được phép làm gián đoạn toàn bộ khối monolith.
  • Mọi thay đổi trên schema dữ liệu dùng chung đều phải được phối hợp kiểm soát; các service không được tự ý thay đổi ngữ nghĩa của dữ liệu hiện có.
  • Mỗi khách hàng doanh nghiệp đều có đầu mối kỹ thuật định danh trực tiếp hỗ trợ trong khung giờ chuyển đổi, không đẩy qua hàng đợi ticket chung.

Phạm vi ứng dụng rộng hơn

  • Các hệ thống .NET Framework lâu năm cần hiện đại hóa mà không được làm gián đoạn dòng doanh thu.
  • Tổ chức kỹ thuật muốn chuẩn hóa quy trình đưa dự án mới lên cloud thay vì làm thủ công.
  • Đội ngũ kỹ sư chuyển dịch từ thói quen phát hành monolith sang kiến trúc microservices.