Vào thời điểm này, một server Web cỡ trung bình (8 cores, 24GB RAM) cũng có thể xử lý hàng trăm, thậm chí hàng nghìn truy vấn mỗi giây. Tất nhiên, nếu đủ kinh phí, bạn còn có thể thuê server khủng hơn nữa. Tuy nhiên, bạn vẫn cần những kỹ thuật nâng cao hiệu suất, đảm bảo rằng bạn không lãng phí tài nguyên và tiền bạc.
Rất nhiều thủ thuật ở đây, bạn có thể áp dụng ngay với ứng dụng Web của mình mà không cần phải nghiên cứu bất cứ công nghệ nào.
//Tài nguyên tĩnh
Hãy đặt các tài nguyên tĩnh (CSS, JavaScript, ảnh, v.v…) lên CDN (Content Delivery Network). Nó sẽ giúp bạn phân phối những tài nguyên này một cách hiệu quả thông qua mạng lưới PoP (Point of Presence). Việc sử dụng CDN sẽ giúp giảm áp lực cho server Web, nâng cao hiệu suất của ứng dụng Web của bạn và cho phép bạn có thể mở rộng vô hạn (tài nguyên tĩnh) ứng dụng của mình.
Các tài nguyên này nên có tên duy nhất cho nội dung của nó, phân biệt nó với các tài nguyên khác và phân biệt các phiên bản khác nhau của chính nó. Ví dụ, khi bạn thay đổi nội dung JavaScript của ứng dụng, asset pipeline của bạn nên compile và đặt lại tên mới cho file này. Tên này nên khác với tên của phiên bản cũ.
Việc này sẽ giúp việc lưu cache trên trình duyệt hiệu quả hơn. Mỗi khi truy cập trang Web, trình duyệt sẽ cache lại nội dung của những tài nguyên tĩnh này và lần sau truy cập, nó sẽ không cần file load lại file nữa. Nếu mỗi phiên bản của file lại có một tên khác nhau, thì khi người dùng vào trang Web đã cập nhật, họ sẽ không bị lỗi layout hay bất cứ lỗi gì khác liên quan đến CSS, JavaScript do tên file đã thay đổi nên cache cũ không còn được dùng nữa.
Có một cách đơn giản về đặt tên đó là sử dụng SHA-256 của nội dung chính file đó làm tên file. Cách này khá hay, khi bạn thay đổi nội dung bên trong, SHA-256 cũng sẽ thay đổi và bạn sẽ có file mới với tên mới.
//Session
Nếu có thể, bạn nên lưu session bằng cookie kèm chữ ký (mã hóa nữa thì càng tốt). Việc này sẽ giúp bạn giảm bớt xử lý trên server do không cần phải truy vấn đến cơ sở dữ liệu trong trường hợp này. Bạn nên sử dụng TLS cho mọi kết nối, và đặt các thuộc tính bảo mật cho cookie. Và với các thao tác đính kèm chữ ký, mã hóa, xác thực, giải mã, v.v tốt nhất bạn không nên tự cài đặt bằng tay mà nên sử dụng các thư viện có sẵn, ví dụ itsdangerous.
Nếu cookie kèm chữ ký không phù hợp với ứng dụng của bạn vì một lý do nào đó (ví dụ kích thước payload quá lớn), thì bạn có thể chuyển sang sử dụng cách lưu trữ key-value đơn giản hơn. Với hầu hết các ứng dụng, bạn có thể sử dụng một số hệ thống hỗ trợ lưu trữ dạng này như memcached hay redis chẳng hạn.
//Load balance
Web server của bạn không thể đảm bảo là luôn chạy ổn định. Vì vậy hãy đặt chúng sau một load balancer ngay từ khi thiết kế. Việc này rất quan trọng, load balancer sẽ phân phối kết nối đến các Web server của bạn giúp chúng hoạt động trơn tru, hiệu quả và tránh bị quá tải.
Hãy thử thêm vào bớt các server sau load balancer. Mọi thao tác rất đơn giản và an toàn khi thêm vào những server mới và loại bỏ server cũ khi nó không phù hợp nữa.
Nếu load balancer khiến bạn phải sử dụng cách giải pháp phân tán, bạn nên hạn chế số lượng kết nối bên trong hệ thống.
Và một điều quan trọng nữa là, hãy thiết lập load balancer thực hiện health check với các server định kỳ.
//Lưu trữ dữ liệu
Với những dữ liệu do người dùng upload lên, và những lưu trữ tương tự (các tài nguyên tĩnh nhưng không phải là một phần của trang), hãy sử dụng dịch vụ của bên thứ ba. Rất nhiều người sử dụng dịch vụ S3 của Amazon. Đây là một giải pháp tốt, dễ dùng, ổn định mà không đắt.
Hãy tránh việc lưu trữ trên chính Web server của mình. Nó có thể gặp một số vấn đề khi bạn có nhiều instance Web mà người dùng chỉ upload lên một trong số chúng. Việc lưu trữ trên chính server Web cũng khiến chúng ta khó mở rộng ứng dụng. Hãy sử dụng các dịch vụ lưu trữ bên ngoài.
//Cơ sở dữ liệu
Với phần lớn các ứng dụng, hệ cơ sở dữ liệu quan hệ là đủ để ứng dụng hoạt động tốt. Tuy nhiên, bạn cần cẩn thận tắc cổ chai. Các ứng dụng thường bị tắc cổ chai khi đọc dữ liệu từ database hơn là ghi dữ liệu.
Nếu cần, bạn có thể thiết lập replica cho cơ sở dữ liệu. Việc này hoàn toàn không khó. Hãy theo dõi thời gian phản hồi của toàn hệ thống cơ sở dữ liệu.
Với những công tụ quản trị trang Web (báo cáo trạng thái, dashboard hay các trang admin khác) có thể có những truy vấn riêng đến replica được chỉ định. Việc này có thể khiến dữ liệu thống kê khác nhau giữa các truy vấn. Và việc kết hợp chúng trên cùng một server có thể làm giảm hiệu suất do phải cache quá nhiều.
Nếu bạn cần thay đổi cấu trúc cơ sở dữ liệu, đừng bao giờ giả định rằng quá trình này sẽ diễn ra rất nhanh. Code ứng dụng của bạn nên chuẩn bị sẵn sàng ứng phó với 3 trạng thái: trước khi migrate, trong khi migrate và đã migrate xong. Ví dụ, nếu bạn cần thêm một cột vào bảng đang có, quá trình thực hiện có thể như sau:
- Thêm một cột mới vào cơ sở dữ liệu (cột này nên để nullable)
- Deploy code mới để ghi dữ liệu vào cột này.
- Chạy một script khác để điền những dữ liệu vào các bản ghi đang có.
- Kiểm tra thông tin được ghi đầy đủ và chính xác.
- Cuối cùng, deploy code mới để đọc dữ liệu từ cột này.
//Deploy và tự động hóa
Mọi thao tác với server nên được code vào trong ứng dụng. Hãy thử tự động hóa các thao tác. Thêm và bớt các server bất cứ khi nào bạn muốn.
Kỹ thuật “dark read” là một kỹ thuật rất thích hợp để test và kiểm tra khả năng đáp ứng yêu cầu của tính năng mới. Dark read nghĩa là những người truy cập trang sẽ truy vấp đến tính năng đó một cách “âm thầm” (ví dụ bằng AJAX), nhưng không xử lý bất cứ điều gì khi có kết quả trả về. Nó sẽ giúp bạn ước lượng hiệu năng của tính năng mới thông qua việc kiểm tra lượng truy vấn tương đối giống thực tế.
Một kỹ thuật khác cũng rất thích hợp để kiểm tra tính năng mới đó mà “feature flag”. Thay vì bạn phải tạo các nhánh test và xây dựng môi trường test riêng biệt, bạn có thể dùng “feature flag” để deploy tính năng mới nhưng chỉ áp dụng với nhóm nhỏ người dùng. Đây là kỹ thuật mà Facebook vẫn thường áp dụng với những tính năng mới của họ.
Dark read và feature flag có thể kết hợp với nhau rất tốt. Bạn có thể deploy dark read cho một tính năng mới, sử dụng feature flag, chỉ áp dụng với một nhóm nhỏ người dùng. Sau đó từ từ tăng số lượng người được áp dụng lên, bạn có thể tính toán và ước lượng số lượng truy vấn cần xử lý, thực hiện tối ưu hóa nếu cần. Cuối cùng, khi đã tự tin về tính năng này, bạn có thể công bố nó rộng rãi tới người dùng.