Linux Nginx構(gòu)建反向代理緩存服務(wù)器

2018-07-31 14:44 更新

防偽碼:曾經(jīng)滄海難為水,除卻巫山不是云。

代理服務(wù)可簡單的分為正向代理和反向代理:

正向代理: 用于代理內(nèi)部網(wǎng)絡(luò)對Internet的連接請求(VPN/NAT),客戶端指定代理服務(wù)器,并將本來要直接發(fā)送給目標(biāo)Web服務(wù)器HTTP請求先發(fā)送到代理服務(wù)器上,然后由代理服務(wù)器去訪問Web服務(wù)器, 并將Web服務(wù)器的Response回傳給客戶端

反向代理: 與正向代理相反,如果局域網(wǎng)向Internet提供資源,并讓Internet上的其他用戶可以訪問局域網(wǎng)內(nèi)資源, 也可以設(shè)置一個代理服務(wù)器, 它提供的服務(wù)就是反向代理. 反向代理服務(wù)器接受來自Internet的連接,然后將請求轉(zhuǎn)發(fā)給內(nèi)部網(wǎng)絡(luò)上的服務(wù)器,并將Response回傳給Internet上請求連接的客戶端

一、nginx反向代理:Web服務(wù)器的調(diào)度器

1、反向代理(Reverse Proxy)方式是指以代理服務(wù)器來接受客戶端的連接請求,然后將請求轉(zhuǎn)發(fā)給網(wǎng)絡(luò)上的web服務(wù)器(可能是apachenginx、tomcat、iis等),并將從web服務(wù)器上得到的結(jié)果返回給請求連接的客戶端,此時代理服務(wù)器對外就表現(xiàn)為一個服務(wù)器。

從上圖可以看出:反向代理服務(wù)器代理網(wǎng)站Web服務(wù)器接收Http請求,對請求進行轉(zhuǎn)發(fā)。而且nginx作為反向代理服務(wù)器可以根據(jù)用戶請求的內(nèi)容把請求轉(zhuǎn)發(fā)給后端不同的web服務(wù)器,例如靜動分離,再例如在nginx上創(chuàng)建多個虛擬主機,這樣就成功的做到了在瀏覽器中輸入不同域名(url)的時候訪問后端的不同web服務(wù)器或web群集。

 

2、反向代理的作用

保護網(wǎng)站安全:任何來自Internet的請求都必須先經(jīng)過代理服務(wù)器;

通過配置緩存功能加速Web請求:可以緩存真實Web服務(wù)器上的某些靜態(tài)資源,減輕真實Web服務(wù)器的負載壓力;

實現(xiàn)負載均衡:充當(dāng)負載均衡服務(wù)器均衡地分發(fā)請求,平衡集群中各個服務(wù)器的負載壓力;

二、什么是nginx

1nginx簡介

Nginx是一款輕量級的網(wǎng)頁服務(wù)器、反向代理器以及電子郵件代理服務(wù)器。因它的穩(wěn)定性、豐富的功能集、示例配置文件和低系統(tǒng)資源的消耗而聞名。Nginx(發(fā)音同engine x),它是由俄羅斯程序員Igor Sysoev所開發(fā)的。起初是供俄國大型的門戶網(wǎng)站及搜索引擎Rambler(俄語:Рамблер)使用。此軟件BSD-like協(xié)議下發(fā)行,可以在UNIX、GNU/Linux、BSD、Mac OS X、Solaris,以及Microsoft Windows等操作系統(tǒng)中運行。

Nginx的應(yīng)用現(xiàn)狀

Nginx 已經(jīng)在俄羅斯最大的門戶網(wǎng)站── Rambler Mediawww.rambler.ru)上運行,同時俄羅斯超過20%的虛擬主機平臺采用Nginx作為反向代理服務(wù)器。

在國內(nèi),已經(jīng)有淘寶、新浪博客、新浪播客、網(wǎng)易新聞、六間房、56.com、Discuz!、水木社區(qū)、豆瓣、YUPOO、海內(nèi)、迅雷在線等多家網(wǎng)站使用 Nginx 作為Web服務(wù)器或反向代理服務(wù)器。

2、Nginx的核心特點

1跨平臺:Nginx 可以在大多數(shù)OS編譯運行,而且也有Windows的版本;

2配置異常簡單:非常容易上手。

3非阻塞、高并發(fā)連接官方測試能夠支撐5并發(fā)連接,在實際生產(chǎn)環(huán)境中跑到23萬并發(fā)連接數(shù)。(這得益于Nginx使用了最新的epoll模型);

注:

對于一個Web服務(wù)器來說,首先看一個請求的基本過程:建立連接—接收數(shù)據(jù)—發(fā)送數(shù)據(jù),在系統(tǒng)底層看來:上述過程(建立連接—接收數(shù)據(jù)—發(fā)送數(shù)據(jù))在系統(tǒng)底層就是讀寫事件。

 

如果采用阻塞調(diào)用的方式,當(dāng)讀寫事件沒有準(zhǔn)備好時,那么就只能等待,當(dāng)前線程被掛起,等事件準(zhǔn)備好了,才能進行讀寫事件。

如果采用非阻塞調(diào)用的方式:事件馬上返回,告訴你事件還沒準(zhǔn)備好呢,過會再來吧。過一會,再來檢查一下事件,直到事件準(zhǔn)備好了為止,在這期間,你就可以先去做其它事情,然后再來看看事件好了沒。雖然不阻塞了,但你得不時地過來檢查一下事件的狀態(tài),你可以做更多的事情了,但帶來的開銷也是不小的。非阻塞調(diào)用指在不能立刻得到結(jié)果之前,該調(diào)用不會阻塞當(dāng)前線程

4事件驅(qū)動:通信機制采用epoll模型,支持更大的并發(fā)連接。

