[Nginx] Server và location block cách làm việc và phương thức điều hướng request
Bài đăng này đã không được cập nhật trong 3 năm
Introduction
Nginx là một trong những web server phổ biến nhất trên thế giới. Nó có thể làm tốt nhiệm vụ handle cho hệ thống có lượng truy cập lớn cùng 1 thời điểm, có thể đảm nhận nhiều công việc như: webserver, mail server hay một reserve proxy server. Trong bài hướng dẫn này, chúng ta sẽ thảo luận về vấn đề: Nginx đã xử lí client request như thế nào? Trả lời câu hỏi này có thể giúp chúng ta hiểu về cấu trúc của server block và location block thậm chí là handle request.
Nginx Block Configurations
Nginx phân chia config trong nhiều block khác nhau tạo thành cấu trúc hình cây. Mỗi lần có request được gửi lên server, nginx sẽ xác định config block nào sẽ được sử dụng để handle request. Và thông thường một khối blogo để handle request sẽ có dạng như sau:
server {
location {
}
}
Một server Block là một tập hợp của nhiều cấu hình nginx quyết định hướng xử lí cho các request khác nhau dựa trên domain name port và IP address. Một location block nằm trong server block được sử dụng để định nghĩa mà nginx có thể handle request cho nhiều request với các dạng URI khác nhau. URI có thể đuợc chia thao bất cứ cách nào mà admin hệ thống muốn để phân loại request.
Cách mà nginx quyết định server block nào sẽ handle request
kể từ khi mà nginx cho phép khai báo server trong config thành những khối block riêng biệt cho từng virtual host thì ta cần phải có cách để xác định được khi nào thì request nào sẽ được xử lí ở đâu. NGINX thực hiện việc này thông qua 2 thuộc tính trong config đó là listen directive và server_name directive.
Phân tích listen directive và server_name để tìm ra server web nào mà request sẽ được map đến.
Đầu tiên, NGINX sẽ nhìn vào điạ chỉ IP và port của request, NGINX sẽ đối chiếu với mỗi listen directive của mỗi server block để tìm ra block nào sẽ giải quyết request này. Thông thường thì listen directive sẽ được định nghĩa là ip or port mà server sẽ trả response. Nếu không khai báo thì nginx sẽ nghe default ở 0.0.0.0:80 (or 0.0.0.0:8080 nếu nginx không run dưới quyền user không phải root). Tóm lại là reponse sau khi xử lí xong sẽ trả response về lại cổng 80.
Listen directive có thể được set thành:
- địa chỉ ip đơn (default sẽ chạy ở cổng 80), hoặc combo bao gồm ip và port
- path to unix socket
Option cuối chỉ có ý nghĩa khi ta muốn trả request về một server khác.
Trong quá trình xác định xem request sẽ được chuyển đến server block nào, nginx sẽ cố xác định thông tin từ listen directive trước theo luật như sau:
- NGINX sẽ gán giá trị mặc định cho block bị thiếu thông tin. VD như: block không có listen directive sẽ sử dụng value là 0.0.0.0:80, block chỉ set địa chỉ ip sẽ mặc định nghe ở cổng 80, block chỉ có mỗi port sẽ chuyển về nghe ở điạ chỉ 0.0.0.0
Sau quá trình find theo ip và port, nginx sẽ find tiếp theo server_name directive và đối chiếu nó với field Host trong request
server {
listen 80;
server_name *.example.com;
. . .
}
Tóm tắt listen directive chỉ ra cổng mà nginx lắng nghe cho giao thức truyền tới, ví dụ listen 80 nghĩa là tất cả những request gửi tới bằng giao thức http sẽ được xử lí tại đây. còn server_name directive sẽ đối chiếu với field Host trong header của request để xem request có đuwocj xử lí theo khối block server này không
location directive block
Sau khi đã chọn được server block nào sẽ tiếp nhận request này thì nginx sẽ tiếp tục phân tích URI của request để tìm ra hướng xử lí của request dựa vào các block location có syntax như sau:
location optional_modifier location_match {
. . .
}
optional_modifier: bạn có thể tạm hiểu nó là kiểu so sánh để tìm ra để đối chiếu với location_match. Có mấy loại option như sau:
- (none): Nếu không khai báo gì thì NGINX sẽ hiểu là tất cả các request có URI bắt đầu bằng phần location_match sẽ được chuyển cho location block này xử lí.
- = : Khai báo này chỉ ra rằng URI phải có chính xác giống như location_match (giống như so sánh string bình thường).
- ~ : Sử dụng regular expression cho các URI.
- ~* : Sử dụng regular expression cho các URI cho phép pass cả chữ hoa và chữ thường
Một số ví dụ
location /site {
. . .
}
các request có URI có dạng như sau: /site, /site/page/1, site/index.html sẽ được xử lí thông qua location này.
location = /site {
. . .
}
với 3 URI như bên trên thì chỉ có /site sẽ có thể được xử lí trong directive này, còn /site/page/1 hay /site/index.html thì không.
location ~ \.(jpe?g|png|gif|ico)$ {
. . .
}
các request có đuôi .jpg,.jpeg, .png, .gif, .ico có thể pass qua location này nhưng .PNG thì không
location ~* \.(jpe?g|png|gif|ico)$ {
. . .
}
giống như trên nhưng đuôi .PNG cũng có thể pass.
Khi nào thì location block sẽ nhảy vào khối block khác
Thông thường khi mà location block được dùng để phục vụ một request nào đó thì action sẽ hoàn toàn nằm trong context của nó ( bên trong dấu {}). Và nó sẽ chỉ nhảy sang các block khác hay chuyển hươngs xử lí request khi có yêu cầu từ chính bên trong context của nó. Một vài directive có thể redirective request. Ví dụ:
- index
- try_files
- rewrite
- error_page
index directive
index direct nằm bên trong location luôn được nginx trỏ tới đầu tiên khi xử lí điều hướng request. Định nghĩa trang mặc định mà Nginx sẽ phục vụ nếu không có tên tập tin được chỉ rõ trong yêu cầu (nói cách khác, trang chỉ mục). Chúng ta có thể chỉ rõ nhiều tên tập tin và tập tin đầu tiên được tìm thấy sẽ được sử dụng. Nếu không có tập tin cụ thể nào được tìm thấy, Nginx sẽ hoặc là cố gắng phát sinh 1 chỉ mục tự động của các tập tin
location = / {
index index.html;
}
try_files directive
Cố gắng phục vụ các tập tin được chỉ rõ (các tham số từ 1 đến N-1 trong chỉ thị), nếu không có tập tin nào tồn tại, nhảy đến khối location được khai báo (tham số cuối cùng trong chỉ thị) hoặc phục vụ 1 URI được chỉ định.
location / {
try_files $uri $uri.html $uri/ /fallback/index.html;
}
rewrite directive
Khác với Apache, Nginx không sử dụng file .htaccess nên khi bạn cần rewrite url sẽ phải convert qua rule của Nginx. Trong bài viết này, mình sẽ đưa ra một số ví dụ các rule của Nginx sử dụng để rewrite url, redirect và một số cấu hình cần thiết khác.
location /download/ {
rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 break;
rewrite ^(/download/.*)/audio/(.*)\..*$ $1/mp3/$2.ra break;
return 403;
}
error_page directive
chỉ thị khi không tìm thấy file tham chiếu.
location / {
error_page 404 = @fallback;
}
location @fallback {
proxy_pass http://backend;
}
Tham Khảo
https://viblo.asia/p/tim-hieu-va-huong-dan-setup-web-server-nginx-OREGwBwlvlN https://hocvps.com/rule-nginx/#Rewrite_URL https://www.digitalocean.com/community/tutorials/understanding-nginx-server-and-location-block-selection-algorithms
All rights reserved