Web Scalability 101: Biết giới hạn của hệ thống

trong danh mục Technology

scalability
Sau mấy tuần vật lộn với công việc sau Tết thì cũng có thời gian viết lách. Đây là bài viết về kỹ thuật đầu tiên của năm và là bài đầu tiên trong loạt bài chia sẻ về các chiến thuật scaling hệ thống web có tên là “Web scalability 101 (vỡ lòng)”.

Nếu quan tâm đến scale hệ thống, bạn có thể google những từ khóa liên quan đến scale, ngôn ngữ, công nghệ mà hệ thống bạn đang sử dụng, và phần lớn là các bài viết chỉ về các cài đặt, cấu hình cụ thể của một công nghệ nào đó như tùy chỉnh PHP thế nào, tùy chỉnh nginx, tùy chỉnh mysql ra sao…và có thể bạn sẽ lạc trong một mớ hỗn độn các kiến thức cấu hình này.

Mình không nói cách tiếp cận này là sai, nhưng nếu chỉ theo hướng này thì bạn sẽ không thể nào lường trước được khi tiếp cận công nghệ mới, hướng này là chưa đủ. Bạn cần một cách tiếp cận ở mức căn bản, nền tảng hơn và khi nắm được các kiến thức nền tảng thì mình nghĩ việc vì sao mình cấu hình php, mysql, nginx hoặc thay đổi kiến trúc sang microservice sẽ trông có vẻ rõ ràng và cụ thể hơn trước khi bắt tay vào triển khai. Và đó là mục tiêu của loạt bài “vỡ lòng” này.

Nội dung đầu tiên mà mình muốn chia sẻ và cực kỳ quan trọng khi bạn muốn bắt tay vào scale hệ thống, đó là phải biết được giới hạn của hệ thống hiện tại. Bởi vì chỉ khi bạn biết được giới hạn của hiện tại thì các nâng cấp, cải tiến sẽ mở rộng được giới hạn này và lượng hóa được khả năng của hệ thống trong tương lai. Có 2 loại giới hạn rõ ràng đó là giới hạn công nghệ và giới hạn của stack mà bạn đang sử dụng.

Giới hạn công nghệ

Nhóm này mình chia thành một số nhánh rõ ràng như là giới hạn của dung lương lưu trữ dữ liệu, tốc độ đọc ghi dữ liệu, tốc độ truyền dẫn dữ liệu và tốc độc xử lý dữ liệu. Biết được các giới hạn này sẽ giúp bạn dễ dàng tính toán được các giới hạn trần khi sử dụng một công nghệ nào đó. Ví dụ khi ghi dữ liệu vào ổ SSD của hãng X thì không thể nào nhanh hơn tốc độ A/s…

Giới hạn của công nghệ là thông tin khá dễ biết vì nó là các tiêu chuẩn của ngành hoặc 1 nhà sản xuất…Tùy theo nhu cầu của hệ thống bạn mà bạn sẽ quan tâm đến các số liệu nào. Mình không bàn nhiều về giới hạn này vì hầu như bạn không thể thay đổi các giới hạn này, trừ khi bạn là nhà chế tạo hoặc cải tiến các công nghệ hiện tại.