非阻塞通過不斷檢查事件的狀態(tài)來判斷是否進行讀寫操作,這樣帶來的開銷很大,因此就有了異步非阻塞的事件處理機制。這種機制讓你可以同時監(jiān)控多個事件,調(diào)用他們是非阻塞的,但可以設(shè)置超時時間,在超時時間之內(nèi),如果有事件準(zhǔn)備好了,就返回。這種機制解決了上面阻塞調(diào)用與非阻塞調(diào)用的兩個問題。

epoll模型為例:當(dāng)事件沒有準(zhǔn)備好時,就放入epoll(隊列)里面。如果有事件準(zhǔn)備好了,那么就去處理;當(dāng)事件沒有準(zhǔn)備好時,才在 epoll里面等著。這樣,我們就可以并發(fā)處理大量的并發(fā)了,當(dāng)然,這里的并發(fā)請求,是指未處理完的請求。線程只有一個,所以同時能處理的請求當(dāng)然只有一個了,只是在請求之間進行不斷地切換而已,切換也是因為異步事件未準(zhǔn)備好,而主動讓出的。這里的切換是沒有任何代價,你可以理解為循環(huán)處理多個準(zhǔn)備好的事件。

多線程方式相比,這種事件處理方式是有很大的優(yōu)勢的,不需要創(chuàng)建線程,每個請求占用的內(nèi)存也很少,沒有上下文切換,事件處理非常的輕量級,并發(fā)數(shù)再多也不會導(dǎo)致無謂的資源浪費(上下文切換)。對于apache服務(wù)器,每個請求會獨占一個工作線程,當(dāng)并發(fā)數(shù)上到幾千時,就同時有幾千的線程在處理請求了。這對操作系統(tǒng)來說,是個不小的挑戰(zhàn):因為線程帶來的內(nèi)存占用非常大,線程的上下文切換帶來的cpu開銷很大,自然性能就上不去,從而導(dǎo)致在高并發(fā)場景下性能下降嚴(yán)重。

總結(jié):通過異步非阻塞的事件處理機制,Nginx實現(xiàn)由進程循環(huán)處理多個準(zhǔn)備好的事件,從而實現(xiàn)高并發(fā)和輕量級。

5Master/Worker結(jié)構(gòu):一個master進程,生成一個或多個worker進程。

注:Master-Worker設(shè)計模式主要包含兩個主要組件MasterWorkerMaster維護著Worker隊列,將請求下發(fā)到多個Worker并行執(zhí)行,Worker主要進行實際邏輯計算,并將結(jié)果返回給Master

nginx采用這種進程模型有什么好處?采用獨立的進程,可以讓互相之間不會影響,一個進程退出后,其它進程還在工作,服務(wù)不會中斷,Master 進程則很快重新啟動新的Worker進程。當(dāng)然,Worker進程的異常退出,肯定是程序有bug了,異常退出,會導(dǎo)致當(dāng)前Worker上的所有請求失敗,不過不會影響到所有請求,所以降低了風(fēng)險。

6內(nèi)存消耗?。?/span>處理大并發(fā)的請求內(nèi)存消耗非常小。在3萬并發(fā)連接下,開啟的10Nginx 進程才消耗150M內(nèi)存(15M*10=150M)。

7內(nèi)置的健康檢查功能:如果 Nginx 代理的后端的某臺 Web 服務(wù)器宕機了,不會影響前端訪問。

8節(jié)省帶寬:支持 GZIP 壓縮,可以添加瀏覽器本地緩存的 Header 頭。

9穩(wěn)定性高:用于反向代理,宕機的概率微乎其微。

三、Nginx+apache構(gòu)筑Web服務(wù)器集群的負載均衡

nginx配置反向代理

配置nginx作為反向代理和負載均衡,同時利用其緩存功能,將靜態(tài)頁面在nginx緩存,以達到降低后端服務(wù)器連接數(shù)的目的并檢查后端web服務(wù)器的健康狀況。

 

1、安裝nginx

環(huán)境:

1
2
3
4
OS:centos7.2
nginx:192.168.31.83
apache1:192.168.31.141
apache2:192.168.31.250

安裝zlib-devel、pcre-devel等依賴包

1
[root@www ~]# yum -y install gcc gcc-c++make libtool zlib zlib-devel pcre pcre-devel openssl openssl-devel

注:

結(jié)合proxyupstream模塊實現(xiàn)后端web負載均衡

使用proxy模塊實現(xiàn)靜態(tài)文件緩存

結(jié)合nginx默認自帶的 ngx_http_proxy_module 模塊 ngx_http_upstream_module模塊實現(xiàn)后端服務(wù)器的健康檢查,也可以使用第三方模塊nginx_upstream_check_module

使用nginx-sticky-module擴展模塊實現(xiàn)Cookie會話黏貼(保持會話)

使用ngx_cache_purge實現(xiàn)更強大的緩存清除功能

上面提到的2個模塊都屬于第三方擴展模塊,需要提前下好源碼,然后編譯時通過--add-moudle=src_path一起安裝。

安裝nginx

1
2
[root@www ~]# groupadd www    #添加www組
[root@www ~]# useradd -g www www -s/sbin/nologin    #創(chuàng)建nginx運行賬戶www并加入到www組,不允許www用戶直接登錄系統(tǒng)
1
2
3
4
5
6
#tar zxf nginx-1.10.2.tar.gz
#tar zxf ngx_cache_purge-2.3.tar.gz 
#tar zxf master.tar.gz
# cd nginx-1.10.2/
[root@www nginx-1.10.2]# ./configure--prefix=/usr/local/nginx1.10 --user=www --group=www--with-http_stub_status_module --with-http_realip_module --with-http_ssl_module--with-http_gzip_static_module--http-client-body-temp-path=/var/tmp/nginx/client--http-proxy-temp-path=/var/tmp/nginx/proxy --http-fastcgi-temp-path=/var/tmp/nginx/fcgi--with-pcre --add-module=../ngx_cache_purge-2.3 --with-http_flv_module --add-module=../nginx-goodies-nginx-sticky-module-ng-08a395c66e42
[root@www nginx-1.10.2]# make &&make install

