一、概述
Nginx的配置放在配置文件nginx.conf/etc/nginx/nginx.conf 中,大概的結構如下:
main # 全局配置
events { # nginx工作模式配置
}
http { # http設置
....
server { # 服務器主機配置
....
location { # 路由配置
....
}
location path {
....
}
location otherpath {
....
}
}
server {
....
location {
....
}
}
upstream name { # 負載均衡配置
....
}
}
主要有
- main,全局配置
- event nginx工作模式
- http http服務器的配置
- server 服務器訪問的配置
- location 路由配置
- upstream 負載均衡配置
二、main模塊
全局配置並不需要包含在大括號中。
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
worker_rlimit_nofile 1024;
- nginx 用哪個用戶來啟動
- worker_processes 啟動的進程數,一般是CPU數量的兩倍
- error_log 錯誤日志,空格后面是日志的等級,有warn error notice等
- pid nginx pid的存放地址
- worker_rlimit_nofile 每個進程打開的文件描述符的數量
三、event 模塊
event {
worker_connections 1024;
multi_accept on;
use epoll;
}
- worker_connections 最大可接收的連接數
- muti_accept 配置指定nginx在收到一個新連接通知后盡可能多的接受更多的連接
- use 配置線程輪詢方式
四、http模塊
http {
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
include /etc/nginx/conf.d/*.conf;
常用配置
- access_log access日志
- error_log 錯誤日志
- log_format 日志格式
- include 引入其他文件作為配置
五、server模塊
server模塊放在http模塊里面,一個server相當於一個虛擬的服務器。
server {
listen 80;
server_name localhost 192.168.1.100;
root /nginx/www;
index index.php index.html index.html;
charset utf-8;
access_log logs/access.log;
error_log logs/error.log;
......
}
- listen 監聽的端口
- server_name 域名或者IP 空格分隔
- root 表示虛擬主機的根目錄
- index 表示全局首頁
- charset 網頁中默認的編碼方式
- access_log 訪問記錄日志
- error_log 錯誤日志
六、location模塊
location模塊放在server模塊里面,表示一個路由規則。
location的語法規則
location [ 空格 | = | ~ | ~* |^~|!~ | !~* ] /uri/ {}
第一部分是location關鍵字
第二部分是修飾語(modifier)
第三部分是匹配的內容
第四部分是匹配成功后處理的方法
1.修飾語
請求目錄是指客戶端發過了的請求的uri,例如客戶端訪問http://www.aa.com/dir1/dir2,其中/dir1/dir2就是請求目錄
- = 精確匹配,也就是請求目錄和匹配的內容完全一致,才會匹配上,不支持正則
- ^~開頭字符串匹配,如果請求目錄的開頭和匹配內容一樣,就會匹配上,不支持正則
- ~ 開頭區分大小寫正則匹配,如果請求目錄的開頭符合匹配內容(正則表達式),就會匹配上
- ~* 和
~類似,區別是這個不區分大小寫 - !~ 和
~類似,區別是不符合正則,就會匹配上 - !~* 和
~*類似,區別是不符合正則,就會匹配上 - 空格,跟
^~類似,區別是優先級最低
上面的修飾符,除了精確匹配=和正則的匹配之外,其他都是前綴匹配,也就是請求目錄的前面匹配上,就算匹配上了,不管后面的。
為了安全起見,建議正在匹配盡量加上^和$
2. 匹配優先級
當多個location都可以匹配請求目錄,那么nginx會使用哪個location呢?
-
如果修飾語不同,那么修飾語的優先級是
=大於^~大於~大於~*大於空格location = /dir1 {
return 601;
}
location ^~ /dir1 {
return 602;
}
location ~ /dir\d {
return 603;
}
location ~* /dir\d {
return 604;
}
location /dir1 {
return 605;
}
使用上面的配置,訪問http://test.kevinlu.com:10000/dir1,第一個location優先級最高,然后逐漸下降(可以通過注釋location來測試)。
-
如果修飾語一樣,會找最長匹配字符串
location / {
return 601;
}location /d {
return 602;
}
如果訪問http://test.kevinlu.com:10000/d,兩個location都會匹配上,但是第二個location會匹配到請求目錄的/d,長度是2,而第一個只會匹配到/,長度是1,前面的長度更長,所以使用第二個location。
注意這里的長度是請求目錄的長度,不是匹配內容的長度。所以~ /\d和~ /3,長度是一樣的,都是長度為1。
-
如果匹配字符串的長度一樣,使用第一個location
location ~ /\d { return 601; } location ~ /3 { return 602; }
例如上面的配置,訪問http://test.kevinlu.com:10000/3,會返回601。
所以總結一下Nginx尋找location的邏輯
- 根據修飾符的優先級,從高到低,尋找匹配的location數量N
- 如果N==0,尋找下一個優先級的修飾符
- 如果N==1,使用該location
- 如果N>1,計算每個location匹配uri的最長的匹配字符串長度L,能達到L的location的數量N1,
- 如果N1==1,返回該location
- 如果N1>1,返回第一個location
- 如果所有location都不滿足,返回404
偽代碼:
MODIFIER_LIST = ['=', '^~', '.......'] #修飾符的優先級排序
def get_location(uri):
"""尋找最優的location"""
for modifier in MODIFIER_LIST:
locations = get_match_location(uri, modifier) #獲取修飾符是modifier,匹配上uri的所有locations
num = len(locations)
if num == 0:
continue
elif num == 1:
return locations[0]
else:
max_length = 0
use_location = None
for location in locations:
length = get_match_uri_length(location, uri) #計算該location匹配上uri的最長匹配字符串的長度
if length > max_length: #這里是大於,不是大於等於,所以如果有多個location的length相同,會采用第一個
use_location = location
return use_location
return 404
alias /data/demo/demo2018/nginx_test/1;
#root html;
#index test.html;
3.常用的匹配配置
#精確匹配首頁
location = / {
proxy_pass http://tomcat:8080/index
}
#靜態資源
location ~* \.(gif|jpg|jpeg|png|css|js|ico|html)$ {
root /webroot/res/;
}
#返回某個目錄下面的所有文件
location ^~ /static/ {
root /webroot/static/;
}
4. 處理請求的指令
當Nginx找到最優的location來處理當前請求后,就會根據location的第四部分(大括號里面)的指令來處理請求,並返回response。
4.1 返回靜態文件
root和alias指令都是用來返回系統本地的問題。兩個指令的值都是本地文件目錄,注意目錄后面要加/,例如/data/www/
- root,會吧root的值和請求uri拼合在一起來尋找本地文件
- alias,會把alias的值和未匹配上的uri子串拼合在一起來尋找本地文件
例如配置:
location /static1/{
root /data/nginx_test/;
}
location /static2/{
alias /data/nginx_test/;
}
location ~ ^/static3/(.+\.html)${
alias /data/nginx_test/$1;
#return 601;
}
當訪問http://test.kevinlu.com/static1/test.html,會返回文件/data/nginx_test/static1/test.html
當訪問http://test.kevinlu.com/static2/test.html,會返回文件/data/nginx_test/test.html
當訪問http://test.kevinlu.com/static3/test.html,會返回文件/data/nginx_test/test.html
注意第二個是沒有static2的。
使用alias的話,如果是正則的匹配方法,就需要使用正則的捕獲功能,把括號里面的字符串賦值到變量$1中。
如果配置后,找不到文件,可以看看error_log,會報錯105415 open() "/data/demo/demo2018/nginx_test/static1/2/test.html" failed (2: No such file or directory),就可以看nginx
4.2反向代理
-
普通代理
Nignx會把HTTP請求通過socket連接,轉發給其他進程來處理location /static1/{
proxy_pass http://localhost:8080/;
proxy_set_header Host $host;
}
使用proxy_pass指令。
- proxy_pass 指定轉發到的socket地址
- proxy_set_header 在http請求的基礎上,增加header 第一個參數是頭的key,第二個是頭的value
- 其他proxy相關指令
.
-
FastCGI代理
location / {
fastcgi_pass localhost:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param QUERY_STRING $query_string;
}
- fastcgi_pass 和proxy_pass類似
- 其他fastcgi指令
4.3返回狀態碼
return指令用戶之間返回response
第一個參數是http狀態碼,
第二個參數是body
可以直接重定向,也可以返回內容給前端。
location /test/{
#return 301 http://www.baidu.com;
return 200 <h1>aaa</h1>;
}
4.4 重定向rewrite
語法:
rewrite regex replacement [flag];
該指令會把看是否uri匹配regex,如果匹配,把replacement替換regex。
flag可以:
- last 向下匹配其他location
- break 終止匹配,不會再匹配下面的location
- redirect 返回302重定向,這個是臨時重定向
- permanent 返回301重定向,這個是永久重定向,
七、upstream
nginx配置
upstream gunicorn_pool
{
#server 地址:端口號 weight表示權值,權值越大,被分配的幾率越大;max_fails表示在fail_timeout中失敗的最大次數,如果達到該次數,就不再導流量到該server
server 192.168.137.130:9098 weight=4 max_fails=2 fail_timeout=30s;
server 192.168.137.133:9098 weight=4 max_fails=2 fail_timeout=30s;
}
server {
listen 80;
server_name 127.0.0.1 www.test.com;
access_log /data/logs/nginx_access.log;
error_log /data/logs/nginx_error.log;
location @gunicorn_proxy {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://gunicorn_pool;
}
}
配置一個upstream,gunicorn_pool。里面有兩個服務層(130和137)
如果兩個服務層都正常,Nginx會把流量根據weight值,導流到兩個服務器。
同一個請求中,如果nginx導流到server1,發現返回的是錯誤響應(例如502),nginx會把請求再發送server2,相當於重試。這時會記錄server1的fail次數+1
如果再fail_timeout時間內,server1的fail次數超過max_fails,在fail_timeout時間內,nginx就不會再把其他請求導流到server1了。
未經允許,請不要轉載
