0
0
Lập trình
Sơn Tùng Lê
Sơn Tùng Lê103931498422911686980

Chuyển đổi từ Kiến trúc Monolith sang EDA trên AWS

Đăng vào 1 tuần trước

• 8 phút đọc

Chuyển đổi từ Kiến trúc Monolith sang EDA trên AWS

Chuyển đổi từ một giải pháp monolithic sang kiến trúc hướng sự kiện (EDA) có thể là một nhiệm vụ khó khăn, nhưng đây là hành trình mà nhiều tổ chức đang thực hiện để đạt được sự linh hoạt, khả năng mở rộng và đổi mới cao hơn.

Trong bài viết này, tôi sẽ chia sẻ những hiểu biết và kỹ thuật thực tiễn dựa trên một dự án chuyển đổi thực tế mà tôi đã tham gia. Những bài học này có thể áp dụng rộng rãi, cho dù bạn đang chạy trên AWS hay đang xem xét cách hiện đại hóa các khối lượng công việc kế thừa của mình.

Điểm Bắt Đầu

Dự án chuyển đổi bắt đầu với một khách hàng thực tế: một công ty trò chơi trực tuyến. Điểm bắt đầu là một ứng dụng lớn trên .NET Framework chạy trên Windows Servers với một cơ sở dữ liệu SQL Server.

Khi một khách hàng mới đăng ký, cần thực hiện các kiểm tra xác minh độ tuổi tự động. Điều này liên quan đến việc gọi một API bên thứ ba, xử lý kết quả và quyết định cho phép nạp tiền hay khóa tài khoản.

Toàn bộ quy trình đã được mã hóa bên trong điểm cuối đăng ký, thực hiện các cuộc gọi đồng bộ đến nhiều lớp nội bộ và API bên thứ ba. Như bạn có thể đoán, điều này dẫn đến việc liên kết chặt chẽ và hạn chế tính linh hoạt.

Mục Tiêu

Tầm nhìn là phân chia ứng dụng thành các dịch vụ dựa trên miền. Mỗi dịch vụ sẽ sở hữu logic và dữ liệu riêng của nó, giảm thiểu sự liên kết và cô lập chức năng kinh doanh.

Ví dụ, tất cả logic liên quan đến việc xác minh độ tuổi có thể được bao gói trong dịch vụ của riêng nó. Bằng cách đó, bất kỳ thay đổi nào đối với việc xác minh (như tích hợp một nhà cung cấp mới) sẽ được giới hạn trong dịch vụ duy nhất đó.

Giới thiệu Dịch vụ Xác minh Độ tuổi

Chúng tôi bắt đầu bằng cách tạo một Dịch vụ Xác minh Độ tuổi độc lập, có:

  • Sở hữu cơ sở dữ liệu riêng cho kết quả và lịch sử kiểm tra.
  • Phát ra các sự kiện để thông báo cho phần còn lại của hệ thống.
  • Cung cấp API đọc tùy chọn cho các tìm kiếm theo yêu cầu.

Việc tích hợp được thực hiện dần dần bằng cách sử dụng một số mẫu đã được thiết lập mà tôi sẽ trình bày bên dưới.

Các Mẫu Chính cho Chuyển Đổi

Mẫu Strangler Fig

Được đặt tên bởi Martin Fowler, mẫu Strangler Fig liên quan đến việc từ từ xây dựng một hệ thống mới xung quanh các cạnh của hệ thống cũ cho đến khi monolith trở nên lỗi thời.

Chúng tôi bắt đầu bằng cách trích xuất quy trình xác minh độ tuổi trước, để lại phần còn lại của hệ thống không thay đổi. Qua thời gian, nhiều chức năng đã được tách ra cho đến khi monolith chỉ còn lại rất ít.

Thông báo Sự kiện

