Làm thế nào để nâng cấp trang web mà không làm gián đoạn dịch vụ? Đây là câu hỏi phỏng vấn các công ty lớn thường hỏi khi bạn xin vào vị trí làm lập trình backend. Bài viết này giới thiệu một giải pháp dễ thực hiện.

Làm thế nào để nâng cấp trang web mà không làm gián đoạn dịch vụ? Đây là câu hỏi phỏng vấn các công ty lớn thường hỏi khi bạn xin vào vị trí làm lập trình backend. Bài viết này giới thiệu một giải pháp dễ thực hiện.

Các hệ thống web thường có cấu trúc sau:

Load balancer và/hoặc reverse proxy web server

App server 1 App server 2 App server 3
Tầng trên cùng là load balancer và/hoặc reverse proxy web server, để hứng kết nối từ client.
Tầng tiếp theo nhiều web app server để phân tải và chết server này thì còn server kia.
Tầng dưới cùng là DB.
Tất nhiên nếu đi sâu vào chi tiết thì mỗi tầng sẽ có nhiều chiêu thức phức tạp nữa. Ví dụ đối với trang web có lượng truy cập khổng lồ, thì sẽ dùng kết hợp cả load balancer và reverse proxy web server chứ không chỉ dùng một cái, DB thì cấu trúc theo kiểu master-slave, có hot standby, failover, lại còn dùng thêm server để cache v.v.

Trong bài viết này, ta dùng cấu trúc giản lược như hình trên để miêu tả giải pháp cho câu hỏi trên.

Chương trình (trang web) = code (app server) + data (DB)

Nâng cấp trang web có thể là nâng cấp một trong 2 cái, hoặc cả 2.

Trường hợp dễ nhất là chỉ nâng cấp code, chỉ thay đổi mã chương trình, giải pháp thường là:
Chỉnh load balancer và/hoặc reverse proxy web server để kết nối không chạy vào app server 1.
Tắt chương trình trên app server 1, thực hiện nâng cấp chương trình.
Bật nó lên lại.
Chỉnh load balancer và/hoặc reverse proxy web server để kết nối chạy vào app server 1 như cũ.
Lặp lại các bước trên cho các app server còn lại.

Đến đây, mặc dù cả code và data đã mới, nhưng ta vẫn giữ cho chương trình như cũ bằng cách cấu hình. Người dùng bình thường nhìn từ bên ngoài (giao diện v.v.) sẽ vẫn thấy các thứ chưa có gì thay đổi, nhưng thực ra nội tạng chương trình đã sẵn sàng để bật sang trạng thái mới. Bí quyết ở đây là chương trình được tích hợp hệ thống gọi là feature flag, để người vận hành có thể bật tắt các tính năng. Việc thiết kế hệ thống feature flag này là đề tài cũng rất thú vị, sẽ đề cập ở bài viết khác.
Bước 4: Bật feature flag để ban đầu chỉ thử nghiệm tính năng mới cho một vài người dùng. Nếu thấy ổn thì sẽ bật cho tất cả mọi người.
Bước 5: Đến đây trang web đã ổn, có thể dọn dẹp để bỏ đi code và data cũ.

Mấu chốt của giải pháp trên là:

Dùng load balancer và/hoặc reverse proxy web server để người dùng vẫn truy cập được dịch vụ.
Viết code mới sao cho nó xử lí được cả data cũ và mới.

Ở trên, ta thấy có chỗ cần tắt app server để nâng cấp. Nếu dùng một số công nghệ cao cấp như Erlang, thì còn có thể nâng cấp code mà không cần tắt app server (hot code reload)! Chiêu thức này rất hữu dụng cho những hệ thống cần realtime (ví dụ realtime multiplayer games), cần lưu trạng thái vào trong memory của app server luôn để xử lí cho nó nhanh, khi nào thực sự cần lưu trạng thái lâu dài mới phải lưu vào DB. Đây cũng là đề tài thú vị, có thể đề cập ở bài viết khác. Hãy tưởng tượng khi cả trăm ngàn game thủ đang đấu realtime với nhau, bạn vẫn có thể nâng cấp chương trình mà không làm đứt kết nối hoặc gián đoạn trận đấu.