Nginx是俄羅斯人用c++編寫的十分輕量級的HTTP服務(wù)器,同時也能作為郵件服務(wù)器、反向代理服務(wù)器、靜態(tài)資源服務(wù)器。
簡介
- Nginx以事件驅(qū)動的方式編寫,所以有非常好的性能,同時也是一個非常高效的反向代理、負(fù)載平衡。其擁有匹配Lighttpd的性能,同時還沒有Lighttpd的內(nèi)存泄漏問題。
- Nginx專為性能優(yōu)化而開發(fā),性能是其最重要的考量,實現(xiàn)上非常注重效率 。它支持內(nèi)核Poll模型,能經(jīng)受高負(fù)載的考驗,有報告表明能支持高達(dá) 50,000個并發(fā)連接數(shù)。
- Nginx具有很高的穩(wěn)定性。其它HTTP服務(wù)器,當(dāng)遇到訪問的峰值,或者有人惡意發(fā)起慢速連接時,也很可能會導(dǎo)致服務(wù)器物理內(nèi)存耗盡頻繁交換,失去響應(yīng),只能重啟服務(wù)器。例如當(dāng)前apache一旦上到200個以上進(jìn)程,web響應(yīng)速度就明顯非常緩慢了。而Nginx采取了分階段資源分配技術(shù),使得它的CPU與內(nèi)存占用率非常低。nginx官方表示保持10,000個沒有活動的連接,它只占2.5M內(nèi)存,所以類似DOS這樣的攻擊對nginx來說基本上是毫無用處的。就穩(wěn)定性而言,nginx比lighthttpd更勝一籌。
- Nginx支持熱部署。它的啟動特別容易, 并且?guī)缀蹩梢宰龅?*24不間斷運行,即使運行數(shù)個月也不需要重新啟動。你還能夠在不間斷服務(wù)的情況下,對軟件版本進(jìn)行進(jìn)行升級。
- ……
HTTP基礎(chǔ)功能:
- 處理靜態(tài)文件,索引文件以及自動索引;
- 反向代理加速(無緩存);
- FastCGI,簡單的負(fù)載均衡和容錯;
- 模塊化的結(jié)構(gòu)。過濾器包括gzipping, byte ranges, chunked responses, 以及 SSI-filter 。在SSI過濾器中,到同一個 proxy 或者 FastCGI 的多個子請求并發(fā)處理;
- SSL 和 TLS SNI 支持;
基本概念:
1.正向代理:
用戶訪問代理服務(wù)器。網(wǎng)站對用戶不透明。對用戶服務(wù)。
2.反向代理:
用戶訪問反向代理服務(wù)器。但是用戶不知道訪問的是反向代理服務(wù)器多個站點中的哪一個站點。對服務(wù)器服務(wù)。
3.負(fù)載均衡
nginx 的 upstream目前支持 4 種方式的分配
1)、輪詢(默認(rèn)):每個請求按時間順序逐一分配到不同的后端服務(wù)器,如果后端服務(wù)器down掉,能自動剔除。
2)、weight:指定輪詢幾率,weight和訪問比率成正比,用于后端服務(wù)器性能不均的情況。
2)、ip_hash :每個請求按訪問ip的hash結(jié)果分配,這樣每個訪客固定訪問一個后端服務(wù)器,可以解決session的問題。
3)、fair(第三方):按后端服務(wù)器的響應(yīng)時間來分配請求,響應(yīng)時間短的優(yōu)先分配。
4)、url_hash(第三方)
4.異步非阻塞
和node類似Nginx 采用了異步非阻塞的方式來處理請求。Nginx 采用的是多 worker 的方式來處理請求,每個 worker 里面只有一個主線程,每個worker線程都繼承了高并發(fā)的特性。
想想 apache 的常用工作方式(apache 也有異步非阻塞版本,但因其與自帶某些模塊沖突,所以不常用),每個請求會獨占一個工作線程,當(dāng)并發(fā)數(shù)上到幾千時,就同時有幾千的線程在處理請求了。這對操作系統(tǒng)來說,是個不小的挑戰(zhàn),線程帶來的內(nèi)存占用非常大,線程的上下文切換帶來的 cpu 開銷很大,自然性能就上不去了,而這些開銷完全是沒有意義的。
命令
1.安裝
osx 用homebrew
brew install nginx
2.nginx命令
命令 | 注釋 | |
---|---|---|
nginx | 啟動nginx,按照默認(rèn)路徑 | |
nginx -t | 測試配置正確性、也可查詢默認(rèn)配置路徑 | |
nignx -c 路徑 | 按照指定路徑[啟動 | ...] |
nginx -s reload | 平滑重啟 | |
nginx -s stop | 停止nginx | |
nginx -v | 顯示 nginx 的版本 | |
nginx -V | nginx 的版本,編譯器版本和配置參數(shù)。 |
3.nginx信號
啟動nginx后會根據(jù)配置生成一個master進(jìn)程和多個worker進(jìn)程(由參數(shù)worker_processes配置,一般為機(jī)器cpu核數(shù))master 來管理 worker 進(jìn)程,所以我們只需要與 master 進(jìn)程通信就行了。master 進(jìn)程會接收來自外界發(fā)來的信號,再根據(jù)信號做不同的事情。所以我們要控制 Nginx,只需要通過 kill 向 master 進(jìn)程發(fā)送信號就行了,例如:
kill -HUP pid
//平滑重啟nginx
//pid是nginx的進(jìn)程
//若在nginx.conf配置了pid文件存放路徑則該文件存放的就是Nginx主進(jìn)程號
//可用路徑代替pid ,例如: '/usr/nginx/logs/nginx.pid'
master進(jìn)程:
信號 | 注釋 |
---|---|
TERM, INT | 快速關(guān)閉 |
QUIT | 從容關(guān)閉 |
HUP | 重載配置 \ 用新的配置開始新的工作進(jìn)程 \ 從容關(guān)閉舊的工作進(jìn)程 |
USR1 | 重新打開日志文件 |
USR2 | 平滑升級可執(zhí)行程序。 |
WINCH | 從容關(guān)閉工作進(jìn)程 |
worker進(jìn)程:
信號 | 注釋 |
---|---|
TERM, INT | 快速關(guān)閉 |
QUIT | 從容關(guān)閉 |
USR1 | 重新打開日志文件 |
conf配置
基本參數(shù)
#運行用戶
user nobody;
#啟動進(jìn)程,通常設(shè)置成和cpu的數(shù)量相等
worker_processes 2;
#nginx pid進(jìn)程號存儲地址
pid logs/nginx.pid;
events {
#ulimit -n 一個進(jìn)程所能夠打開的文件的最大數(shù)
#反向代理,最大并發(fā)數(shù) worker_connections * worker_processes/2
worker_connections 1024;
}
負(fù)載均衡
在http節(jié)點里添加:
#定義負(fù)載均衡設(shè)備的 Ip及設(shè)備狀態(tài)
upstream myServer {
server 127.0.0.1:9090 down;
server 127.0.0.1:8080 weight=2;
server 127.0.0.1:6060;
server 127.0.0.1:7070 backup;
ip_hash;
}
在需要使用負(fù)載的Server節(jié)點下添加
proxy_pass http://myServer;
upstream 每個設(shè)備的狀態(tài):
- down :表示單前的server暫時不參與負(fù)載
- weight :默認(rèn)為1.weight越大,負(fù)載的權(quán)重就越大。
- max_fails :允許請求失敗的次數(shù)默認(rèn)為1.當(dāng)超過最大次數(shù)時,返回proxy_next_upstream 模塊定義的錯誤
- fail_timeout:max_fails 次失敗后,暫停的時間。
- backup: 其它所有的非backup機(jī)器down或者忙的時候,請求backup機(jī)器。所以這臺機(jī)器壓力會最輕。
ip_hash
使用負(fù)載均衡服務(wù)器一多就會出現(xiàn)一個問題,那怎么實現(xiàn)多臺服務(wù)器之間session的共享。其中一個方案就是ip_hash。nginx中的ip_hash能夠?qū)⒛硞€ip的請求定向到同一臺后端,這樣一來這個ip下的某個客戶端和某個后端就能建立起穩(wěn)固的session;
nginx 編程
1.nginx變量
Nginx 變量的創(chuàng)建和賦值操作發(fā)生在全然不同的時間階段。Nginx 變量的創(chuàng)建只能發(fā)生在 Nginx 配置加載的時候,或者說 Nginx 啟動的時候;而賦值操作則只會發(fā)生在請求實際處理的時候。這意味著不創(chuàng)建而直接使用變量會導(dǎo)致啟動失敗,同時也意味著我們無法在請求處理時動態(tài)地創(chuàng)建新的 Nginx 變量。
server {
listen 8080;
location /foo {
echo "foo = [$foo]";
}
location /bar {
set $foo 32;
echo "foo = [$foo]";
}
}
我們使用了標(biāo)準(zhǔn) ngx_rewrite 模塊的 set 配置指令對變量 $a 進(jìn)行了賦值操作。特別地,我們把字符串 hello world 賦給了它。
這里我們使用第三方 ngx_echo 模塊的 echo 配置指令將 $foo 變量的值作為當(dāng)前請求的響應(yīng)體輸出。
我們用curl訪問地址:
$ curl 'http://localhost:8080/foo' //foo = []
$ curl 'http://localhost:8080/bar' //foo = [32]
2.Nginx 內(nèi)建變量
例如由 ngx_http_core 模塊提供的內(nèi)建變量 $uri,可以用來獲取當(dāng)前請求的 URI(經(jīng)過解碼,并且不含請求參數(shù)),而 $request_uri 則用來獲取請求最原始的 URI (未經(jīng)解碼,并且包含請求參數(shù))。但是大部分內(nèi)建變量類似保留值不可被賦值。
location /test {
echo "uri = $uri";
echo "request_uri = $request_uri";
echo "name: $arg_name";//name不區(qū)分大小寫
}
$ curl "http://localhost:8080/test?Name=aaa"
:uri = /test
:request_uri = /test
:name: aaa
$ curl "http://localhost:8080/test?a=3&b=4"
:uri = /test
:request_uri = /test?a=3&b=4
:name:
也有一些內(nèi)建變量是支持改寫的,其中一個例子是 $args. 這個變量在讀取時返回當(dāng)前請求的 URL 參數(shù)串(即請求 URL 中問號后面的部分,如果有的話),而在賦值時可以直接修改參數(shù)串:
location /test {
set $orig_a $arg_a;
set $args "a=5";
echo "original a: $orig_a";
echo "a: $arg_a";
}
$ curl 'http://localhost:8080/test?a=3'
:original a: 3
:a: 5
原本$arg_a應(yīng)該返回參數(shù)a=3,但是訪問時賦值了$args 'a=5',所以取$arg_a時返回了5;
參考鏈接:
http://www.ttlsa.com/nginx/nginx-tutorial-from-entry-to-the-master-ttlsa/
https://openresty.org/download/agentzh-nginx-tutorials-zhcn.html
http://wiki.jikexueyuan.com/project/nginx/nginx-framework.html