Giúp website của bạn nhanh lên gấp N lần với Nginx

Nginx là gì, ảnh hưởng như nào tới tốc độ trang web

Web server là gì ?

Máy chủ Web (Web Server) là máy tính mà trên đó cài đặt phần mềm phục vụ web, đôi khi người ta cũng gọi chính phần mềm đó là web server. Tất cả các web server đều hiểu và chạy được các file *.htm và *.html. Tuy nhiên mỗi web server lại phục vụ một số kiểu file chuyên biệt chẳng hạn như llS của Microsoft dành cho *.asp, *.aspx…; Apache, Nginx dành cho *.php…; Sun Java system web server của SUN dành cho *.jsp…

Ở phần lõi của máy chủ web là một dịch vụ web phục vụ nội dung tĩnh cho một trình duyệt bằng cách tải một tập tin từ đĩa và chuyển nó lên mạng, tới một người sử dụng trình duyệt web. Sự trao đổi hoàn toàn này được thực hiện gián tiếp thông qua một trình duyệt và một máy chủ kết nối tới một thiết bị khác sử dụng HTTP. Bất kỳ máy tính nào cũng có thể vào trong một dịch vụ web bằng cách cài đặt phần mềm dịch vụ và kết nối internet.

Máy Web Server là máy chủ có dung lượng lớn, tốc độ cao, được dùng để lưu trữ thông tin như một ngân hàng dữ liệu, chứa những website đã được thiết kế cùng với những thông tin liên quan khác. (các mã Script, các chương trình, và các file Multimedia)

Web Server có khả năng gửi đến máy khách những trang Web thông qua môi trường Internet qua giao thức HTTP – giao thức được thiết kế để gửi các file đến trình duyệt Web (Web Browser), và các giao thức khác.

Tất cả các Web Server đều có một địa chỉ IP (IP Address) hoặc cũng có thể có một Domain Name. Giả sử khi bạn đánh vào thanh Address trên trình duyệt của bạn một dòng http://www.abc.com sau đó gõ phím Enter bạn sẽ gửi một yêu cầu đến một Server có Domain Name là www.abc.com. Server này sẽ tìm trang Web có tên là index.htm rồi gửi nó đến trình duyệt của bạn.

Bất kỳ một máy tính nào cũng có thể trở thành một Web Server bởi việc cài đặt lên nó một chương trình phần mềm Server Software và sau đó kết nối vào Internet.

Khi máy tính của bạn kết nối đến một Web Server và gửi đến yêu cầu truy cập các thông tin từ một trang Web nào đó, Web Server Software sẽ nhận yêu cầu và gửi lại cho bạn những thông tin mà bạn mong muốn.

Giống như những phần mềm khác mà bạn đã từng cài đặt trên máy tính của mình, Web Server Software cũng chỉ là một ứng dụng phần mềm. Nó được cài đặt, và chạy trên máy tính dùng làm Web Server, nhờ có chương trình này mà người sử dụng có thể truy cập đến các thông tin của trang Web từ một máy tính khác ở trên mạng (Internet, Intranet).

Web Server Software còn có thể được tích hợp với CSDL (Database), hay điều khiển việc kết nối vào CSDL để có thể truy cập và kết xuất thông tin từ CSDL lên các trang Web và truyền tải chúng đến người dùng.

Server phải hoạt động liên tục 24/24 giờ, 7 ngày một tuần và 365 ngày một năm, để phục vụ cho việc cung cấp thông tin trực tuyến. Vị trí đặt server đóng vai trò quan trọng trong chất lượng và tốc độ lưu chuyển thông tin từ server và máy tính truy cập.

Nginx

Nginx là 1 máy chủ reverse proxy mã nguồn mở cho các giao thức HTTP, HTTPS, SMTP, POP3 và IMAP, cũng như là 1 máy chủ cân bằng tải (load balancer), HTTP cache và web. Dự án Nginx được bắt đầu với việc tập trung vào tính đồng thời cao, hiệu năng cao và sử dụng tài nguyên thấp và được phát triển bởi Igor Sysoev vào nằm 2002, được phân phối ra công chúng lần đầu vào nằm 2004.

Không giống với các máy chủ web truyền thống, Nginx không dựa trên luồn (thread) để xử lý yêu cầu. Thay vào đó, nó sử dụng 1 kiến trúc bất đồng bộ hướng sự kiện linh hoạt . Kiến trúc này sử dụng ít, nhưng quan trọng hợn, là lượng bộ nhớ có thể dự đoán khi hoạt động. Đây chính là điểm mấu chốt khiến Nginx là 1 trong số ít những máy chủ được viết để giải quyết vấn đề C10K

Nói đến đây một số bạn sẽ tò mò là vấn đề C10K là gì ? Hiểu đơn giản thì do các máy chủ web truyền thống xử lý các yêu cầu dựa trên luồn (thread), tức là mỗi khi máy chủ web nhận được 1 yêu cầu mới, nó sẽ tạo ra 1 luồng mới để xử lý cho yêu cầu này, và cứ thế khi số lượng các yêu cầu gửi đến máy chủ web ngày càng nhiều thì số lượng các luồn xử lý này trong máy chủ sẽ ngày càng tăng. Và điều này dẫn đến việc thiếu hụt tài nguyên cấp cho các luồn xử lý trên ... (Các bạn có thể tìm hiểu rõ hơn tại đây)