注:nginx的所有模塊必須在編譯的時候添加,不能再運行的時候動態(tài)加載。

優(yōu)化nginx程序的執(zhí)行路徑

1
2
3
4
5
6
7
[root@www nginx-1.10.2]# ln -s/usr/local/nginx1.10/sbin/nginx /usr/local/sbin/
[root@www nginx-1.10.2]# nginx -t
[root@www nginx-1.10.2]# mkdir -p/var/tmp/nginx/client
[root@www nginx-1.10.2]# chown -Rwww:www /var/tmp/nginx/
[root@www nginx-1.10.2]# nginx -t
nginx: the configuration file/usr/local/nginx1.10/conf/nginx.conf syntax is ok
nginx: configuration file/usr/local/nginx1.10/conf/nginx.conf test is successful

2、編寫nginx服務(wù)腳本:

[root@www ~]# vi /etc/init.d/nginx  內(nèi)容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#!/bin/bash
# chkconfig: 2345 99 20
# description: Nginx Service ControlScript
PROG="/usr/local/nginx1.10/sbin/nginx"
PIDF="/usr/local/nginx1.10/logs/nginx.pid"
case "$1" in
 start)
  netstat -anplt |grep ":80" &> /dev/null &&pgrep "nginx" &> /dev/null
  if [ $? -eq 0 ]
  then
    echo "Nginx service alreadyrunning."
  else
    $PROG -t &> /dev/null
    if [ $? -eq 0 ] ; then 
      $PROG
      echo "Nginx service start success."
    else
    $PROG -t
    fi
  fi
  ;;
 stop)
  netstat -anplt |grep ":80" &> /dev/null &&pgrep "nginx" &> /dev/null
  if [ $? -eq 0 ]
  then
   kill -s QUIT $(cat $PIDF)
   echo "Nginx service stop success." 
  else
   echo "Nginx service already stop"
  fi
  ;;
 restart)
   $0 stop
   $0 start
   ;;
 status)
  netstat -anplt |grep ":80" &> /dev/null &&pgrep "nginx" &> /dev/null
  if [ $? -eq 0 ]
  then
    echo "Nginx service is running."
  else
    echo "Nginx is stop."
  fi
 ;; 
 reload)
  netstat -anplt |grep ":80" &> /dev/null &&pgrep "nginx" &> /dev/null
  if [ $? -eq 0 ]
  then
   $PROG -t &> /dev/null
   if [ $? -eq 0 ] ; then
     kill -s HUP $(cat $PIDF)
     echo "reload Nginx config success."
   else
     $PROG -t
   fi
  else
   echo "Nginx service is not run." 
  fi 
   ;;
 *)
  echo "Usage: $0 {start|stop|restart|reload}"
  exit 1
esac
[root@www ~]# chmod +x /etc/init.d/nginx
[root@www ~]# chkconfig --add nginx
[root@www ~]# chkconfig nginx on
[root@www ~]# service  nginx start
Nginx service start success.
[root@www ~]# service  nginx status
Nginx service is running.
[root@www ~]# netstat -anpt | grep nginx
tcp        0     0 0.0.0.0:80             0.0.0.0:*               LISTEN      3977/nginx: master  
[root@www ~]# firewall-cmd --permanent--add-port=80/tcp
success
[root@www ~]# firewall-cmd --reload
Success

注:如果你想在已安裝好的nginx上添加第三方模塊,依然需要重新編譯,但為了不覆蓋你原有的配置,請不要make install,而是直接拷貝可執(zhí)行文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# nginx –V
[root@www nginx-1.10.2]#./configure  --add-module=……   #你的第三方模塊
[root@www nginx-1.10.2] #make后不要makeinstall,改為手動拷貝,先備份
[root@www nginx-1.10.2]#cp /usr/local/nginx1.10/sbin/nginx /usr/local/nginx1.10/sbin/nginx.bak
[root@wwwnginx-1.10.2] #cp objs/nginx /usr/local/nginx1.10/sbin/nginx
配置nginx反向代理:反向代理+負載均衡+健康探測
查看nginx加載的模塊
[root@www ~]## nginx -V
nginx version: nginx/1.10.2
built by gcc 4.8.5 20150623 (Red Hat4.8.5-4) (GCC) 
built with OpenSSL 1.0.1e-fips 11 Feb2013
TLS SNI support enabled
configure arguments:--prefix=/usr/local/nginx1.10 --user=www --group=www--with-http_stub_status_module --with-http_realip_module --with-http_ssl_module--with-http_gzip_static_module--http-client-body-temp-path=/var/tmp/nginx/client--http-proxy-temp-path=/var/tmp/nginx/proxy--http-fastcgi-temp-path=/var/tmp/nginx/fcgi --with-pcre--add-module=../ngx_cache_purge-2.3 --with-http_flv_module --add-module=../nginx-goodies-nginx-sticky-module-ng-08a395c66e42
nginx的所有模塊必須在編譯的時候添加,不能再運行的時候動態(tài)加載。

3、nginx-sticky-module模塊:

這個模塊的作用是通過cookie黏貼的方式將來自同一個客戶端(瀏覽器)的請求發(fā)送到同一個后端服務(wù)器上處理,這樣一定程度上可以解決多個backend serverssession同步的問題 —— 因為不再需要同步,而RR輪詢模式必須要運維人員自己考慮session同步的實現(xiàn)。

