Chuỗi bài về hành trình thích ứng Kiến trúc Cloud-Native: Bài #3 – Nâng cao khả năng giám sát tiêu chuẩn và tính đàn hồi

Trong bài viết trước, Tối đa thông lượng hệ thống, chúng ta đã nói về những kiểu mẫu thiết kế giúp bạn nhận dạng các thử thách mở rộng tức khắc để giúp nâng cao trải nghiệm khách hàng. Trong bài viết này, chúng ta sẽ nói về những kiểu mẫu kiến trúc (architecture patterns) để nâng cao tính đàn hồi, tại sao việc giám sát lại quan trọng và cách để xây dựng giải pháp giám sát toàn diện.

Trong chuỗi bài này chúng ta sử dụng ví dụ một hệ thống thương mại điện tử với như cầu siêu tăng trưởng chạy trên Cloud. Kiến trúc hiện tại sử dụng monolith chạy trên Amazon EC2 và CSDL là Amazon RDS PostgreSQL.

Ứng dụng monolith này sử dụng kiến trúc phần mềm dạng nguyên khối (tight couple). Phiên giao dịch từ front-end đến back-end cần được hoàn thành trong 30 milliseconds, nếu không thì trải nghiệm người dùng sẽ bị ảnh hưởng không tốt. Ứng dụng này cũng cần tích hợp với các ứng dụng bên ngoài nhằm mục đích làm giàu dữ liệu, xử lý thanh toán, thực hiện đơn hàng. Một vài hệ thống bên ngoài này không cung cấp cam kết chất lượng dịch vụ SLAs (Service Level Agreements) về thời gian phản hồi nhưng trung bình thời gian phản hồi là 15ms. Hệ thống cần khoảng 30 phút trước khi một máy chủ mới hoàn thành khởi động và phục vụ các yêu cầu từ người dùng. Trong 30 phút này có 10 phút cho khởi động ứng dụng, 5 phút để tạo và kiểm thử kết nối, 10 phút để kiểm thử nhanh (sanity test), 5 phút để tải bộ đệm ứng dụng.

Nâng cao khả năng đàn hồi 

Mức độ phức tạp của các ứng dụng monolith khiến cho việc kiểm thử gặp khó khăn. Bạn không thể tránh khỏi lỗi thông qua việc đơn giản kiểm thử tất cả các ngữ cảnh có thể dẫn đến lỗi ứng dụng và hạ tầng. Ứng dụng cần phải được thiết kế để xử lý bất kỳ lỗi nào để duy trì trải nghiệm khách hàng một cách liền mạch ngay cả khi những hệ thống back-ends gặp phải sự cố. Trong phần này chúng ta sẽ tìm hiểu những cách giúp nâng cao khả năng đàn hồi của hệ thống.

Tối thiểu lỗi failover đảm bảo tính liên tục vận hành 

Xây dựng chiến lược phục hồi thảm hoạ DR (Disaster Recovery) đòi hỏi chúng ta phải làm việc ngược lại từ yêu cầu RPO (Recovery Point Objective) và RTO (Recovery Time Objective). Yêu cầu trong ví dụ này chúng ta cần xây dựng hệ thống không bị downtime quá 30 phút (RTO = 30 phút) và dữ liệu bị mất đi chỉ tính bằng một vài phút (RPO = một vài phút).

Để thoả mãn yêu cầu này, chúng tôi đã phát triển một kế hoạch duy trì vận hành theo dài hạn theo tài liệu Disaster Recovery of Workloads on AWS: Recovery in the Cloud bao gồm những điểm sau đây:

  • Chấp nhận mất dữ liệu không nằm trong CSDL 
  • Trước kia chúng tôi sử dụng cơ chế Backup/Restore nhưng hiện tại chúng tôi muốn nâng cao khả năng sẵn sàng hơn. Đối với lưu trữ dữ liệu chúng tôi dùng chiến lược Pilot Light với kỹ thuật point-in-time backup, cross-region Amazon RDS read replicas, Cross-region Amazon S3 replication, và các mẫu CloudFormation.
  • Sử dụng AWS Backup để đơn giản hoá việc sao lưu và sao chép Amazon EC2, Amazon Elastic Block Store (Amazon EBS) và Amazon RDS giữa các AWS Region. Điều này giúp giảm thiểu rủi ro về gián đoạn hệ thống ở quy mô Region.
  • Xây dựng pipeline tự động tạo các “Golden AMI”, Amazon Machine Image chứa đựng hệ điều hành, các gói thư viện sử dụng Amazon Image Builder.
  • Cuối cùng, chúng tôi triển khai mã nguồn ứng dụng tự động thông qua AWS CodePipeline.

