Nginx 技術研究html
1. Nginx安裝
1.1. 準備的軟件
Ø nginx-1.4.1.tar.gz前端
下載地址:http://nginx.org/en/download.html其中包含開發版和穩定版,到目前爲止穩定版本最高版本號爲1.4.1linux
Ø nginx-sticky-module-1.1.tar.gznginx
下載地址:http://code.google.com/p/nginx-sticky-module/downloads/listweb
1.2. 安裝nginx-1.4.1.tar.gz
Ø 解壓nginx-1.4.1.tar.gz正則表達式
[root@c-admin Nginx]#cd ..windows
[root@c-admin Nginx]#tar zxvf nginx-1.4.1.tar.gz後端
Ø 解壓nginx-sticky-module-1.1.tar.gz瀏覽器
[root@c-admin Nginx]#tar zxvf nginx-sticky-module-1.1.tar.gztomcat
Ø 檢查安裝環境並配置
[root@c-admin Nginx]#cd nginx-1.4.1
[root@c-admin Nginx]#./configure --add-module= /root/nginx-sticky-module-1.1
Ø 安裝
[root@c-admin Nginx]#make && make install
Ø 啓動nginx
進入Nginx 默認安裝目錄/usr/local/nginx/sbin目錄.
[root@c-admin sbin]#./nginx
1.3. 可能的錯誤
1. 錯誤1:
解決:
32爲操做系統執行:ln -s /usr/local/lib/libpcre.so.1 /lib
64爲操做系統執行:ln -s /usr/local/lib/libpcre.so.1 /lib64
2. 錯誤2:
提示在頭文件中已經定義了NGX_SENDFILE_LIMIT。且在文件nginx-1.4.1/src/unix/ngx_linux_sendfile_chain.c中從新定義,重定義錯誤。
解決:
修改文件nginx-1.4.1/src/unix/ngx_linux_sendfile_chain.c中 27行代碼#define NGX_SENDFILE_LIMIT 2147483647L修改成#define NGX_SENDFILE_LIMIT 0x80000000
Ø 驗證安裝是否成功
在瀏覽器地輸入 http://127.0.0.1 若是出現如下相似頁面表明安裝成功
2. Nginx啓動方式
在不考慮nginx單進程工做的狀況下,這個過程包含三種方式:
默認啓動方式,啓動新的nginx,命令: windows或linux下,./nginx
指定配置文件的啓動方式,nginx –c conf/nginx.conf
指定安裝目錄的啓動方式,nginx –p /usr/local/nginx
配置,命令: nginx –s reload
熱替換nginx代碼
Location
表示執行一個正則匹配,區分大小寫
表示執行一個正則匹配,不區分大小寫
表示普通字符匹配,若是該選項匹配,只匹配該選項,不匹配別的選項,通常用來匹配目錄
進行普通字符精確匹配
定義一個命名的 location,使用在內部定向時,例如 error_page, try_files
通用匹配,任何請求都會匹配到。
精確匹配會第一個被處理。若是發現精確匹配,nginx中止搜索其餘匹配。
普通字符匹配,正則表達式規則和長的塊規則將被優先和查詢匹配,也就是說若是該項匹配還需去看有沒有正則表達式匹配和更長的匹配。
則只匹配該規則,nginx中止搜索其餘匹配,不然nginx會繼續處理其餘location指令。
最後匹配理帶有"~"和"~*"的指令,若是找到相應的匹配,則nginx中止搜索其餘匹配;當沒有正則表達式或者沒有正則表達式被匹配的狀況下,那麼匹配程度最高的逐字匹配指令會被使用。
(網上驗證)
Server
nginx以名字查找虛擬主機時,若是名字能夠匹配多於一個主機名定義,好比同時匹配了通配符的名字和正則表達式的名字,那麼nginx按照下面的優先級別進行查找,並選中第一個匹配的虛擬主機:
確切的名字;
最長的以星號起始的通配符名字:*.example.org;
最長的以星號結束的通配符名字:mail.*;
第一個匹配的正則表達式名字(按在配置文件中出現的順序)。
2. Nginx監控
經過查看Nginx的併發鏈接,咱們能夠更清除的知道網站的負載狀況。Nginx併發查看有兩種方法(之因此這麼說,是由於筆者只知道兩種),一種是經過web界面,一種是經過命令,web查看要比命令查看顯示的結果精確一些。下面介紹這兩種查看方法
經過web界面查看時Nginx須要開啓status模塊,也就是安裝Nginx時加上–with-http_stub_status_module 而後配置Nginx.conf,在server點裏面加入以下內容
location /nginx_status {
stub_status on;
access_log off;
allow 192.168.1.100; 訪問IP
deny all;
}
配置完後從新啓動Nginx後咱們能夠經過瀏覽器訪問http://localhost/status 查看,以下圖
解析:
Active connections //當前 Nginx 正處理的活動鏈接數。
server accepts handledrequests //總共處理了8 個鏈接 , 成功建立 8 次握手,總共處理了500個請求。
Reading //nginx 讀取到客戶端的 Header 信息數。
Writing //nginx 返回給客戶端的 Header 信息數。
Waiting //開啓 keep-alive 的狀況下,這個值等於 active – (reading + writing),意思就是 Nginx 已經處理完正在等候下一次請求指令的駐留鏈接
經過命令查看
#netstat -n | awk ‘/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}’
TIME_WAIT 17
ESTABLISHED 3254
LAST_ACK 236
FIN_WAIT_1 648
FIN_WAIT_2 581
CLOSING 7
CLOSE_WAIT 4916
解析:
CLOSED //無鏈接是活動的或正在進行
LISTEN //服務器在等待進入呼叫
SYN_RECV //一個鏈接請求已經到達,等待確認
SYN_SENT //應用已經開始,打開一個鏈接
ESTABLISHED //正常數據傳輸狀態/當前併發鏈接數
FIN_WAIT1 //應用說它已經完成
FIN_WAIT2 //另外一邊已贊成釋放
ITMED_WAIT //等待全部分組死掉
CLOSING //兩邊同時嘗試關閉
TIME_WAIT //另外一邊已初始化一個釋放
LAST_ACK //等待全部分組死掉
3. Nginx訪問控制
考慮到不少企業及我的的網站大都使用各類CMS,而攻擊者在進行攻擊以前,都會根據一些細節判斷對方使用的系統,再進行鍼對性的攻擊。不少CMS發行後,在一些目錄或多或少都留下了部分.txt等文本信息(黑客已此判斷此CMS版本等),您能夠刪除這些文件,也可使用本文的方法將其屏蔽。
禁止訪問文件類型
如,Nginx下禁止訪問*.txt,doc文件,配置方法以下:
方法1:(不許瀏覽器get命令訪問,使用迅雷是能夠將文件下來的,防止手工判斷)
location ~* \.(txt|doc)$ {
if (-f $request_filename) {
root /data/www/wwwroot/linuxtone/test;
break;
}
}
方法2: (什麼都不許訪問,可能影響爬蟲robots.txt以及一些txt調用)
location ~* \.(txt|doc)${
root /data/www/wwwroot/linuxtone/test;
deny all;
}
禁止訪問某個目錄
location ~ ^/(WEB-INF)/ {
deny all;
}
禁止某個IP或網段訪問使用ngx_http_access_module限制ip訪問
location / {
deny 192.168.1.1;
allow 192.168.1.0/24;
allow 10.1.1.0/16;
deny all;
}
規則按順序檢測,至道第一個匹配的規則出現。在這個例子中,只容許IPV4的10.1.1.0/16和192.168.1.0/24中除去192.168.1.1來訪問,其餘的客戶端ip訪問都是不容許的。
爲了預防有太多的規則,使用模塊ngx_http_geo_module是更可取的
語法:allow address | CIDR | all;
默認:—
所屬指令:http, server, location, limit_except
指定的IP地址己網段均可以訪問。
語法:deny address | CIDR | all;
默認:—
所屬指令:http, server, location, limit_except
指定的IP地址及網段都不能夠訪問
限制下載連接
在http{}裏面,加上這句:
limit_zone one $binary_remote_addr 10m;
而後,在server{}裏面加上下面這段:
location / {
limit_conn one 1;
limit_rate 100k;
}
這裏limit_conn one 1是指一個IP只能用一個線程下載。limit_rate 100k是指最大隻能下載100k。
限速
nginx能夠經過HTTPLimitZoneModule和HTTPCoreModule兩個組件來對目錄進行限速。
http {
limit_zone one $binary_remote_addr 10m;
server {
location /download/ {
limit_conn one 1;
limit_rate 300k;
}
}
}
limit_zone: 是針對每一個IP定義一個存儲session狀態的容器.這個示例中定義了一個10m的容器,按照32bytes/session, 能夠處理320000個session。
limit_conn one 1:限制每一個IP只能發起一個併發鏈接。
limit_rate 300k: 對每一個鏈接限速300k. 注意,這裏是對鏈接限速,而不是對IP限速。若是一個IP容許兩個併發鏈接,那麼這個IP就是限速limit_rate×2。
注意:limit_zone只能定義在http做用域,limit_conn和limit_rate能夠定義在http server location做用域。
限制某一時間段內同一ip鏈接數
http{
#定義一個名爲allips的limit_req_zone用來存儲session,大小是10M內存,
#以$binary_remote_addr 爲key,限制平均每秒的請求爲20個,
#1M能存儲16000個狀態,rete的值必須爲整數,若是限制兩秒鐘一個請求,能夠設置成30r/m。
limit_req_zone $binary_remote_addr zone=allips:10m rate=20r/s;
}
文件上傳大小限制
配置文件里加入以下,具體大小根據你本身的業務作調整。
client_max_body_size 10m;
4. 一個nginx存在多個應用的狀況
Nginx.conf配置以下:
#gzip on;
upstream myserver{
server 192.168.51.50:8080;
}
upstream mytest{
server 192.168.51.106:8080;
}
server {
listen 81;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
root html;
proxy_pass http://myserver;
proxy_set_header X-Real-IP $remote_addr;
client_max_body_size 100m;
# index index.html index.htm;
}
location /jspds {
root html;
proxy_pass http://myserver/jspDS;
proxy_set_header X-Real-IP $remote_addr;
client_max_body_size 100m;
# index index.html index.htm;
}
location /helloworld {
root html;
proxy_pass http://mytest/helloWorld;
proxy_set_header X-Real-IP $remote_addr;
client_max_body_size 100m;
# index index.html index.htm;
}
5. Nginx負載均衡策略
5.1. 第一種:輪詢
upstream test{
server 192.168.0.1:3000;
server192.168.0.1:3001;
}
5.2. 第二種:權重
upstream test{
server 192.168.0.1 weight=2;
server 192.168.0.2 weight=3;
}
這種模式可解決服務器性能不等的狀況下輪詢比率的調配
5.3. 第三種:ip_hash
upstream test{
ip_hash;
server 192.168.0.1;
server 192.168.0.2;
}
這種模式會根據來源IP和後端配置來作hash分配,確保固定IP只訪問一個後端
5.4. 第四種:fair
須要安裝Upstream Fair Balancer Module
upstream test{
server 192.168.0.1;
server 192.168.0.2;
fair;
}
這種模式會根據後端服務的響應時間來分配,響應時間短的後端優先分配
5.5. 第五種:自定義hash
須要安裝Upstream Hash Module
upstream test{
server 192.168.0.1;
server 192.168.0.2;
hash $request_uri;
}
這種模式能夠根據給定的字符串進行Hash分配
具體應用:
server{
listen 80;
server_name .test.com;
charset utf-8;
location / {
proxy_pass http://test/;
}
}
此外upstream每一個後端的可設置參數爲:
1.down: 表示此臺server暫時不參與負載。
2.weight: 默認爲1,weight越大,負載的權重就越大。
3.max_fails: 容許請求失敗的次數默認爲1.當超過最大次數時,返回proxy_next_upstream模塊定義的錯誤。
4.fail_timeout: max_fails次失敗後,暫停的時間。
5.backup: 其它全部的非backup機器down或者忙的時候,請求backup機器,應急措施。
默認負載均衡策略
Nginx 提供輪詢(round robin)、用戶 IP 哈希(client IP)和指定權重 3 種方式。
默認狀況下,Nginx 會爲你提供輪詢做爲負載均衡策略。可是這並不必定可以讓你滿意。好比,某一時段內的一連串訪問都是由同一個用戶 Michael 發起的,那麼第一次 Michael 的請求多是 backend2,而下一次是 backend3,而後是 backend1、backend2、backend3……在大多數應用場景中,這樣並不高效。固然,也正因如此,Nginx 爲你提供了一個按照 Michael、Jason、David 等等這些亂七八糟的用戶的 IP 來 hash 的方式,這樣每一個 client 的訪問請求都會被甩給同一個後端服務器。具體的使用方式以下:
upstream backend {
ip_hash;
server backend1.example.com;
server backend2.example.com;
server.backend3.example.com;
}
這種策略中,用於進行 hash 運算的 key,是 client 的 C 類 IP 地址(C 類 IP 地址就是範圍在 192.0.0.0 到 223.255.255.255 之間,前三段號碼錶示子網,第四段號碼爲本地主機的 IP 地址類別)。這樣的方式保證一個 client 每次請求都將到達同一個 backend。固然,若是所 hash 到的 backend 當前不可用,則請求會被轉移到其餘 backend。
再介紹一個和 ip_hash 配合使用的關鍵字:down。當某個一個 server 暫時性的宕機(down)時,你可使用「down」來標示出來,而且這樣被標示的 server 就不會接受請求去處理。具體以下:
upstream backend {
server blog.csdn.net/poechant down;
server 145.223.156.89:8090;
server unix:/tmp/backend3;
}
還可使用指定權重(weight)的方式,以下:
upstream backend {
server backend1.example.com;
server 123.321.123.321:456 weight=4;
}
默認狀況下 weight 爲 1,對於上面的例子,第一個 server 的權重取默認值 1,第二個是 4,因此至關於第一個 server 接收 20% 的請求,第二接收 80% 的。要注意的是 weight 與 ip_hash 是不能同時使用的,緣由很簡單,他們是不一樣且彼此衝突的策略。
重試策略
能夠爲每一個 backend 指定最大的重試次數,和重試時間間隔。所使用的關鍵字是 max_fails 和 fail_timeout。以下所示:
upstream backend {
server backend1.example.com weight=5;
server 54.244.56.3:8081 max_fails=3 fail_timeout=30s;
}
在上例中,最大失敗次數爲 3,也就是最多進行 3 次嘗試,且超時時間爲 30秒。max_fails 的默認值爲 1,fail_timeout 的默認值是 10s。傳輸失敗的情形,由 proxy_next_upstream 或 fastcgi_next_upstream 指定。並且可使用 proxy_connect_timeout 和 proxy_read_timeout 控制 upstream 響應時間。
有一種狀況須要注意,就是 upstream 中只有一個 server 時,max_fails 和 fail_timeout 參數可能不會起做用。致使的問題就是 nginx 只會嘗試一次 upstream 請求,若是失敗這個請求就被拋棄了 : ( ……解決的方法,比較取巧,就是在 upstream 中將你這個可憐的惟一 server 多寫幾回,以下:
upstream backend {
server backend.example.com max_fails fail_timeout=30s;
server backend.example.com max_fails fail_timeout=30s;
server backend.example.com max_fails fail_timeout=30s;
}
5.6. 備機策略
從 Nginx 的 0.6.7 版本開始,可使用「backup」關鍵字。當全部的非備機(non-backup)都宕機(down)或者繁忙(busy)的時候,就只使用由 backup 標註的備機。必需要注意的是,backup 不能和 ip_hash 關鍵字一塊兒使用。舉例以下:
upstream backend {
server backend1.example.com;
server backend2.example.com backup;
server backend3.example.com;
}
6. Nginx會話親和
6.1. session sticky方式
1. 下載 Session Sticky:wget https://nginx-sticky-module.googlecode.com/files/nginx-sticky-module-1.1.tar.gz
2. 安裝模塊
若是 Nginx 以前已經安裝了,能夠經過 nginx -V 命令查看當時編譯的參數。在參數後面追加安裝 Session Sticky 模塊的參數,避免影響以前 Nginx 已有模塊。
進入 nginx 源碼目錄,執行命令:
./configure … --add-module=/usr/local/src/nginx-sticky-module-1.1
Make
make install
3. 激活模塊:在 upstream塊中添加 sticky; 便可激活Session Sticky模塊。
upstream {
sticky;
server 127.0.0.1:9000;
server 127.0.0.1:9001;
server 127.0.0.1:9002;
}
4. 可用選項:
sticky [name=route] [domain=.foo.bar] [path=/] [expires=1h] [hash=index|md5|sha1] [no_fallback];
name: 能夠爲任何的string字符,默認是route
domain:哪些域名下可使用這個cookie
path:哪些路徑對啓用sticky,例如path/test,那麼只有test這個目錄纔會使用sticky作負載均衡
expires:cookie過時時間,默認瀏覽器關閉就過時,也就是會話方式。
no_fallbackup:若是設置了這個,cookie對應的服務器宕機了,那麼將會返回502(bad gateway 或者 proxy error),建議不啓用。
nginx sticky使用注意事項:nginx sticky模塊不能與ip_hash同時使用
5. ngix sticky模塊工做流程圖:
首先根據輪詢RR隨機到某臺後端,而後在響應的Set-Cookie上加上route=md5(upstream)字段,第二次請求再處理的時候,發現有route字段,直接導向原來的那個節點。
6. 測試nginx sticky
我後端是兩臺tomcat服務器,每臺服務器的JESSIONED值都有特殊的標誌。好比209這臺是s209,225這臺是s225.打開頁面,無論怎麼刷新JESSIONED值都是不變.可是若是開啓了sticky,能夠看到JESSIONED值不會發生變化.死死的粘滯在其中一臺服務器上.測試圖以下:
使用sticky的狀況下,無論怎麼刷新都是下面圖
6.2. ip_hash模式(不推薦使用)
nginx中的ip_hash技術可以將某個ip的請求定向到同一臺後端,這樣一來這個ip下的某個客戶端和某個後端就能創建起穩固的session,ip_hash是在upstream配置中定義的:
upstream backend {
server 127.0.0.1:8080 ;
server 127.0.0.1:9090 ;
ip_hash;
}
不推薦使用的緣由以下:
1.nginx不是最前端的服務器。
ip_hash要求nginx必定是最前端的服務器,不然nginx得不到正確ip,就不能根據ip做hash。譬如使用的是squid爲最前端,那麼nginx取ip時只能獲得squid的服務器ip地址,用這個地址來做分流是確定錯亂的。
2. nginx的後端還有其它方式的負載均衡。
假如nginx後端又有其它負載均衡,將請求又經過另外的方式分流了,那麼某個客戶端的請求確定不能定位到同一臺session應用服務器上。
3.多個外網出口。
不少公司上網有多個出口,多個ip地址,用戶訪問互聯網時候自動切換ip。並且這種狀況不在少數。使用 ip_hash 的話對這種狀況的用戶無效,沒法將某個用戶綁定在固定的tomcat上。
6.3. nginx_upstream_jvm_route(nginx擴展,推薦使用)
nginx_upstream_jvm_route 是一個nginx的擴展模塊,用來實現基於 Cookie 的 Session Sticky 的功能。
簡單來講,它是基於cookie中的JSESSIONID來決定將請求發送給後端的哪一個server,nginx_upstream_jvm_route會在用戶第一次請求後端server時,將響應的server標識綁定到cookie中的JSESSIONID中,從而當用戶發起下一次請求時,nginx會根據JSESSIONID來決定由哪一個後端server來處理。
1.nginx_upstream_jvm_route安裝
下載地址(svn):http://nginx-upstream-jvm-route.googlecode.com/svn/trunk/
假設nginx_upstream_jvm_route下載後的路徑爲/usr/local/nginx_upstream_jvm_route,
(1)進入nginx源碼路徑
patch -p0 < /usr/local/nginx_upstream_jvm_route/jvm_route.patch
(2)./configure --with-http_stub_status_module --with-http_ssl_module --prefix=/usr/local/nginx --with-pcre=/usr/local/pcre-8.33 --add-module=/usr/local/nginx_upstream_jvm_route
(3)make& make install
關於nginx的下載與安裝參考:http://hanqunfeng.iteye.com/blog/697696
2.nginx配置:
upstream tomcats_jvm_route
{
server 192.168.33.10:8090 srun_id= instance1;
server 192.168.33.11:8090 srun_id= instance2;
jvm_route $cookie_JSESSIONID|sessionid reverse;
}
3. 應用服務器配置
在loong服務器上增長jvmRoute參數以下:
在集羣上建立jvm參數
1. asadmin create-jvm-options --target cluster1 "-DjvmRoute=\${INSTANCE_NAME}"
2. asadmin create-system-properties --target INSTANCE_NAME=instance1
3. asadmin create-system-properties --target instance2 INSTANCE_NAME=instance2