另外內(nèi)置的 ip_hash 也可以實現(xiàn)根據(jù)客戶端IP來分發(fā)請求,但它很容易造成負載不均衡的情況,而如果nginx前面有CDN網(wǎng)絡(luò)或者來自同一局域網(wǎng)的訪問,它接收的客戶端IP是一樣的,容易造成負載不均衡現(xiàn)象。nginx-sticky-modulecookie過期時間,默認瀏覽器關(guān)閉就過期。

這個模塊并不合適不支持 Cookie 或手動禁用了cookie的瀏覽器,此時默認sticky就會切換成RR。它不能與ip_hash同時使用。

1
2
3
4
5
upstream backend {
       server 192.168.31.141:80 weight=1;
       server 192.168.31.250:80 weight=1;
       sticky;
}

配置起來超級簡單,一般來說一個sticky指令就夠了。

相關(guān)信息可以查看官方文檔

1
https://bitbucket.org/nginx-goodies/nginx-sticky-module-ng

4、load-balance其它調(diào)度方案:

這里順帶介紹一下nginx的負載均衡模塊支持的其它調(diào)度算法:

輪詢(默認) :每個請求按時間順序逐一分配到不同的后端服務(wù)器,如果后端某臺服務(wù)器宕機,故障系統(tǒng)被自動剔除,使用戶訪問不受影響。Weight 指定輪詢權(quán)值,Weight值越大,分配到的訪問機率越高,主要用于后端每個服務(wù)器性能不均的情況下。

ip_hash  每個請求按訪問IPhash結(jié)果分配,這樣來自同一個IP的訪客固定訪問一個后端服務(wù)器,有效解決了動態(tài)網(wǎng)頁存在的session共享問題。當(dāng)然如果這個節(jié)點不可用了,會發(fā)到下個節(jié)點,而此時沒有session同步的話就注銷掉了。

least_conn :請求被發(fā)送到當(dāng)前活躍連接最少的realserver上。會考慮weight的值。

url_hash  此方法按訪問urlhash結(jié)果來分配請求,使每個url定向到同一個后端服務(wù)器,可以進一步提高后端緩存服務(wù)器的效率。Nginx本身是不支持url_hash的,如果需要使用這種調(diào)度算法,必須安裝Nginx hash軟件包 nginx_upstream_hash 。

fair :這是比上面兩個更加智能的負載均衡算法。此種算法可以依據(jù)頁面大小和加載時間長短智能地進行負載均衡,也就是根據(jù)后端服務(wù)器的響應(yīng)時間來分配請求,響應(yīng)時間短的優(yōu)先分配。Nginx本身是不支持fair的,如果需要使用這種調(diào)度算法,必須下載Nginx upstream_fair 模塊。

 

5、負載均衡與健康檢查:

嚴(yán)格來說,nginx自帶是沒有針對負載均衡后端節(jié)點的健康檢查的,但是可以通過默認自帶的 ngx_http_proxy_module 模塊和ngx_http_upstream_module 模塊中的相關(guān)指令來完成當(dāng)后端節(jié)點出現(xiàn)故障時,自動切換到下一個節(jié)點來提供訪問。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
upstream backend {
       sticky;
       server 192.168.31.141:80 weight=1 max_fails=2 fail_timeout=10s;
       server 192.168.31.250:80 weight=1 max_fails=2 fail_timeout=10s;
}
server {
  ……
location / {
           proxy_pass http://backend;
}
……
}
weight : 輪詢權(quán)值也是可以用在ip_hash的,默認值為1
max_fails : 允許請求失敗的次數(shù),默認為1。當(dāng)超過最大次數(shù)時,返回proxy_next_upstream模塊定義的錯誤。
fail_timeout : 有兩層含義,一是在10s 時間內(nèi)最多容許2 次失??;二是在經(jīng)歷了 2 次失敗以后,10s時間內(nèi)不分配請求到這臺服務(wù)器。

6、nginxproxy緩存使用:

緩存也就是將jscss、image等靜態(tài)文件從后端服務(wù)器緩存到nginx指定的緩存目錄下,既可以減輕后端服務(wù)器負擔(dān),也可以加快訪問速度,但這樣緩存及時清理成為了一個問題,所以需要 ngx_cache_purge 這個模塊來在過期時間未到之前,手動清理緩存。

proxy模塊中常用的指令時proxy_passproxy_cache.