Bạn có thể tham khảo link sau với nội dung “Latency Numbers Every Programmer Should Know” (https://gist.github.com/jboner/2841832)

Giới hạn của stack

Các giới hạn này liên quan trực tiếp đến hệ thống mà bạn đang xây dựng. Ví dụ hệ thống của bạn một giây phục vụ được bao nhiêu request và có thể cải tiến được hơn nữa không. Áp dụng công nghệ X,Y,Z vào sẽ cải tiến được bao nhiêu…Việc đo đếm các giới hạn này không đơn giản và nếu một action của bạn lệ thuộc vào nhiều công nghệ, phần mềm thì việc cải tiến sẽ phức tạp hơn rất nhiều. Ví dụ 1 web request bạn có xử lý đụng đến đọc ghi dữ liệu database, đọc ghi file, gọi web service khác, tính toán thì việc cải thiện giới hạn bằng cách xem xét các thành phần cụ thể.

Tính toán giới hạn của web server

Ở đây mình sẽ lấy một ví dụ cụ thể về việc tính toán được giới hạn của web server sử dụng PHP và nginx để hình dung được bức tranh và có thể giúp ra quyết định scale. Cho đề bài sau:
– Bạn đang có 1 server có 2GB Ram
– Chạy 4 PHP worker process (xử lý đồng thời 4 request 1 thời điểm)
– Mỗi PHP worker process tốn 20MB Ram
– Mỗi request trung bình xử lý 100ms.
Câu hỏi: Mỗi giây server này phục vụ được tối đa bao nhiêu request. Và có thể nâng lên tối đa bao nhiêu request nếu không muốn đầu tư server cấu hình mạnh hơn.

Nếu mỗi request chiếm 100ms của process thì 1 giây mỗi process có thể phục vụ 10 request. Chúng ta có 4 process có nghĩa là mỗi giây chúng ta có 4×10 request có nghĩa là với cấu hình hiện tại, server này phục vụ tối đa 40 request. Nếu quá con số request này truy cập vào server thì các request sau sẽ chờ cho đến khi các request trước đó xử lý xong. Và tùy theo “ứng xử” của hệ thống, nếu chờ quá lâu thì sẽ bỏ/hủy request này và thông báo lại cho người dùng.

Để cải tiến được giới hạn này, chúng ta cần xem xét các thông tin tham gia vào bài toán. Hiện tại có 3 tham số khả dụng sẽ giúp cải tiến. Đó là số process có thể tăng thêm để tận dụng ram trống, vì hiện tại ram của server là 2G, giả sử dành 200M cho các xử lý khác của hệ thống thì còn thừa 1.8G (~1800MB Ram), như vậy, ta có thể tăng lên 1800/20=90 process. Theo như phần trước thì mỗi process xử lý được 10 request thì nếu có 90 process thì xử lý được 900req/s. Như vậy tăng gấp 22.5 lần so với cấu hình đầu.

Ở đây bạn sẽ thấy chưa cần làm gì, chỉ với việc thay đổi cấu hình là đã tăng khả năng phục vụ của hệ thống lên 20 lần. Giả sử team của bạn thấy mình hoàn toàn có khả năng giảm thời gian xử lý trung bình xuống còn 50ms/req, tức là tăng khả năng thêm gấp đôi nữa. Hoặc team bạn sử dụng công nghệ khác giúp tối ưu bộ nhớ của 1 process xuống trung bình còn 10MB Ram, tức là tăng thêm gấp đôi 1 lần nữa.

Lưu ý 1: để biết được dung lượng của 1 process, bạn có thể google để tìm câu lệnh trên linux để biết hoặc có thể đơn giản chạy câu lệnh top để xem process của bạn chiếm bao nhiêu memory.

Lưu ý 2: trong ví dụ trên giả sử bạn đang sử dụng MySQL để truy cập dữ liệu. Giả sử ở 40 req/s thì mysql hỗ trợ OK, nhưng khi lên 900req/s thì Mysql của bạn sẽ quá tải và có thể đã ngưng phục vụ ở 200req/s. Có nghĩa là con số 900 bạn không đạt được do giới hạn của mysql. Như vậy, bạn sẽ thấy bài toán sẽ cần giải thêm 1 cách khác để mở rộng hệ thống vượt ra ngoài con số 200req/s.

Lưu ý 3: đề bài trong ngữ cảnh là các con số trung bình (ram trung bình, thời gian trung bình), trong thực tế có thể có những request tốn nhiều ram hơn nhiều (vd: 500MB), xử lý lâu hơn trung bình rất nhiều (2000-3000ms/req) khiến cho các con số bị sai lệch cũng như treo hệ thống vì với cấu hình 90 process, nếu memory không cấp đủ thì xảy ra tình trạng swap ổ cứng, khiến cho hệ thống bị đơ đơ, nên không phải dùng hết ram cấp cho process là hiệu quả vì nó cũng đi kèm rủi ro hết ram. Đây là nguyên nhân chính vì sao mình phải cần nhiều server để chia tải cho toàn hệ thống.

Như vậy, với việc biết được các phụ thuộc của request thì mình sẽ có những hướng thay đổi, cải tiến phù hợp cho hệ thống. Bài viết này sẽ không đi sâu vào các cấu hình và các giả thuyết mình đặt ra nhằm giúp những bạn nào chưa có kinh nghiệm scale hệ thống hiểu được một phần câu chuyện. Việc đo đạc này sẽ giúp bạn biết được giới hạn của hệ thống, và bạn sẽ có các chiến lược scale khi hệ thống của bạn lên tới ngưỡng phục vụ cảnh báo (vd 80% giới hạn).

Bài tiếp theo mình sẽ nói về kiến trúc microservice sẽ giúp giải bài toán scale mysql như thế nào vì mysql là một trong những thành phần rất khó scale.

Gởi bình luận