Yếu tố phân đoạn là gì trong lập trình web năm 2024

Như đã giới thiệu ở bài trước, mình sẽ giới thiệu về twlve-factor app. Đây là 12 yếu tố cần thiết để xây dựng 1 ứng dụng “xịn xò”, ổn định, dễ mở rộng, dễ deploy.

Trong bài này, mình sẽ giải thích các yếu tố từ 8 tới 12 nhé:

  • 8. Concurrency: Một app nên được chia tách thành nhiều process nhỏ để tăng concurrency
  • 9. Disposability: Process của web app nên sống nhanh, chết nhẹ nhàng, để có thể dễ dàng chạy/kill process nhanh chóng
  • 10. Dev/prod parity: Các môi trường dev/staging/production nên giống nhau hết sức có thể
  • 11. Logs: Logs nên được viết ra dạng stream ở stdout
  • 12. Admin Processes: Một số task dạng admin (tạo database, fix dữ liệu) nên được chạy trong cùng môi trường với app đang chạy

Đây là phần 3 trong series 3 phần về Twelve-Factor App:

  1. Lược dịch và giải thích Twelve-Factor. Giải thích Codebase và Dependencies
  2. Giải thích Config, Backing Service, Build -> Release -> Run, Processes, Port Binding
  3. Giải thích Concurrency, Disposability, Dev/Prod Parity, Logs, Admin Processes

8. Concurrency – Một app nên được chia tách thành nhiều process nhỏ để tăng concurrency

Trong các ngôn ngữ Java, C#, ta thường quản lý concurrency (chạy song snog) thông qua Thread/Task. Các web app này thường được chạy trong 1 process siêu to khổng lồ, sử dụng thread để xử lý nhiều cùng lúc.

Theo khuyến khích của Twelve-Factor App, do CPU và RAM không thể scale tới vô hạn. Vì vậy, để ứng dụng dễ scale, ta nên scale bằng cách chạy nhiều process. Khi cần ta có thể dễ dàng chạy thêm process, hoặc thêm server rồi chạy process của ứng dụng trong server mới.

Ngoài ra, ta cũng nên tách biệt process theo chức năng. Ví dụ những tác vụ hiển thị trang web, cần xử lý song song nhiều, đưa kết quả nhanh cho user thì ta dùng web process. Những tác vụ chạy ngầm (encode file, tính toán nhiều, gọi API ngoài) tốn nhiều thời gian thì ta có thể cho vào worker/background process.

Yếu tố phân đoạn là gì trong lập trình web năm 2024

Nếu các bạn từng deploy ứng dụng NodeJS trên Production, chạy bằng PM2, bạn sẽ thấy nó cũng đi theo mô hình này. PM2 sẽ tạo ra nhiều process NodeJS để scale khi cần.

9. Disposability – Process của web app nên khởi động nhanh, chết nhẹ nhàng

Chuyện kể rằng, ngày xửa ngày xưa, có những dự án Java/Rails siêu to khổng lồ, với những process kinh khủng tớm phải, mỗi lần khởi động phải mất tận 1-2 tiếng mới chạy lên được. Hệ quả là mỗi lần cần release code mới, hoặc phải sửa chữa/nâng cấp server, cả team dev và Operation phải đóng cửa/bảo trì tận 3-4 tiếng để nâng cấp.

Yếu tố phân đoạn là gì trong lập trình web năm 2024
Mỗi lần cần nâng cấp hệ thống là lại downtime cả nửa ngày trời

Do vậy, process của 1 web app nên khởi động càng nhanh càng tốt (vài giây hoặc vài phút). Nhờ vậy, khi cần release phiên bản mới, scale hệ thống, ta có thể dễ dàng chạy lại process, hoặc chạy process trên server mới.

Ngoài ra, process cũng phải chết nhẹ nhàng. Khi hệ thống ra lệnh cho nó chết, nó sẽ làm xong việc (hoặc ngừng) rồi chết chứ không dây dưa. Ví dụ như web process, khi nhận được signal sẽ tự động tắt exit.

Với các process chạy ngầm thì vấn đề này nan giải hơn tí. Ví dụ process đã nhận 1 task từ message queue, nhưng đang xử lý thì … bị giết. Trước khi chết, nó phải tìm cách đưa task đó lại queue, nếu không task đó sẽ không bao giờ được xử lý; dẫn đến lỗi hệ thống, mất dữ liệu.

10. Dev/prod parity – Các môi trường dev/staging/production nên giống nhau hết sức có thể

Một hệ thống trên production thường có rất nhiều thành phần: Web Server, Database, Cache Server, Message Queue, …

Để chạy ứng dụng ở local/staging, dev cũng phải chạy những thứ này, sử dụng version khác hoặc bản nhẹ hơn, mới hơn. Điều này dẫn đến 1 số bug … lạ, chỉ xảy ra ở production mà không xảy ra ở dev, staging.

Yếu tố phân đoạn là gì trong lập trình web năm 2024
Nên đảm bảo các môi trường giống nhau hết mức có thể

Do vậy, ta nên đảm bảo các công nghệ sử dụng ở môi trường dev/staging giống production hết sức có thể! Ví dụ, Production dùng .NET 6.0 + Postgres 12 thì dev/staging cũng nên vậy, đừng đú đởn .NET 7.0 + Postgres 13 để tránh lỗi thư viện, bug không đáng có.

11. Logs – Log nên được viết ra dưới dạng stream và stdout

Logging là một công cụ đơn giản và mạnh mẽ, ghi lại toàn bộ những hoạt động của hệ thống. Nhờ có logging, ta có thể tra cứu lại trạng thái của hệ thống trong quá khứ, những code nào đã được chạy, từ đó tìm ra lỗi và fix dễ dàng hơn.

Mỗi ngôn ngữ như Java, C#, PHP đều có 1 số thư viên phổ biến để quản lý log như log4net, log4j, serilog, … Các thư viện này hỗ trợ ghi log ra file, thiết lập các level log (debug, info, warning).

Twelve-Factor app khuyên rằng ứng dụng không nên tự quản lý log của nó, chỉ gần ghi ra dưới dạng stream trong stdout (giống ghi ra console ấy).

Sau đó, những log này sẽ được các log router như Logplex và Fluentd xử lý thêm bằng cách lưu vào file, gửi tới nguồn khác để lưu trữ, hiển thị trong dashboard v…v

Yếu tố phân đoạn là gì trong lập trình web năm 2024
Các bạn cũng có thể tìm hiểu thêm về ELK Stack để quản lý log

Cá nhân mình thấy lời khuyên này chỉ hữu ích nếu bạn deploy app lên cloud/heroku/Kubernetes. Nếu các bạn chạy app trên VPS hay server thì cứ log file như thường hoặc dùng ELK cũng được nhé.

12. Admin Processes – Một số task dạng admin (tạo database, fix dữ liệu) nên được chạy trong cùng môi trường với app đang chạy

Trong quá trình phát triển app, đôi khi bạn sẽ cần chạy 1 số task dạng admin, chỉ chạy 1 lần như sau:

  • Migrate database và dữ liệu (thêm/sửa table hoặc cột). (Chạy rake db:migrate hoặc npm run migrate)
  • Chạy script để sửa dữ liệu, xoá bỏ dữ liệu thừa (python scripts/fix_money.py hoặc node scripts/fix.js)
  • Truy cập REPL của Python, Rails để kiếm tra dữ liệu, chạy thử hàm

Những script này nên được để cùng với codebase để đảm bảo code của scripts luôn là code mới nhất! Mấy anh developer/opeator sẽ ssh vào server đang chạy code production để chạy các script này, đảm bảo script chạy ở cùng môi trường với app đang chạy.

Tạm kết

Như đã nói ở phần 1, 12 lời khuyên này chỉ là kinh nghiệm và khuyến cáo, phù hợp với các ứng dụng web chạy trên cloud, các app sử dụng kiến trúc microservice.

Với các ứng dụng cũ hơn, chạy trên server vật lý, bạn vẫn có thể áp dụng 1 số lời khuyên để ứng dụng chạy ổn định hơn, dễ quản lý và bảo trì hơn nhé.

Các nội dung mình chia sẻ trong bài hơi nặng tính chuyên ngành, đôi khi khó hiểu nếu bạn chưa áp dụng vào dự án thực tế. Do vậy, nếu có đoạn nào không hiểu, các bạn cứ comment để mình giải thích kĩ hơn nha!