nginxweb緩存功能的主要是由proxy_cache、fastcgi_cache指令集和相關(guān)指令集完成,proxy_cache指令負責(zé)反向代理緩存后端服務(wù)器的靜態(tài)內(nèi)容,fastcgi_cache主要用來處理FastCGI動態(tài)進程緩存。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
http {
   #$upstream_cache_status記錄緩存命中率
log_format  main  '$remote_addr - $remote_user [$time_local]"$request" '
                      '$status $body_bytes_sent"$http_referer" '
                     '"$http_user_agent" "$http_x_forwarded_for"'
                      '"$upstream_cache_status"';
access_log  logs/access.log  main;
proxy_buffering on;   #代理的時候,開啟或關(guān)閉緩沖后端服務(wù)器的響應(yīng)
proxy_temp_path /usr/local/nginx1.10/proxy_temp;
   proxy_cache_path /usr/local/nginx1.10/proxy_cachelevels=1:2 keys_zone=my-cache:100m  inactive=600mmax_size=2g;
   server {
       listen       80;
       server_name  localhost;
       root   html;
       index  index.php index.htmlindex.htm;
       #ngx_cache_purge實現(xiàn)緩存清除
       location  ~/purge(/.*) {
           allow 127.0.0.1;
           allow 192.168.31.0/24;
           deny all;
          proxy_cache_purge my-cache$host$1$is_args$args;
       }
     location ~ .*\.(gif|jpg|png|html|htm|css|js|ico|swf|pdf)(.*) {
           proxy_pass  http://backend;
           proxy_redirect off;
           proxy_set_headerHost $host;
           proxy_set_header X-Real-IP$remote_addr;
           proxy_set_header X-Forwarded-For$proxy_add_x_forwarded_for;
           proxy_ignore_headers Set-Cookie;
proxy_hide_header Set-Cookie;
           proxy_next_upstream error timeoutinvalid_header http_500 http_502 http_503 http_504;
           proxy_cachemy-cache;
           add_header Nginx-Cache$upstream_cache_status;
           proxy_cache_valid200 304 301 302 8h;
           proxy_cache_valid 404 1m;
           proxy_cache_valid any 1d;
           proxy_cache_key$host$uri$is_args$args;
          expires30d;
      }

相關(guān)選項說明:

proxy_buffering on; 代理的時候,開啟或關(guān)閉緩沖后端服務(wù)器的響應(yīng)。

當(dāng)開啟緩沖時,nginx盡可能快地從被代理的服務(wù)器接收響應(yīng),再將它存入緩沖區(qū)中。

 

proxy_temp_path 緩存臨時目錄。后端的響應(yīng)并不直接返回客戶端,而是先寫到一個臨時文件中,然后被rename一下當(dāng)做緩存放在 proxy_cache_path 。0.8.9版本以后允許tempcache兩個目錄在不同文件系統(tǒng)上(分區(qū)),然而為了減少性能損失還是建議把它們設(shè)成一個文件系統(tǒng)上。

 

proxy_cache_path 設(shè)置緩存目錄,目錄里的文件名是cache_key MD5值。

levels=1:2 keys_zone=my-cache:100m表示采用2級目錄結(jié)構(gòu),第一層目錄只有一個字符,是由levels=1:2設(shè)置,總共二層目錄,子目錄名字由二個字符組成。Web緩存區(qū)名稱為my-cache,內(nèi)存緩存空間大小為100MB,這個緩沖zone可以被多次使用。文件系統(tǒng)上看到的緩存文件名類似于 /usr/local/nginx1.10/proxy_cache/c/29/b7f54b2df7773722d382f4809d65029c。

inactive=600 max_size=2g表示600分鐘沒有被訪問的內(nèi)容自動清除,硬盤最大緩存空間為2GB,超過這個大小將清除最近最少使用的數(shù)據(jù)。

 

需要在默認情況,nginx不緩存從后端響應(yīng)的http頭中帶有Set-Cookie的對象。如果客戶端發(fā)送的請求帶有Cookie header,varnish將忽略緩存,直接將請求傳遞到后端。nginx中通過proxy_ignore_headers設(shè)置忽略它們,設(shè)置方法如下:

解決辦法:  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
proxy_ignore_headers Set-Cookie;
proxy_hide_header Set-Cookie;
  
  
  
proxy_cache : 引用前面定義的緩存區(qū) my-cache
  
proxy_cache_key :定義如何生成緩存的鍵,設(shè)置web緩存的key值,nginx根據(jù)key值md5哈希存儲緩存
  
proxy_cache_valid : 為不同的響應(yīng)狀態(tài)碼設(shè)置不同的緩存時間,比如200、302等正常結(jié)果可以緩存的時間長點,而404、500等緩存時間設(shè)置短一些,這個時間到了文件就會過期,而不論是否剛被訪問過。
  
add_header指令來設(shè)置response header,語法: add_header name value;
$upstream_cache_status這個變量來顯示緩存的狀態(tài),我們可以在配置中添加一個http頭來顯示這一狀態(tài),
$upstream_cache_status包含以下幾種狀態(tài): ·MISS 未命中,請求被傳送到后端 ·HIT 緩存命中 ·EXPIRED 緩存已經(jīng)過期請求被傳送到后端 ·UPDATING 正在更新緩存,將使用舊的應(yīng)答 ·STALE 后端將得到過期的應(yīng)答
  
expires : 在響應(yīng)頭里設(shè)置Expires:或Cache-Control:max-age,返回給客戶端的瀏覽器緩存失效時間。
  
下面的nginx.conf實現(xiàn)nginx在前端做反向代理服務(wù)器的完整配置文件的例子,處理js、png等靜態(tài)文件,jsp/php等動態(tài)請求轉(zhuǎn)發(fā)到其它服務(wù)器tomcat/apache
user www www;
worker_processes  4;
worker_cpu_affinity 0001 0010 0100 1000;
error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;
worker_rlimit_nofile 10240;
pid        logs/nginx.pid;
events {
   use epoll;
   worker_connections  4096;
}
http {
   include       mime.types;
   default_type application/octet-stream;
   log_format  main  '$remote_addr - $remote_user [$time_local]"$request" '
                      '$status $body_bytes_sent"$http_referer" '
                     '"$http_user_agent""$http_x_forwarded_for"'
                     '"$upstream_cache_status"';
access_log  logs/access.log  main;
server_tokensoff;
   sendfile        on;
   #tcp_nopush     on;
   #keepalive_timeout  0;
   keepalive_timeout  65;
   #Compression Settings
   gzip on;
   gzip_comp_level 6;
   gzip_http_version 1.1;
   gzip_proxied any;
   gzip_min_length 1k;
   gzip_buffers 16 8k;
   gzip_types text/plain text/css text/javascript application/jsonapplication/javascript application/x-javascript application/xml;
   gzip_vary on;
   #end gzip
   # http_proxy Settings
   client_max_body_size   10m;
   client_body_buffer_size   128k;
   proxy_connect_timeout   75;
   proxy_send_timeout   75;
   proxy_read_timeout   75;
   proxy_buffer_size   4k;
   proxy_buffers   4 32k;
   proxy_busy_buffers_size   64k;
proxy_temp_file_write_size  64k;
proxy_bufferingon;
   proxy_temp_path /usr/local/nginx1.10/proxy_temp;
   proxy_cache_path /usr/local/nginx1.10/proxy_cache levels=1:2keys_zone=my-cache:100m max_size=1000m inactive=600m max_size=2g;
   #load balance Settings
   upstream backend {
       sticky;
       server 192.168.31.141:80 weight=1 max_fails=2 fail_timeout=10s;
       server 192.168.31.250:80 weight=1 max_fails=2 fail_timeout=10s;
   }
   #virtual host Settings
   server {
       listen       80;
       server_name  localhost;
       charset utf-8;
       location  ~/purge(/.*) {
           allow 127.0.0.1;
           allow 192.168.31.0/24;
           deny all;
           proxy_cache_purge my-cache$host$1$is_args$args;
       }
       location / {
            index  index.php index.html index.htm;
            proxy_pass        http://backend;
            proxy_redirect off;
           proxy_set_header  Host $host;
            proxy_set_header  X-Real-IP $remote_addr;
            proxy_set_header  X-Forwarded-For  $proxy_add_x_forwarded_for;
            proxy_ignore_headers Set-Cookie;
proxy_hide_header Set-Cookie;
            proxy_next_upstream error timeoutinvalid_header http_500 http_502 http_503 http_504;
       }
       location ~ .*\.(gif|jpg|png|html|htm|css|js|ico|swf|pdf)(.*) {
           proxy_pass  http://backend;
           proxy_redirect off;
           proxy_set_header Host $host;
           proxy_set_header X-Real-IP$remote_addr;
           proxy_set_header X-Forwarded-For$proxy_add_x_forwarded_for;
           proxy_next_upstream error timeoutinvalid_header http_500 http_502 http_503 http_504;
           proxy_cache my-cache;
           add_header Nginx-Cache$upstream_cache_status;
           proxy_cache_valid 200 304 301 3028h;
           proxy_cache_valid 404 1m;
           proxy_cache_valid any 1d;
           proxy_cache_key$host$uri$is_args$args;
          expires 30d;
       }
       location /nginx_status {
            stub_status on;
            access_log off;
            allow 192.168.31.0/24;
            deny all;
       }
   }
}

常用指令說明:

main全局配置:

woker_processes 4
在配置文件的頂級main部分,worker角色的工作進程的個數(shù),master進程是接收并分配請求給worker處理。這個數(shù)值簡單一點可以設(shè)置為cpu的核數(shù)
grep^processor /proc/cpuinfo | wc -l,也是 auto 值,如果開啟了sslgzip更應(yīng)該設(shè)置成與邏輯CPU數(shù)量一樣甚至為2倍,可以減少I/O操作。如果nginx服務(wù)器還有其它服務(wù),可以考慮適當(dāng)減少。

 

worker_cpu_affinity
也是寫在main部分。在高并發(fā)情況下,通過設(shè)置cpu粘性來降低由于多CPU核切換造成的寄存器等現(xiàn)場重建帶來的性能損耗。如
worker_cpu_affinity0001 0010 0100 1000; (四核)。

附:

CPU工作狀況:(輸入 top 后,按1 查看)

上面的配置表示:4CPU,開啟4個進程。0001表示開啟第一個cpu內(nèi)核, 0010表示開啟第二個cpu內(nèi)核,依次類推;有多少個核,就有幾位數(shù),1表示該內(nèi)核開啟,0表示該內(nèi)核關(guān)閉。

例如:

1、2CPU,開啟2個進程

worker_processes  2;

worker_cpu_affinity 0110;

2、2CPU,開啟4進程

worker_processes 4;

worker_cpu_affinity 01100110;

、2CPU,開啟8進程

worker_processes  8;

worker_cpu_affinity 0110011001100110;

4、8CPU,開啟2進程

worker_processes  2;

worker_cpu_affinity 10101010  01010101;

說明:10101010表示開啟了第2,4,6,8內(nèi)核,01010101表示開始了1,3,5,7內(nèi)核

通過 apache ab測試查看nginxCPU的使用狀況:

如果多個CPU內(nèi)核的利用率都相差不多,證明nginx己經(jīng)成功的利用了多核CPU。

測試結(jié)束后,CPU內(nèi)核的負載應(yīng)該都同時降低。

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
worker_connections 4096寫在events部分。每一個worker進程能并發(fā)處理(發(fā)起)的最大連接數(shù)(包含與客戶端或后端被代理服務(wù)器間等所有連接數(shù))。
  
worker_rlimit_nofile 10240寫在main部分。worker進程的最大打開文件數(shù)限制。默認是沒有設(shè)置,如果沒設(shè)置的話,這個值為操作系統(tǒng)的限制(ulimit-n)??梢韵拗茷椴僮飨到y(tǒng)最大的限制65535。把這個值設(shè)高,這樣nginx就不會有“too many open files”問題了。
  
use epoll寫在events部分。在Linux操作系統(tǒng)下,nginx默認使用epoll事件模型,得益于此,nginx在Linux操作系統(tǒng)下效率相當(dāng)高。同時Nginx在OpenBSD或FreeBSD操作系統(tǒng)上采用類似于epoll的高效事件模型kqueue。
  
http服務(wù)器:
與提供http服務(wù)相關(guān)的一些配置參數(shù)。例如:是否使用keepalive啊,是否使用gzip進行壓縮等。
sendfile on開啟高效文件傳輸模式。
  
keepalive_timeout 65 : 長連接超時時間,單位是秒,長連接請求大量小文件的時候,可以減少重建連接的開銷,如果設(shè)置時間過長,用戶又多,長時間保持連接會占用大量資源。
client_max_body_size 10m允許客戶端請求的最大單文件字節(jié)數(shù)。如果有上傳較大文件,請設(shè)置它的限制值
client_body_buffer_size 128k緩沖區(qū)代理緩沖用戶端請求的最大字節(jié)數(shù)
server_tokens off;
隱藏nginx的版本號
  
模塊http_proxy:這個模塊實現(xiàn)的是nginx作為反向代理服務(wù)器的功能,包括緩存功能
proxy_connect_timeoutnginx跟后端服務(wù)器連接超時時間(代理連接超時)
  
proxy_read_timeout定義從后端服務(wù)器讀取響應(yīng)的超時。此超時是指相鄰兩次讀操作之間的最長時間間隔,而不是整個響應(yīng)傳輸完成的最長時間。如果后端服務(wù)器在超時時間段內(nèi)沒有傳輸任何數(shù)據(jù),連接將被關(guān)閉。
  
proxy_send_timeout
定義向后端服務(wù)器傳輸請求的超時。此超時是指相鄰兩次寫操作之間的最長時間間隔,而不是整個請求傳輸完成的最長時間。如果后端服務(wù)器在超時時間段內(nèi)沒有接收到任何數(shù)據(jù),連接將被關(guān)閉。
  
proxy_buffer_size 4k設(shè)置緩沖區(qū)的大小為size。nginx從被代理的服務(wù)器讀取響應(yīng)時,使用該緩沖區(qū)保存響應(yīng)的開始部分。這部分通常包含著一個小小的響應(yīng)頭。該緩沖區(qū)大小默認等于proxy_buffers指令設(shè)置的一塊緩沖區(qū)的大小,但它也可以被設(shè)置得更小。
  
proxy_buffers 8 4k
語法: proxy_buffers the_numberis_size;
為每個連接設(shè)置緩沖區(qū)的數(shù)量為number,每塊緩沖區(qū)的大小為size。這些緩沖區(qū)用于保存從被代理的服務(wù)器讀取的響應(yīng)。每塊緩沖區(qū)默認等于一個內(nèi)存頁的大小。這個值是4K還是8K,取決于平臺。
附:查看Linux內(nèi)存頁大小
[root@www ~]# getconf PAGESIZE
4096
[root@www ~]# getconf PAGE_SIZE
4096
  
proxy_busy_buffers_size 64k高負荷下緩沖大?。J大小是proxy_buffers指令設(shè)置單塊緩沖大小的2倍)
  
proxy_max_temp_file_size當(dāng) proxy_buffers 放不下后端服務(wù)器的響應(yīng)內(nèi)容時,會將一部分保存到硬盤的臨時文件中,這個值用來設(shè)置最大臨時文件大小,默認1024M。
  
proxy_temp_file_write_size 64k當(dāng)緩存被代理的服務(wù)器響應(yīng)到臨時文件時,這個選項限制每次寫臨時文件的大小。
  
模塊http_gzip:
gzip on : 開啟gzip壓縮輸出,減少網(wǎng)絡(luò)傳輸。
  
gzip_min_length 1k : 設(shè)置允許壓縮的頁面最小字節(jié)數(shù),頁面字節(jié)數(shù)從header頭得content-length中進行獲取。建議設(shè)置成大于1k的字節(jié)數(shù),小于1k可能會越壓越大。
  
gzip_buffers 4 16k : 設(shè)置系統(tǒng)獲取幾個單位的緩存用于存儲gzip的壓縮結(jié)果數(shù)據(jù)流。416k代表以16k為單位,按照原始數(shù)據(jù)大小以16k為單位的4倍申請內(nèi)存。如果沒有設(shè)置,默認值是申請跟原始數(shù)據(jù)相同大小的內(nèi)存空間去存儲gzip壓縮結(jié)果
  
gzip_http_version 1.1 : 用于識別 http 協(xié)議的版本,早期的瀏覽器不支持 Gzip 壓縮,用戶就會看到亂碼,所以為了支持前期版本加上了這個選項,如果你用了 Nginx 的反向代理并期望也啟用 Gzip 壓縮的話,由于末端通信是 http/1.1,故請設(shè)置為 1.1。
  
gzip_comp_level 6 : gzip壓縮比,1壓縮比最小處理速度最快,9壓縮比最大但處理速度最慢(傳輸快但比較消耗cpu)
  
gzip_types :匹配mime類型進行壓縮,無論是否指定”text/html”類型總是會被壓縮的。
默認值: gzip_types text/html (默認不對js/css文件進行壓縮)# 壓縮類型,匹配MIME類型進行壓縮# 不能用通配符 text/*# (無論是否指定)text/html默認已經(jīng)壓縮 # 設(shè)置哪壓縮種文本文件可參考 conf/mime.types
  
gzip_proxied any : Nginx作為反向代理的時候啟用,根據(jù)某些請求和應(yīng)答來決定是否在對代理請求的應(yīng)答啟用gzip壓縮,是否壓縮取決于請求頭中的“Via”字段,指令中可以同時指定多個不同的參數(shù),意義如下:
off – 關(guān)閉所有的代理結(jié)果數(shù)據(jù)的壓縮expired – 啟用壓縮,如果header頭中包含 “Expires” 頭信息no-cache – 啟用壓縮,如果header頭中包含 “Cache-Control:no-cache” 頭信息no-store – 啟用壓縮,如果header頭中包含 “Cache-Control:no-store” 頭信息private – 啟用壓縮,如果header頭中包含 “Cache-Control:private” 頭信息no_last_modified – 啟用壓縮,如果header頭中不包含 “Last-Modified” 頭信息no_etag – 啟用壓縮 ,如果header頭中不包含 “ETag” 頭信息auth – 啟用壓縮 , 如果header頭中包含 “Authorization” 頭信息any – 無條件啟用壓縮
  
gzip_vary on :和http頭有關(guān)系,加個vary頭,給代理服務(wù)器用的,有的瀏覽器支持壓縮,有的不支持,所以避免浪費不支持的也壓縮,所以根據(jù)客戶端的HTTP頭來判斷,是否需要壓縮
  
模塊http_stream:這個模塊通過一個簡單的調(diào)度算法來實現(xiàn)客戶端IP到后端服務(wù)器的負載均衡,upstream后接負載均衡器的名字,后端realserver以 host:portoptions; 方式組織在 {} 中。如果后端被代理的只有一臺,也可以直接寫在 proxy_pass 。
  
Location:
root /var/www/html
定義服務(wù)器的默認網(wǎng)站根目錄位置。如果locationURL匹配的是子目錄或文件,root沒什么作用,一般放在server指令里面或/下。
  
index index.jsp index.html index.htm
定義路徑下默認訪問的文件名,一般跟著root放
  
proxy_pass http:/backend
請求轉(zhuǎn)向backend定義的服務(wù)器列表,即反向代理,對應(yīng)upstream負載均衡器。也可以proxy_pass http://ip:port。
  
proxy_redirect off;
指定是否修改被代理服務(wù)器返回的響應(yīng)頭中的location頭域跟refresh頭域數(shù)值
例如:
設(shè)置后端服務(wù)器“Location”響應(yīng)頭和“Refresh”響應(yīng)頭的替換文本。假設(shè)后端服務(wù)器返回的響應(yīng)頭是 “Location: http://localhost:8000/two/some/uri/”,那么指令
proxy_redirecthttp://localhost:8000/two/ http://frontend/one/;
將把字符串改寫為 “Location: http://frontend/one/some/uri/”。
proxy_set_headerHost $host;
允許重新定義或者添加發(fā)往后端服務(wù)器的請求頭。
Host的含義是表明請求的主機名,nginx反向代理服務(wù)器會向后端真實服務(wù)器發(fā)送請求,并且請求頭中的host字段重寫為proxy_pass指令設(shè)置的服務(wù)器。因為nginx作為反向代理使用,而如果后端真實的服務(wù)器設(shè)置有類似防盜鏈或者根據(jù)http請求頭中的host字段來進行路由或判斷功能的話,如果反向代理層的nginx不重寫請求頭中的host字段,將會導(dǎo)致請求失敗。
proxy_set_headerX-Forwarded-For $proxy_add_x_forwarded_for;
后端的Web服務(wù)器可以通過X-Forwarded-For獲取用戶真實IP
X_Forward_For字段表示該條http請求是有誰發(fā)起的?如果反向代理服務(wù)器不重寫該請求頭的話,那么后端真實服務(wù)器在處理時會認為所有的請求都來自反向代理服務(wù)器,如果后端有防攻擊策略的話,那么機器就被封掉了。因此,在配置用作反向代理的nginx中一般會增加兩條配置,修改http的請求頭:proxy_set_header Host $host;proxy_set_header X-Forward-For $remote_addr;
  
proxy_next_upstream error timeoutinvalid_header http_500 http_502 http_503 http_504;
增加故障轉(zhuǎn)移,如果后端的服務(wù)器返回502、504、執(zhí)行超時等錯誤,自動將請求轉(zhuǎn)發(fā)到upstream負載均衡池中的另一臺服務(wù)器,實現(xiàn)故障轉(zhuǎn)移。
  
proxy_set_header X-Real-IP $remote_addr;
web服務(wù)器端獲得用戶的真實ip但是,實際上要獲得用戶的真實ip,也可以通過X-Forward-For


 7、驗證:nginx反向代理的緩存功能、負載均衡及健康檢查

1)下面我們來測試一下緩存功能

