1.根目錄和索引文件
server { root /www/data; location / { } location /images/ { } location ~ \.(mp3|mp4) { root /www/media; } }
root指令能放置的位置是:http,server,location。
上面的意思是:我所有的location定義都是基於根目錄/www/data的,也就是說"/"指的就是/www/data/,而"/images/"指的就是/www/data/images/。
我們可以為每個目錄都定義一個索引文件,默認是index.html。
index指令的值:可以是index.html或者index.htm,或者index.php。
如果我們的URI是/images/some/path,那么nginx返回的文件就是/www/data/images/some/path/index.html。當然,前提是這個index.html得存在,否則返回404錯誤。
假如我訪問/images/some/path這個URI時,我希望在網頁上展示的是列表,需要使用指令autoindex:會展示/www/data/images/some/path/目錄下的所有文件夾和文件。
location /images/ {
autoindex on;
}
可以在index指令后添加多個索引文件,nginx會按順序查找,找到哪個就使用哪個:
location / {
root html;
index index.html index.php index.htm index.$geo.html;
}
$geo是一個用geo指令設置的自定義變量,這個變量的值取決於客戶端的IP地址。
index.php文件的重定向:
location / { root /data; index index.html index.php; } location ~ \.php { fastcgi_pass localhost:8000; ... }
2.嘗試多個選項
try_files用於提供備選方案,當用戶請求的URI不存在時,給予用戶一個備選的方案。
server { root /www/data; location /images/ { try_files $uri /images/default.gif; } }
我們的URI是/images/aa.png,匹配到location之后,首先嘗試去查找/www/data/images/aa.png文件,發現沒有,此時nginx就會將/www/data/images/default.gif文件
返回給用戶。
(問題:我的瀏覽器顯示的是www.example.com/images/aa.png,但實際上看到的文件卻是www.example.com/images/default.gif,目前不知道原因)。
還有一點要注意:我們的替換方法(比如上面的/images/default.gif)一定要在root的范圍內,也就是/www/data目錄下尋找,你不能寫成其他的。
location / { try_files $uri $uri/ $uri.html =404; }
如果匹配完所有的內容,都沒能找到,就返回404錯誤。注意,如果你不明確指定404錯誤,那么nginx會返回500內部服務器錯誤的字樣。
返回指定的錯誤頁面:
error_page 404 /404.html; location = /404.html { root html; }
重定向到命名location所代表的后端服務器:
location / { try_files $uri $uri/ @backend; } location @backend { proxy_pass http://backend.example.com; }
當前面的$uri,$uri/都匹配不上時,就交給@backend所代表的http://backend.example.com去處理。
這里可以查看nginx的Content Caching(https://www.nginx.com/resources/webinars/content-caching-nginx-plus/),看它如何戲劇性地提高站點的性能,同時深入
理解Nginx的緩存功能。
3.優化Nginx提供內容的速度
對nginx的配置做少許的修改,就能提高nginx的性能。
(1)開啟sendfile
location /mp3 {
sendfile on;
sendfile_max_chunk 1m;
...
}
如果不開啟sendfile,nginx會自己處理文件的傳輸,在發送數據之前,會將數據拷貝到buffer區域。
如果開啟sendfile,就會省略拷貝到buffer區域的步驟,而是會直接從一個文件描述符拷貝到另一個文件描述符。
如果一個連接傳輸數據很快,那么它會一個人霸占一個工作進程,那么可以限制sendfile()方法每次傳輸的數據量大小,那么可以定義sendfile_max_chunk指令,從而限制每
個連接中最大可以傳輸的數據量。
(2)開啟tcp_nopush
location /mp3 {
sendfile on;
tcp_nopush on;
...
}
tcp_nopush需要和sendfile一起使用,它的作用是:讓HTTP響應頭和sendfile()發送的數據混合為一個數據包發送出去。
(3)開啟tcp_nodelay
location /mp3 { tcp_nodelay on; keepalive_timeout 65; ... }
這個選項用於覆蓋Nagle's算法。
Nagle's算法原本的作用是:用於解決在緩慢的網絡中傳輸很小的數據包問題。它的做法是在200ms的延遲時間內,將多個小的數據包組合為一個大的數據包,然后發出去。
當nginx提供大的靜態文件時,它不管文件大小,都是立即發送出去。
delay會影響在線應用程序,比如ssh,在線游戲,在線交易。
tcp_nodely設置為on,表示關閉Nagle's算法。
必須開啟keepalive,才能使用這個指令,否則不能使用。
(4)優化Backlog Queue
有一個重要的因素是:Nginx處理incoming connections時,有多快?
監聽套接字的監聽隊列:listen socket的"listen" queue
一般規則是:當一個連接建立后,它就會被放入這個"listen" queue中去。
在正常情況下,要么是低隊列,要么根本就沒有隊列。
但是在高負載情況下,這個隊列就會很高,可能會造成不穩定的性能、可能會丟棄連接,可能會出現延時。
- 測量"listen" queue的長度
netstat -Lan (這個命令可能不對,但重要的是下面的結果)
Current listen queue sizes (qlen/incqlen/maxqlen) Listen Local Address 0/0/128 *.12345 10/0/128 *.80 0/0/128 *.8080
我們看端口80的listen queue,隊列中目前有10個未接受的連接,這個隊列的最大長度是128,也就是可以有128個連接在隊列中。這是正常的結果。
如果出現的是下面的結果:
Current listen queue sizes (qlen/incqlen/maxqlen) Listen Local Address 0/0/128 *.12345 192/0/128 *.80 0/0/128 *.8080
我們看到192超出了最大限制,這在網站繁忙時很容易看到。
我們需要做一些調整,允許更多的連接來排隊。從2個層面來調整,一個是操作系統,一個是nginx自身。
首先是調整操作系統:
sysctl -w net.core.somaxconn=4096
這里的somaxconn指的是socket max connections,指的是監聽套接字的最大連接數。
vim /etc/sysctl
net.core.somaxconn = 4096
然后是調整nginx:
server { listen 80 backlog 4096; # The rest of server configuration }