Hiện nay, có khoảng 14,72 % (hơn 137 triệu) các website trên Internet đang sử dụng Nginx là máy chủ web.

Sử dụng nginx thế nào cho tốt

Nginx là một giải pháp hoàn hảo có thể giúp cho bạn rất nhiều thứ, từ reverse proxy, đến deliver static file (như là css/js/image), đến load balancing. Việc hiểu rõ nginx có thể làm gì ở trên, và bạn có thể tuỳ chỉnh gì,

Loại bỏ các limitation ở tầng kernel

Để có thể tận dụng tốt nginx thì đôi khi có nhiều limit ở tầng kernel vốn được setup default mà không phù hợp. Những setting mà tôi nói đến dưới đây được chỉnh ở file /etc/sysctl.conf.

net.core.somaxconn: Đây là số lượng connection max mà được nginx queue (buffering) trước khi xử lý. Access càng nhiều -> nginx sẽ không xử lý kịp và phải buffer vào queue, queue càng lớn, buffer càng nhiều, block càng ít, sẽ làm nginx tăng lên tương đối

net.ipv4.iplocalportrange: Khi sử dụng nginx dưới dạng một reverse proxy, thì mỗi một connection đến proxy sẽ sử dụng một ephemeral ports, do đó khi access nhiều sẽ dấn đên nhanh hết port, dấn đến blocking. Tăng chỉ số này sẽ giúp connection đến upstream được nhiều hơn, giúp ít blocking hơn

sys.fs.filemax: Đây là số file descriptor max mà linux server có thể sử dụng được, mà như bạn đã biết socket trên linux là file, do đó chỉ số này càng lớn, nginx mở đc càng nhiều socket, sẽ giúp cho max connection tăng.

net.ipv4.tcpwmem và net.ipv4.tcprmem: đây là 2 chỉ số của kernel để buffering cho TCP/IP. Nói chung là càng to càng tốt.

Dưới đây là bộ config được recommend cho nginx server:

net.ipv4.ip_local_port_range='1024 65000'
net.ipv4.tcp_tw_reuse='1'
net.ipv4.tcp_fin_timeout='15'
net.core.netdev_max_backlog='4096'
net.core.rmem_max='16777216'
net.core.somaxconn='4096'
net.core.wmem_max='16777216'
net.ipv4.tcp_max_syn_backlog='20480'
net.ipv4.tcp_max_tw_buckets='400000'
net.ipv4.tcp_no_metrics_save='1'
net.ipv4.tcp_rmem='4096 87380 16777216'
net.ipv4.tcp_syn_retries='2'
net.ipv4.tcp_synack_retries='2'
net.ipv4.tcp_wmem='4096 65536 16777216'
vm.min_free_kbytes='65536'

Phân tích log nginx để tìm bottle neck

Phân tích access log từ nginx sẽ giúp bạn biết bottle neck ở đâu, có một tool rất đơn giản là https://github.com/matsuu/kataribe

Để sử dụng tool này thì bạn cần setting nginx log format sử dụng directive

log_format with_time '$remote_addr - $remote_user [$time_local] '
                                      '"$request" $status $body_bytes_sent '
                                      '"$http_referer" "$http_user_agent" $request_time';
access_log /var/log/nginx/access.log with_time;

Caching with nginx

Nginx khi sử dụng để server static file thì bạn nên để ý kĩ các setting về cache, và compression. Setting sử dụng gzip cho static file cũng rất quan trọng. Sử dụng gzip sẽ giúp giảm rất nhiều cost liên quan đến IO, và đường truyền. Setting cache control sẽ giúp server không request lại static file đó nữa cho đến khi cache expire. Bạn có thể tham khảo setting dưới đây.

http {
    gzip              on;
    gzip_http_version 1.0;
    gzip_types        text/plain
                      text/html
                      text/xml
                      text/css
                      application/xml
                      application/xhtml+xml
                      application/rss+xml
                      application/atom_xml
                      application/javascript
                      application/x-javascript
                      application/x-httpd-php;
    gzip_disable      "MSIE [1-6]\.";
    gzip_disable      "Mozilla/4";
    gzip_comp_level   1;
    gzip_proxied      any;
    gzip_vary         on;
    gzip_buffers      4 8k;
    gzip_min_length   1100;
}

Khi sử dụng nginx dưới dạng reverse proxy, nếu memory của bạn thừa thãi, và lượng data để response cũng không lớn bạn có thể set để nginx cache trên memory thay vì trên file

proxy_cache_path /dev/shm/nginx levels=1:2 keys_zone=czone:16m max_size=32m inactive=10m;

Advance nginx

Một setting cũng rất hay được sử dụng là keepalive. Thông thường keep alive là một technique của http giúp "giữ" connection TCP lại ngay cả khi HTTP connection session đã kết thúc, để có thể reuse lại cho request tiếp theo. Trong trường hợp implement thường HTTP client tạo 1 kết nối TCP tới server đích, gửi request và nhận response. Sau đó server đóng lại kết nối.

Technique này rất có lợi khi mà thông thường một user sẽ gửi rất nhiều request để lấy cả static resource.

Để tìm hiểu kĩ hơn về mục đihcs của technique này, bạn có thể đọc thêm ở đây https://www.nginx.com/blog/http-keepalives-and-web-performance/

Sử dụng keepalive trên nginx rất đơn giản bằng cách thêm directive keepalive vào trong upstream section

 upstream app {
      server 127.0.0.1:5000;
      keepalive 16;
    }