Bởi vì đặc tính stateful của ứng dụng, việc tạo EBS snapshot không ngăn cản việc mất mát dữ liệu. Chúng tôi đã cập nhật CI/CD pipeline để triển khai mã nguồn ứng dụng ở Region khác theo hướng dẫn từ bài viết Using AWS CodePipeline to Perform Multi-Region Deployments.

Nâng cao khả năng cân bằng tải giữa các máy chủ 

Ứng dụng monolith xử lý tất cả các phiên giao dịch từ những phiên dài tới 3 phút, hoặc các phiên ngắn 30ms. Để hạn chế các lưu lượng mất cân bằng này chúng tôi đã sử dụng giải thuật Least Outstanding Request Algorithm ở Application Load Balancer. Điều này giúp phân phối tải được tối ưu và hiệu quả hơn.

Thoái lui theo sỗ mũ (Exponential backoff)

Sau khi triển khai các kỹ thuật Retry và Timeout, chúng tôi đã học hỏi được là việc sử dụng Backoff là rất quan trọng cho ứng dụng. Đặc biệt là thoái lui theo số mũ vì thời gian chờ sẽ tăng thêm sau mỗi lần thử lại (Retry). Bạn có thể tham khảo thêm qua bài viết về sử dụng Retry có thể trở thành một thiết kế không tốt (anti-patterns) cho ứng dụng đàn hồi: Timeouts, retries, and backoff with jitter.

Chúng tôi đã quan sát thấy rằng việc thử lại khiến tràn ngập CSDL khi có độ trễ do jitter. Chúng tôi đã triển khai Retry Throttling với AWS Java SDK theo bài viết: Introducing Retry Throttling.

Phân rã (Decoupling) tích hợp sử dụng kiểu mẫu thiết kế hướng sự kiện (event-driven)

Ứng dụng của chúng ta gặp phải một số sự cố khi thực hiện thanh toán và thực hiện đơn hàng làm ảnh hưởng vận hành kinh doanh. Để khắc phục điều này, chúng tôi xác định các đường thông điệp bất đồng bộ để nâng cao trải nghiệm khách hàng. Chúng tôi đã cập nhật ứng dụng sử dụng các kiểu mẫu thiết kế theo bài viết FIFO topics example use case:

  • Ứng dụng gởi các yêu cầu đến chủ đề (topic) Amazon Simple Notification Service (Amazon SNS) và được đăng ký bởi nhiều Amazon Simple Queue Service (Amazon SQS) theo kiến trúc phân phối fanout.
  • Sử dụng AWS Lambda để lấy thông điệp trong hàng chờ Amazon SQS và tương tác với hệ thống bên ngoài, điều tiết số lượng lời gọi đến hệ thống bên ngoài.
  • Tiếp theo, các thông báo được gởi đến người dùng theo yêu cầu.

Kiểu mẫu thiết kế này giúp chúng ta thử lại các yêu cầu không thành công sử dụng FIFO (First In First Out) và tính năng chống lặp lại mô tả trong bài viết Introducing Amazon SNS FIFO – First-in-First-out Pub/Sub Messaging.

Tiên đoán mở rộng với Amazon EC2 

Bởi vì ứng dụng monolith không mở rộng nhanh chóng khi có một lượng người dùng truy xuất cao đột xuất (thời gian bootstrap ứng dụng). Để tiên đoán nhu cầu này, chúng tôi đã tối ưu sự sẵn sàng ứng dụng và tự động mở rộng thông qua các dữ liệu sử dụng CPU lịch sử. Phương pháp tiếp cận này được mô tả kỹ trong bài viết New – Predictive Scaling for EC2, Powered by Machine Learning. Kỹ thuật này cho phép điều chỉnh giãn nở theo nhu cầu thông qua việc tiên đoán lịch sử sử dụng và thời gian để ứng dụng sẵn sàng (warm-up time) khi bootstrap.

Chuẩn hoá giám sát