Chúng tôi đã áp dụng mẫu Thông báo Sự kiện sử dụng Amazon EventBridge.

  • Khi một khách hàng đăng ký, monolith phát hành một sự kiện CustomerRegistered.
  • Quy trình đăng ký không chờ đợi kết quả – nó chỉ đơn giản phát tán sự kiện.
  • Các dịch vụ khác, như Dịch vụ Xác minh Độ tuổi, đã đăng ký và hoạt động độc lập.

Cách tiếp cận này đã tách rời các dịch vụ và cho phép hành vi không đồng bộ mà không buộc các hệ thống thượng nguồn phải thay đổi.

Dark Launching

Để kiểm tra dịch vụ mới một cách an toàn, chúng tôi đã chạy nó ở chế độ dark launch.

  • Monolith vẫn thực hiện mã cũ.
  • Dịch vụ mới tiêu thụ sự kiện và thực hiện kiểm tra song song, lưu trữ kết quả trong cơ sở dữ liệu của riêng nó.
  • Đầu ra đã bị bỏ qua trong giai đoạn này.

Chúng tôi đã sử dụng các báo cáo để so sánh kết quả cũ và mới, đồng thời gỡ lỗi và tinh chỉnh mà không ảnh hưởng đến khách hàng.

Công tắc Tính năng

Sau đó, chúng tôi đã giới thiệu các cờ tính năng để điều khiển từ xa xem monolith hay dịch vụ mới là chính thống.

AWS cung cấp các cách đơn giản để thực hiện điều này bằng cách sử dụng SSM Parameter Store, AppConfig, hoặc bạn có thể sử dụng các công cụ bên thứ ba như LaunchDarkly.

Khi được xác thực, chúng tôi đã đảo ngược công tắc để vô hiệu hóa mã xác minh của monolith và hoàn toàn dựa vào dịch vụ mới.

Giả sử bạn có mã tương tự như sau trong monolith:

python Copy
def register(user_data):
    SaveUserToDatabase(user_data)
    IsVerified = HttpCallToAgeVerificationService(user_data)
    PersistAgeVerificationToDatabase(IsVerified, user_data)

Một cờ tính năng có thể được thêm như sau, với mã thông báo sự kiện mới được kích hoạt mọi lúc:

python Copy
def register(user_data):
    SaveUserToDatabase(user_data)
    if not feature_flag_enabled(USE_NEW_AGE_VERIFICATION_SERVICE):
        IsVerified = HttpCallToAgeVerificationService(user_data)
        PersistAgeVerificationToDatabase(IsVerified, user_data)
    SendUserRegisteredEventNotification(user_data)

Khi đã sẵn sàng, cờ USE_NEW_AGE_VERIFICATION_SERVICE có thể bị vô hiệu hóa và monolith chỉ còn gửi sự kiện, không còn thực hiện cuộc gọi xác minh độ tuổi nữa.

Giả lập Di sản

Cuối cùng, chúng tôi cần duy trì tính tương thích. Monolith vẫn mong đợi các kết quả xác minh trong cơ sở dữ liệu của nó.

Để giải quyết vấn đề này, chúng tôi đã giới thiệu một dịch vụ Giả lập Di sản:

  • Dịch vụ Xác minh Độ tuổi phát hành các sự kiện như AgeVerificationPassed.
  • Giả lập Di sản tiêu thụ các sự kiện đó và cập nhật cơ sở dữ liệu cũ.

Điều này giúp monolith hoạt động mà không cần thay đổi xâm lấn, và giả lập sau đó được ngừng hoạt động khi monolith được nghỉ hưu.

Thách Thức và Giải Pháp