如果在緩存時間之內(nèi)需要更新被緩存的靜態(tài)文件怎么辦呢,這時候就需要手動來清除緩存了。

ngx_cache_pure清除緩存模塊使用說明

用谷歌瀏覽器測試的時候,可以按F12調(diào)用開發(fā)工具,選擇Network選項,我們可以看到,Response Headers,在這里我們可以看到,我們請求的是否是緩存

從圖中我們可以看到,我們訪問的服務(wù)器是192.168.31.83,緩存命中。

也可以查看緩存目錄或nginx的訪問日志

 

清除緩存:

上述配置的proxy_cache_purge指令用于方便的清除緩存,但必須按照第三方的ngx_cache_purge 模塊才能使用

使用 ngx_cache_purge 模塊清除緩存(直接刪除緩存目錄下的文件也算一種辦法):

GET方式請求URL

即使用配置文件中的location ~ /purge(/.*)

瀏覽器訪問http://192.168.31.83/purge/your/may/path來清除緩存

緩存清除成功。

備注:
      1purgengx_cache_pure 模塊指令
      2your/may/path 是要清除的緩存文件URL路徑

2)若只有一臺客戶端要驗證負載均衡和健康檢查可以先關(guān)掉緩存功能和保持session會話

#proxy_buffering off;

#sticky

測試過程略

 

擴展知識1
nginx修改版本等信息
1、vi /usr/local/src/nginx-1.0.12/src/core/nginx.h   #編譯前編輯

1
2
3
4
#define nginx_version
#define NGINX_VERSION
#define NGINX_VER
#define NGINX_VAR

修改上面的信息,即可更改nginx顯示版本。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
2
、
vi/usr/local/src/nginx-1.0.12/src/http/ngx_http_special_response.c   #
編譯前編輯
static u_char ngx_http_error_full_tail[] =
static u_char ngx_http_error_tail[] =
修改上面的信息為你自己的。
3
、
vi/usr/local/src/nginx-1.0.12/src/http/ngx_http_header_filter_module.c   #
編譯前編輯
static char ngx_http_server_string[]=
修改上面的信息為你自己的。
4
、編譯完成之后,修改
/usr/local/nginx/conf
目錄下面
fastcgi.conf
fastcgi.conf.default
、
fastcgi_params
fastcgi_params.default
這四個文件里面的版本名稱
/usr/local/nginx/sbin/nginx -V  #
查看
nginx
版本號

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號