Mục lục
Tìm hiểu về NGINX
NGINX là gì?
NGINX là một máy chủ web mã nguồn mở mạnh mẽ và được biết đến rộng rãi trong việc phục vụ các trang web qua giao thức HTTP.
Với việc sử dụng kiến thức đơn luồng, kỹ thuật đồng bộ không đồng bộ (asynchronous), NGINX đạt được hiệu suất và ổn định cao, trở thành lựa chọn ngày càng phổ biến hơn so với Apache server. Nó có khả năng thực hiện các nhiệm vụ như cân bằng tải, caching HTTP, cũng như hoạt động như một reverse proxying, streaming media, và proxy email cho các giao thức như IMAP, POP3, và SMTP…
Web server này được sáng tạo bởi Igor Sysoev, một nhân viên của công ty Rambler Media Group, vào năm 2002. Ông Igor bắt đầu phát triển Web server này với mục tiêu ban đầu là giải quyết vấn đề về tải đồng thời trên các trang web của Rambler, một trong những trang web lớn tại Nga. Dựa trên kinh nghiệm của mình làm việc với các máy chủ web trước đó, ông Sysoev đã xây dựng NGINX với một kiến trúc sử dụng mô hình đồng thời không đồng bộ (event-driven) thay vì mô hình đồng bộ truyền thống. Điều này giúp NGINX có thể xử lý đồng thời hàng nghìn kết nối mà không làm giảm hiệu suất.
Với lợi thế về tốc độ, độ tin cậy và khả năng mở rộng mạnh mẽ, nhiều đại diện lớn trong ngành công nghiệp công nghệ như Google, Netflix, Adobe, Cloudflare, WordPress,… đều chọn Web server này làm phần quan trọng trong cơ sở hạ tầng của họ.
Các cột mốc quan trọng của NGINX
- Năm 2002 – sáng tạo: Igor Sysoev, một nhân viên của Rambler Media Group ở Nga, bắt đầu phát triển Web server này để giải quyết vấn đề về tải đồng thời trên trang web của Rambler.
- Năm 2004 – phiên bản đầu tiên: Web server này được phát hành lần đầu tiên dưới dạng mã nguồn mở vào tháng 10 năm 2004, đánh dấu bước khởi đầu chính thức của nó.
- Năm 2008 – phiên bản 1.0: Web server này đạt đến bản 1.0, chỉ số mốc quan trọng cho sự ổn định và tin cậy của nền tảng.
- Năm 2011 – phổ biến trên toàn thế giới: Web server này trở thành một trong những máy chủ web phổ biến nhất trên toàn thế giới, được sử dụng rộng rãi bởi các trang web lớn và doanh nghiệp.
- Năm 2013 – NGINX, INC.: Công ty NGINX, Inc. được thành lập để hỗ trợ phát triển và cung cấp dịch vụ hỗ trợ cho Web server này. Igor Sysoev chuyển từ vị trí CTO tại Rambler sang làm CTO tại NGINX, Inc.
- Năm 2016 – NGINX Plus và Merger: NGINX, Inc. giới thiệu NGINX Plus, một phiên bản có thương mại và tính năng mở rộng của Web server này. F5 Networks mua lại NGINX, Inc. trong một thương vụ trị giá hơn 670 triệu USD.
- Năm 2019 – Phiên bản 1.16 và 1.17: Web server này phát hành các phiên bản mới, mang đến cải tiến về hiệu suất và tính năng.
- Ngày nay – sự phát triển và đa nhiệm: Web server này tiếp tục được sử dụng rộng rãi, không chỉ là máy chủ web mà còn là giải pháp đa nhiệm cho bộ cân bằng tải, proxy ngược, và nhiều ứng dụng mạng khác. Web server này đã trải qua một hành trình ấn tượng từ sự sáng tạo đến trở thành một trong những công cụ quan trọng trong ngành công nghiệp web và mạng.
NGINX Docker
NGINX Docker là một phiên bản của máy chủ web NGINX được đóng gói trong một container Docker. Docker là một nền tảng ảo hóa hàng đầu, giúp đơn giản hóa quá trình triển khai ứng dụng bằng cách đóng gói chúng và tất cả các phụ thuộc của chúng vào các container.
NGINX Docker cung cấp một cách thuận tiện để triển khai và quản lý máy chủ web NGINX mà không cần cài đặt và cấu hình trực tiếp trên hệ điều hành mục tiêu.
Khi sử dụng NGINX Docker, bạn có thể triển khai nhanh chóng một môi trường web mà không lo lắng về các vấn đề phức tạp của cài đặt và cấu hình truyền thống. Containerization giúp tăng khả năng di động, linh hoạt và quản lý dễ dàng trong quá trình triển khai ứng dụng web của bạn.
Cài đặt NGINX
Cài đặt NGINX
Hiện nay NGINX đã được sử dụng rộng rãi và trở nên phổ biến, nên việc cài đặt khá đơn giản bằng lệnh sau:
# Cài đặt NGINX
sudo apt-get update
sudo apt-get install nginx
# Kiểm tra version
sudo nginx -v
Tìm hiểu tệp cấu hình của NGINX
Thư mục chính của NGINX là /etc/nginx/ trong đó tệp tin quan trọng là nginx.conf và thư mục sites-available.
Máy tôi sử dụng Ubuntu 18.04.6 LTS, sau khi cài đặt thì nginx ở version 1.14.0 và cấu hình mặc định trong tệp nginx.conf như sau:
user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 768;
# multi_accept on;
}
http {
##
# Basic Settings
##
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
# server_tokens off;
# server_names_hash_bucket_size 64;
# server_name_in_redirect off;
include /etc/nginx/mime.types;
default_type application/octet-stream;
##
# SSL Settings
##
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
ssl_prefer_server_ciphers on;
##
# Logging Settings
##
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
##
# Gzip Settings
##
gzip on;
# gzip_vary on;
# gzip_proxied any;
# gzip_comp_level 6;
# gzip_buffers 16 8k;
# gzip_http_version 1.1;
# gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
##
# Virtual Host Configs
##
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
#mail {
# # See sample authentication script at:
# # http://wiki.nginx.org/ImapAuthenticateWithApachePhpScript
#
# # auth_http localhost/auth.php;
# # pop3_capabilities "TOP" "USER";
# # imap_capabilities "IMAP4rev1" "UIDPLUS";
#
# server {
# listen localhost:110;
# protocol pop3;
# proxy on;
# }
#
# server {
# listen localhost:143;
# protocol imap;
# proxy on;
# }
#}
Trong tệp nginx.conf, có các cấu hình bạn cần quan tâm:
- worker_processes: Thiết lập này định nghĩa số worker processes mà NGINX sẽ sử dụng. Bởi vì NGINX là đơn luồng (single threaded), nó thường bằng với số lõi CPU.
- worker_connection: Đây là số lượng tối đa của các kết nối đồng thời cho mỗi worker process và nói cho các worker process của chúng ta có bao nhiêu người có thể được phục vụ đồng thời bởi NGINX.
- access_log & error_log: Đây là những tệp tin mà NGINX sẽ sử dụng để log bất kỳ lỗi và số lần truy cập. Các bản ghi này thường được sử dụng để gỡ lỗi hoặc sửa chữa.
- gzip: Đây là các thiết lập nén GZIP của các NGINX reponse. Tính năng này có nhiều thiết lập phụ, phần bị comment bởi mặc định có thể giúp hiệu suất được cải thiện đáng kể. Trong các thiết lập phụ của GZIP, cần quan tâm tới
gzip_comp_level
, nó là mức nén và nằm trong khoảng từ 1 tới 10. Thông thường, giá trị này không nên lớn hơn 6 — trên mức này lợi ích từ việc nén là không đáng kể, vì nó cần sử dụng nhiều CPU hơn.gzip_types
là một danh sách các kiểu response sẽ được nén.
NGINX hỗ trợ nhiều ngữ cảnh và các ngữ cảnh có thể lông nhau: http, uptream, location,…
Một số lệnh thao tác với NGINX
NGINX chạy dưới dạng dịch vụ, bạn thao tác với NGINX bằng các lệnh dưới:
# Khởi động NGINX
sudo systemctl start nginx
# Load lại cấu hình mà không muốn dừng dịch vụ
sudo systemctl reload nginx
# Kiểm tra trạng thái NGINX
sudo systemctl status nginx
Log của NGINX thường để trong thư mục /var/log/nginx, một số lệnh kiểm tra log như sau:
# Kiểm tra log lỗi
sudo tail -f /var/log/nginx/error.log
# Xem log truy cập
sudo tail -f /var/log/nginx/access.log
# Kiểm tra port của nginx, port thay đổi tùy cấu hình
sudo netstat -tuln | grep -E '80|443'
Khi bạn thay đổi cấu hình, bạn nên kiểm tra tệp cấu hình có đúng cú pháp không bằng lệnh:
sudo nginx -t
Ứng dụng của NGINX
Sử dụng NGINX như một Reverve Proxy
Reverse Proxy là gì?
Reverse Proxy là một server trung gian giữa Client và Server. Nó kiểm soát các request từ Client, và điều phối những request đó tới Server phù hợp, để Server xử lí request đó. Khi Server xử lí xong, sẽ trả về response cho Reverse Proxy, và Reverse Proxy có trả về response đó cho Client.
Một số ưu điểm của Reverse Proxy là:
- Có thể che giấu sự tồn tại và các đặc điểm của các Server thực sự được dùng.
- Load balancing, Proxy có thể chia đều các request của Client tới Server.
- Có thể nén nội dung, tăng tốc độ truy cập.
- Có thể trở thành một application firewall để chống đỡ những cuộc tấn công (ví dụ DDoS) và các ứng dụng Web.
Cấu hình NGINX thành một Reverse Proxy
Bài toán của chúng ta như sau:
- Chúng ta có server A với IP là x.x.x.x có triển khai ứng dụng web trên cổng 6688
- Chúng ta muốn hạn chế kết nối server A, chỉ server B với IP y.y.y.y có thể truy cập tới server A
- Người dùng phải truy cập vào website thông qua server B
Như vậy chúng ta cài đặt NGINX trên server B, mở tệp /etc/nginx/nginx.conf và thêm cấu hình sau và cuối của ngữ cảnh http:
http {
# ...
server {
listen 6688;
server_name testing-proxy;
location / {
proxy_pass "http://x.x.x.x:6688";
}
}
}
Toàn bộ tệp /etc/nginx/nginx.conf sẽ như sau:
user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 768;
# multi_accept on;
}
http {
##
# Basic Settings
##
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
# server_tokens off;
# server_names_hash_bucket_size 64;
# server_name_in_redirect off;
include /etc/nginx/mime.types;
default_type application/octet-stream;
##
# SSL Settings
##
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
ssl_prefer_server_ciphers on;
##
# Logging Settings
##
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
##
# Gzip Settings
##
gzip on;
# gzip_vary on;
# gzip_proxied any;
# gzip_comp_level 6;
# gzip_buffers 16 8k;
# gzip_http_version 1.1;
# gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
##
# Virtual Host Configs
##
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
server {
listen 6688;
server_name testing-proxy;
location / {
proxy_pass "http://x.x.x.x:6688";
}
}
}
#mail {
# # See sample authentication script at:
# # http://wiki.nginx.org/ImapAuthenticateWithApachePhpScript
#
# # auth_http localhost/auth.php;
# # pop3_capabilities "TOP" "USER";
# # imap_capabilities "IMAP4rev1" "UIDPLUS";
#
# server {
# listen localhost:110;
# protocol pop3;
# proxy on;
# }
#
# server {
# listen localhost:143;
# protocol imap;
# proxy on;
# }
#}
Chúng ta dùng lệnh sau để kiểm tra tính hợp lệ tệp cấu hình:
nginx -t
Và sau đó dùng lệnh sau để NGINX tự động load lại cấu hình:
nginx -s reload
Bây giờ chúng ta có thể mở trình duyệt, vào link http://y.y.y.y:6688 để truy cập vào website.
Sử dụng NGINX như một hệ thống cân bằng tải Loadbalancing
Loadbalancing là gì?
Loadbalancing
hay còn được biết đến với tên "Cân bằng tải"
là một kĩ thuật được sử dụng cực kì phổ biến của các web developer nhăm mục đích tối ưu hóa việc sử dụng tài nguyên , băng thông, giảm độ trễ cũng như khả năng xử lý lỗi của của 1 website.
Nói 1 cách cụ thể hơn, thì thay vì sử dụng 1 server cho 1 web site, chúng ta sẽ sử dụng nhiều server để làm việc đó. Cùng với đó là sự gia tăng về web server chũng ta sẽ cần có 1 máy chủ để phân phối các lưu lượng truy cập cho các server một cách hợp lý . Máy chủ này gọi là Loadbalancer
.
Kỹ thuật LoadBalacing được sử dụng phổ biến cho những Website có lưu lượng truy cập lớn. Thay vì phải sử dụng một server cực mạnh để đảm bảo hiệu năng cho người dùng, với kỹ thuật LoadBalacing chúng ta chỉ cần nhiều server nhỏ, như vậy sẽ giảm chi phí đáng kể.
Cấu hình NGINX thành một LoadBalancer
Chúng ta cần có ít nhất 3 server:
- main: Đóng vai trò như một LoadBalancer
- server_1, server_2: Đều chúng source code và đều trỏ tới cùng 1 Database để đảm bảo tính toàn vẹn dữ liệu. Chú ý: Khi cấu hình bạn phải thay server_1, server_2 bằng IP tương ứng.
Để cấu hình NGINX thành một LoadBalancer, chúng ta thêm cấu hình sau vào cuối ngữ cảnh http:
http {
# ...
upstream backend {
server server_1;
server server_2;
}
server {
listen 80;
location / {
proxy_pass http://backend;
}
}
}
Với cấu hình như trên nginx sẽ nhận tất cả các lưu lượng chạy vào cổng 80 và phân phối lưu lưu đó qua 2 server là server_1 và server_2.
Các chiến lượng cân bằng tải
* Chiến lược Round robin:
Mặc đinh thì nginx
sẽ sử dụng thuật toán này để tính lưu lượng cho các server con. Với thuật toán này các server sẽ được lần lượt nhận các request theo thứ tự . Cụ thể là :
- Request 1 ==> server_1
- Request 2 ==> server_2
- ……………………………………….
- Request n ==> server_1
- Request n + 1 ==> server_2
Đây là thuật toán không tối ưu vì nó phân phối đều request đến các server mà không tâm tới cấu hình cũng như khả năng đáp ứng của từng server.
* Chiến lược Least connected:
Với chiến lược này bạn phải cấu hình như sau:
upstream backend {
least_conn;
server server_1;
server server_2;
}
Với việc sử dụng thuật toán này, nginx sẽ tính lưu lượng traffic và connection thực tế mà server đó đang phải xử lý và sẽ phân bổ request mới đến server đang phải xử lý ít request hơn và mình thấy đây là một thuật toán khá thực tế khi sử dụng loadbalancing.
* Chiến lược Hash:
Cách thức chiến lược này hoạt động như sau:
- Ta cần cung cấp 1
key
chonginx
,key
này có thể là text cũng có thể là argument , header hay cookie v….v…. của request truyền lên Nginx
sử dụngkey
này để mã hóa và check xemkey
này đã được gắn với server nào (trong cache).- Nếu chưa gắn với server nào thì
nginx
sẽ random server (Theo thuật toán Round Robin) và cache lại - Nếu đã gắn với server thì auto chọn server đó
Để sử dụng chiến lược này, trong ngữ cảnh uptream chúng ta cần khai báo thêm:
hash `key` [consistent]
Trong đó key có thể là:
- Giá trị key lấy từ header của http:
$http_session_id => Lấy Header có name là : session_id - Lấy từ tham số trong http:
$arg_mobile ==> Lấy Argument có name là : mobile - Theo Ip:
$remote_addr
Trong trường hợp key truyền lên là rỗng, nginx sẽ quay trở lại thuật toán Round robin để phân bố request .
Còn consistent đây là một tham số bạn thể truyền vào hoặc không . Nếu bạn truyền tham số này vào thì phương thức ketama sẽ được xử dụng cho việc mã hóa key. Hiểu một cách ngắn gọn rằng , với việc sử dụng Hash này, khi bạn thêm mới hoặc xóa 1 server nào đó bất kì trong loadbalancer, nginx sẽ xóa toàn bộ cache đã lưu. Quay trở lại với phương thức ketama, nó sẽ đảm bảo chỉ các cache của các server bị ảnh hưởng bị clear và đảm bảo các request không bị ảnh hưởng hoạt động như cũ.
Như vậy với chiến lược này, ta có thể cấu hình như sau:
upstream backend {
hash $http_session_id consistent; #use method ketama
server server_1;
server server_2;
}
Thực tế $http_session_id hay được sử dụng cho ứng dụng đòi hỏi quyền đăng nhập. Tức là khi người dùng đã đăng nhập (Có session id) thì các request tiếp theo của người dùng sẽ được đẩy sang server đã đăng nhập trước đó. Một số ứng dụng, vì lý do bảo mật, sau khi đăng nhập sẽ tự động sinh ra session id khác thì không sử dụng được.
* Chiến lược IP Hash:
Thuật toán này cũng sử dụng hash và nó hash ip address của client. Bản chất thì nó sẽ sử dụng bộ 3 octet của ipv4 hoặc toàn bộ địa chỉ ipv6 để làm key mã hóa rồi hoạt động như thuật toán hash thông thường . Thuật toán này đảm bảo rằng, khi hoạt động bình thường , request từ 1 client luôn luôn chỉ đến 1 server. Trong 1 số trường hợp, điều này rất quan trọng, thường đảm bảo phiên đăng nhập người dùng.
upstream backend {
ip_hash;
server server_1;
server server_2;
}
* Chiến lược Least Time:
Chiến lược này sẽ cấu hình như sau:
upstream backend {
least_time first_byte;
server server_1;
server server_2;
}
Thuật toán này thực sự rất thông mình nên nó chỉ dành cho phiên bản trả phí. Việc quyết định sử dụng server nào phụ thuộc vào lượng request active của server và độ trễ khi xử lý của server. Nó sẽ chọn server ít connection và độ trễ thấp nhất. Tuy nhiên việc tính độ trễ này phụ thuộc vào tham số đầu vào least_time. Cụ thể như sau :
- connect: Thời gian connect đến upstream server
first_byte
: Thời gian nhận về những byte dữ liệu đầu tiên- last_byte: Thời gian nhận hết toàn bộ dữ liệu
* Chiến lược Random:
Chiến lược này sẽ random các server để lựa chọn server mà request sẽ đi tới. Đặc biệt nên bạn enable tham số two thì nginx sẽ chọn ra 2 server thỏa mãn thuật toán đi kèm, sau đó chọn ngẫu nhiên 1 server.
upstream backend {
random two least_conn;
server server_1;
server server_2;
server server_3;
}
Các thuật toán support cho param two:
- least_conn
- least_time=connect (Trong NGINX Plus)
- least_time=first_byte (Trong NGINX Plus)
- least_time=last_byte (Trong NGINX Plus)
Cơ chế kiểm tra server và bắt lỗi của nginx
* Cấu hình để nginx biết khi nào server không khỏe mạnh:
Với bản miễn phí, chúng ta cần cấu hình nginx để nó biết khi nào thì server không khỏe mạnh:
location / {
proxy_next_upstream http_404;
proxy_pass http://backend;
}
Trong cấu hình trên, nếu response trả về 404 thì sẽ bị đánh dấu là không khỏe mạnh và chuyển qua server khác.
* Cấu hình “Max Fails” và “Fail timeout“:
upstream backend {
server server_1 max_fails=2 fail_timeout=3;
server server_2;
}
Trong cấu hình trên, chúng ta định nghĩa số lần tối đa unhealthy của 1 server trong 1 thời gian cố định sẽ được config bẳng fail_timeout directive . Nếu con số này bị vượt quá thì server sẽ bị đánh dấu là unavaiable . Directive này sẽ không hoạt động nên directive fail_timeout có giá trị là 0
* Đánh dấu 1 server là không khỏe mạnh:
Để đánh dấu server là không khỏe mạnh, ta cũng có thể cấu hình lại file config bằng cách thêm hậu tố down
vào sau server address trong upstream directive . Cụ thể như sau:
upstream backend {
server server_1 down;
server server_2;
server server_3;
}
Trong ví dụ bên trên server_1 sẽ bị down vĩnh viễn, cho đến khi bạn cấu hình lại server . Ngoài ra nếu bạn nào tò mò vì sao nếu xóa server khỏi list danh sách sao ko comment hay xóa luôn đi cho nhanh mà phải dùng đến cái down này thì lý do rất đơn giản bởi vì khi xóa hay comment vào thì các hashes
của server đó sẽ bị xóa đi, dùng down
thì sẽ còn nguyên đảm bảo tính toàn vẹn. Điều này cực kì có ý nghĩa khi bạn đang dùng một thuật toán hash hay ip_hash
* Cấu hình backup server:
upstream backend {
server server_1;
server server_2;
server server_3 backup;
}
Khi bạn đánh dấu 1 server là backup
(trong ví dụ nêu trên là server_3
) thì server này sẽ ko được phân phối traffic cho đến khi các server active bị đánh dấu là unavailable , mỗi 1 server unavailable thì 1 server backup sẽ được mở ra và thế vào chỗ của server không khỏe mạnh đó. Backup server không được khả dụng khi chúng ta sử dung các thuật toán cân bằng tải là hash, ip_hash hay là random.
* Cấu hình weight server:
upstream backend {
server server_1 weight=2;
server server_2;
}
Đây là chỉ số làm thay đổi lưu lượng traffic tới server cụ thể trong một upstream . Nó cực kì hữu ích nếu bạn có 1 server có hardware vượt trội hơn hẳn so với server khác . Khi đó bạn cần đẩy nhiều request hơn đến server đó để hiệu năng được xử lý một cách trơn tru mượt mà nhất . Hoặc nếu bạn có 1 server yếu hơn và muốn request ít hơn thì cũng có thể sử dụng param này.
Trong ví dụ trên , lượng traffic vào server_1 sẽ gắp đôi lượng traffic của server_2 . Mặc định thì trọng số này sẽ là 1.
Cấu hình Http Caching cho Nginx
<Đang cập nhật>
Tham khảo:
Trả lời