Việc gián đoạn hệ thống Production là nỗi kinh hãi cho tất cả mọi người, nhưng với giải pháp giám sát đúng đắn chúng có thể giúp ta ít áp lực hơn. Sau một vài gián đoạn của ứng dụng, chúng tôi nhận ra rằng cần phải suy nghĩ lại một cách toàn diện và không theo dõi các chỉ số một lần cơ bản.

Việc lưu tất cả log của mỗi máy chủ và so sánh chúng có thể gây khó khăn khi bạn tìm kiếm lỗi, nguyên nhân lỗi. Chúng tôi đã tìm ra điều cốt lõi để khắc phục sự cố đó là: giám sát và sự kiện tương quan. Chi tiết trình bày ở phần sau.

Định nghĩa những chỉ số ứng dụng và hạ tầng 

Một phần của chỉ số theo dõi và giám sát, chúng tôi tuân thủ theo các hướng dẫn trong trụ cột về hiệu năng (Performance Pillar) của tài liệu AWS Well-Architected Framework. Nói chung, chúng tôi làm việc ngược lại (backwards) từ trải nghiệm khách hàng để xác định những chỉ số liên quan hiệu năng cho mỗi thành phần hệ thống và màn hình hiển thị các chỉ số toàn diện.

Tập trung log 

Khi phân tích các sự kiện gây gián đoạn hệ thống, chúng tôi nhận ra rằng thời gian sử dụng cho các sự kiện khác nhau có tính liên quan khiến cho thời gian trung bình giải quyết sự cố cao và yêu cầu cơ bản hiệu năng đã không được tuân thủ. Điều này cũng cho thấy sự thiếu hụt trong theo dõi bảo mật. Để vượt qua những thử thách này, chúng tôi:

Chúng tôi đã sử dụng giải pháp này như nền móng và cập nhật cấu hình theo như hướng dẫn Amazon ES Service Best Practices để tối ưu hoá hiệu năng ở quy mô. Chúng tôi cũng tạo các bản snapshot của ES cluster hàng giờ và sử dụng Amazon S3 Cross-Region Replication để khôi phục cluster trong trường hợp có sự cố.

Quản trị giới hạn dịch vụ với Service Quota và tương thích chiến lược đa tài khoản (Multi-Account)

Chúng tôi quan sát thấy rằng hầu hết các dịch vụ chạy trong cùng một tài khoản, điều này dẫn đến những giới hạn dịch vụ. Chúng tôi đã triển khai hai chiến lược cho tình huống này:

  • Sử dụng Service Quota để chủ động xác định giới hạn dịch vụ. Bạn có thể tham khảo thêm bài viết: Introducing Service Quotas: View and manage your quotas for AWS services from one central location để hiểu thêm về quản trị giới hạn dịch vụ trên AWS. Service Quota có thể tích hợp Amazon CloudWatch cho một vài dịch vụ. Với tích hợp này giúp bạn nhận được cảnh báo khi một dịch vụ gần chạm tới giới hạn. Dựa vào đó, đội ngũ vận hành có thể gởi các yêu cầu để nâng giới hạn trước khi hệ thống bị ảnh hưởng.
  • Khi sử dụng Service Quota, chúng tôi đã nhận thấy rằng môi trường Production và Non-production nên triển khai trên nhiều tài khoản với rất nhiều lý do bao gồm như giới hạn dịch vụ trên mỗi tài khoản. Điều này được trình bày trong bài viết Best Practices for Organizational Units with AWS Organizations, môi trường đa tài khoản cho phép bạn đơn giản hoá việc tính phí, linh hoạt kiểm soát bảo mật, quản trị tài khoản ở quy mô, và tăng trưởng nhanh mà vẫn nâng cao sự sáng tạo.

Hình 1 – Kiến trúc hiện tại với nâng cao sự đàn hồi và chuẩn hoá giám sát

Kết luận

Trong bài viết này chúng ta đã thảo luận về kiểu mẫu thiết kế mà bạn có thể ứng dụng để nâng cao tính đàn hồi, đảm bảo mục tiêu RPO và RTO, mở rộng ứng dụng monolith bằng việc tiên đoán sử dụng, mở rộng năng lực giám sát ứng dụng, hoạch định cho triển khai đa tài khoản. Trong bài viết tiếp theo, chúng ta sẽ bàn kỹ hơn về kiểu mẫu kiến trúc để nâng cấp kiến trúc hiện tại.


Bài được dịch từ bài viết trên AWS Blogs, bạn có thể xem bài viết gốc tại đây.