Không có chuyển đổi nào hoàn thành mà không gặp phải các vấn đề lớn. Chúng tôi đã gặp phải một số vấn đề phổ biến:

  1. Độ trễ - Các hệ thống hướng sự kiện gây ra độ trễ so với các cuộc gọi đồng bộ của monolith. Trong trường hợp của chúng tôi, chúng tôi đã thiết kế các giá trị mặc định cơ sở dữ liệu để xử lý các trạng thái "đang chờ xác minh".
  2. Điều kiện Đua – Các sự kiện có thể đến không theo thứ tự. Các dịch vụ cần có khả năng thử lại, idempotency, và đôi khi đọc dự phòng từ một API nguồn thật.
  3. Idempotency – Việc giao hàng ít nhất một lần có nghĩa là các bản sao xảy ra. Chúng tôi đã sử dụng ID sự kiện và kiểm tra loại bỏ bản sao trong Amazon DynamoDB để ngăn chặn nhiều ưu đãi được gán. Việc kiểm tra idempotency là rất quan trọng.
  4. Hỗn loạn Sự kiện – Không có quản lý, các sự kiện trở nên lộn xộn. Chúng tôi đã xây dựng một Danh mục Sự kiện ghi lại các nhà sản xuất, người tiêu dùng và thuộc tính để đảm bảo tính nhất quán. Điều này giúp tránh các sự kiện với tên không nhất quán, các sự kiện trùng lặp với tên khác nhau, các sự kiện không có mục đích, hoặc các sự kiện có nhiều hơn một trách nhiệm.
  5. Khả năng Quan sát – Nhật ký, chỉ số và theo dõi là rất quan trọng. Trên AWS, điều này có nghĩa là CloudWatch Logs, theo dõi X-Ray và bảng điều khiển chỉ số cho độ trễ, thử lại và tỷ lệ lỗi.

Giải Pháp Cuối Cùng

Dưới đây là kiến trúc cuối cùng ở mức cao:

  1. Khách hàng đăng ký trong monolith và điều này phát hành một sự kiện CustomerRegistered tới EventBridge.
  2. Dịch vụ Xác minh Độ tuổi tiêu thụ sự kiện, gọi nhà cung cấp bên thứ ba, và lưu trữ kết quả trong cơ sở dữ liệu cục bộ của nó.
  3. Nó sau đó phát hành các sự kiện AgeVerificationPassed/AgeVerificationFailed.
  4. Giả lập Di sản lắng nghe và cập nhật cơ sở dữ liệu của monolith, giữ cho tính tương thích cho mã phụ thuộc.
  5. Qua thời gian, các miền khác (như thay đổi địa chỉ) cũng phát hành các sự kiện, cho phép tách rời thêm.

Bài Học Rút Ra

Việc chuyển đổi sang kiến trúc hướng sự kiện không chỉ là về công nghệ – mà còn là về các mẫu, chiến lược kiểm tra và thỏa hiệp kinh doanh.

Một số điểm quan trọng:

  • Bắt đầu nhỏ – trích xuất một tính năng và lặp lại với Mẫu Strangler.
  • Phát ra sự kiện sớm – ngay cả khi không ai tiêu thụ chúng ngay bây giờ, chúng sẽ rất có giá trị sau này. Chỉ cần đảm bảo ghi lại chúng.
  • Sử dụng dark launches và cờ tính năng – kiểm tra một cách an toàn trong sản xuất.
  • Thiết kế cho các vấn đề không đồng bộ – độ trễ, điều kiện đua và bản sao là không thể tránh khỏi.
  • Đầu tư vào khả năng quan sát – nếu không có nó, bạn sẽ bay mù và nó giúp bạn cải thiện hệ thống theo thời gian.

Kết Luận

Chuyển đổi từ một monolith sang kiến trúc hướng sự kiện trên AWS là một sự tiến hóa, không phải là một viết lại lớn. Bằng cách kết hợp EventBridge, microservices, và các mẫu chuyển đổi đã được chứng minh, bạn có thể cung cấp giá trị kinh doanh theo từng giai đoạn trong khi giảm rủi ro.

Hãy nắm bắt sức mạnh của các sự kiện, để kiến trúc của bạn phát triển một cách tự nhiên, và đừng ngần ngại thử nghiệm.

Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào