Càng đơn giản càng tốt!

Sau nhiều năm đi làm, vẽ vời đủ thứ, dựng từ hệ thống 1 server cho đến hệ thống mấy chục con server, và bây giờ đang làm trong hệ thống hàng nghìn con server, thì đến thời điểm hiện tại (tất nhiên là theo quan điểm của mình nhé), mình thấy rằng việc chúng ta thiết kế được gọi là tốt phải là một thiết kế bám sát với nghiệp vụ của dự án, không quá đơn giản để dễ dàng bị đánh sập, nhưng cũng không quá lớn để gây lãng phí nguồn lực của tổ chức. Dự án bao giờ cũng được chia thành các giai đoạn khác nhau, và ở giai đoạn bắt đầu, khi còn chưa biết liệu dự án có thành công hay không, thì chúng ta cần lựa chọn một kiến trúc đơn giản, để nhanh chóng ra được sản phẩm chiếm lĩnh thị trường và tiết kiệm được chi phí.

Các thành phần cơ bản

Một hệ thống web cơ bản bao gồm các thành phần:

  1. Load balancer (LB): mục tiêu cơ bản của việc dùng #LB là để:
  • Cân bằng tải: Dữ liệu sẽ được phân bổ cho nhiều #WebServer xử lý để làm tăng tốc độ và giảm tải CPU cũng như RAM cho từng server
  • High Availability (HA): Khi một web server có vấn đề thì vẫn còn các server khác hoạt động và hệ thống của chúng ta sẽ đảm bảo khả năng phục vụ 24/7
  • SSL Termination: Kinh nghiệm thực tế cho thấy việc setup #SSL #Certificate rất hay bị quên, từ công to đến công ty bé nên nếu không quá lo lắng về #Performance hãy set SSL Certificate tập trung ở đây để thuận tiện cho việc vận hành

Còn nhiều mục đích khác để sử dụng LB nhưng hãy dành cho những bài viết khác nhé. Một trong những LB chúng ta hay dùng đó là #nginx, nó tương đối nhẹ, hiệu năng cao và quan trọng nhất với các công ty nhỏ là nó đang miễn phí

  1. Web Server: Là các HTTP server mà chúng ta vẫn viết bằng #SpringBoot #Node.js #PHP, #GoLang hay #.Net đó, các service này chịu trách nhiệm xử lý #request của client do LB phân bổ và trả lại kết quả cho #LB. Thông thường chúng ta sẽ chạy tối thiểu 2 web server để đảm bảo #HA
  2. Memory Cache server: Dùng để lưu các thông tin cần được chia sẻ giữa các Web Server và yêu cầu tốc độ truy xuất nhanh, từ trước giờ mình hay token của user ở đây, và mình không sử dụng #jwt token đâu nhé, mình toàn dùng #sha256 token cho ngắn gọn. Mình cũng thường dùng #Redis và thường tổ chức theo kiểu #Sentinel (có thể hiểu đơn giản là mô hình #Replication, sẽ có 1 con làm #master và 1 đến 2 con làm #slave, dữ liệu ở các con này sẽ giống y chang nhau để master có tèo thì vẫn có slave lên thay thế).
  3. Database: Đương nhiên rồi, hệ thống nào thì cũng cần có #Database để lưu trữ dữ liệu lâu dài, MySQL vẫn là lựa chọn số 1 vì nó vẫn phù hợp với đa phần các bài toán nghiệp vụ (cho web) hiện nay, nó miễn phí và có cộng đồng rất lớn. Mình thường tổ chức theo mô hình #Replication để đảm bảo HA cho hệ thống.

Cấu hình tối thiểu

Chắc hẳn nhiều anh em đang thắc mắc là chúng ta nên lựa chọn cấu hình cho server thế nào cho phù hợp và với từng cấu hình thì sẽ chịu được bao nhiêu request/giây đúng không? Mình thường hay lựa chọn thế này:

  1. Nginx: 16GB RAM, 8 Cores CPU, vì con này chủ yếu xử lý I/O và thêm phần SSL Termination nên nó tương đối ngốn RAM và CPU
  2. Webserver: 4G RAM, 4 Cores CPU, vì các con này chủ yếu xử lý logic nên cũng khá tốn CPU, tuy nhiên là mình nên có nhiều WebServer để làm HA cho tốt
  3. Redis: 8GB RAM, 4Cores CPU: Cấu hình cao như thế này nhưng với hệ thống cả triệu user chắc cũng chỉ dùng hết 4GB RAM là căng
  4. MySQL: 16GB RAM, 8 Cores CPU: Đương nhiên rồi Database lúc nào cũng sẽ ngốn rất nhiều RAM và CPU do nó phải cache dữ liệu và xử lý query

Với cấu hình như thế này có khả năng sẽ chịu được trung bình từ 5000 đến 10000 request / giây tùy vào nghiệp vụ Nhưng thực tế đây là cấu hình cho công ty nhà giàu, còn nếu công ty các bạn còn nghèo, hãy chia các cấu hình cho 4 nhé. Và nếu vẫn còn cảm thấy lăn tăn về chi phí thì có thể chọn cấu hình như này:

  1. Nginx: 2GB RAM, 2 Cores CPU
  2. Webserver: 1G RAM, 1 Cores CPU
  3. Redis: 2GB RAM, 1Cores CPU
  4. MySQL: 4GB RAM, 4 Cores CPU

Cân nhắc dùng memory caching

Như đã nói ở bài trước, việc dùng memory cache là không bắt buộc, nếu bạn cảm thấy nó quá lằng nhằng, đội chi phí, hãy bỏ nó đi. Việc thiết kế hệ thống hãy bám sát yêu cầu nghiệp vụ, giảm thiểu chi phí phát triển và vận hành cho doanh nghiệp.

Tổng kết

Sau bao nhiêu dự án, bao nhiêu hệ thống và cũng là bao nhiêu đau thương mình đã nhận ra rằng, việc thiết kế hệ thống càng đơn giản gọn nhẹ càng tốt, nếu có thể #scale theo chiều ngang (tăng số lượng server) được thì tăng, không thì cứ tăng cấu hình của server lên mà chạy, một con server 200GB, 300GB RAM cũng được, miễn là hàng tháng nó vẫn kiếm cả triệu đô, tỉ đô để làm trụ cột cho doanh nghiệp trước, đến khi có tiền rồi, chúng ta sẽ xây dựng những hệ thống khác ngon lành cành đào và phù hợp với tư tưởng của chúng ta hơn.

Tư duy tiết kiệm

Có lẽ nhiều anh em sẽ thắc mắc sao mình hay nói đến "chi phí doanh nghiệp" và sẽ cười mình, 😃. Đó là điều thú vị khi chúng ta luôn nghĩ rằng ông chủ của công ty nào cũng rất giàu. Nhưng kì thực không hẳn như vậy. Có nhiều người phải bán nhà bán cửa để hiện thực hóa ước mơ của mình, có những bạn sinh viên, những bạn đang đi làm có mơ ước startup, và đang nỗ lực từng ngày với từng đồng lương ít ỏi, chi phí thuê server hàng tháng sẽ luôn là gánh nặng. Nên trong giai đoạn doanh nghiệp còn nhỏ, còn ít tiền, hãy luôn tiết kiệm, để dành những đồng tiền quý giá vào những việc có ích hơn nhé, 🙂

Tham khảo

  1. https://www.digitalocean.com/community/tutorials/an-introduction-to-haproxy-and-load-balancing-concepts
  2. https://redis.io/topics/sentinel
  3. https://www.toptal.com/mysql/mysql-master-slave-replication-tutorial
  4. https://www.nginx.com/blog/testing-the-performance-of-nginx-and-nginx-plus-web-servers/
  5. https://www.digitalocean.com/pricing