Nginx動靜分離負載均衡

前期準備javascript

使用Debian環境。安裝Nginx(默認安裝),一個web項目,安裝tomcat(默認安裝)等。php

Nginx.conf配置css

1 # 定義Nginx運行的用戶 和 用戶組 若是對應服務器暴露在外面的話建議使用權限較小的用戶 防止被入侵
 2 # user www www;
 3 
 4 #Nginx進程數, 建議設置爲等於CPU總核心數
 5 worker_processes 8;
 6 
 7 #開啓全局錯誤日誌類型
 8 error_log /var/log/nginx/error.log info;
 9 
10 #進程文件
11 pid /var/run/nginx.pid;
12 
13 #一個Nginx進程打開的最多文件描述數目 建議與ulimit -n一致
14 #若是面對高併發時 注意修改該值 ulimit -n 還有部分系統參數 而並不是這個單獨肯定
15 worker_rlimit_nofile 65535;
16 
17 events{
18 #使用epoll模型提升性能
19 use epoll;
20 #單個進程最大鏈接數
21 worker_connections 65535;
22 }
23 
24 http{
25 #擴展名與文件類型映射表
26 include mime.types;
27 #默認類型
28 default_type application/octet-stream;
29 sendfile on;
30 tcp_nopush on;
31 tcp_nodelay on;
32 keepalive_timeout 65;
33 types_hash_max_size 2048;
34 #日誌
35 access_log /var/log/nginx/access.log;
36 error_log /var/log/nginx/error.log;
37 #gzip 壓縮傳輸
38 gzip on;
39 gzip_min_length 1k;  #最小1K
40 gzip_buffers 16 64K;
41 gzip_http_version 1.1;
42 gzip_comp_level 6;
43 gzip_types text/plain application/x-javascript text/css application/xml application/javascript;
44 gzip_vary on;
45 #負載均衡組
46 #靜態服務器組
47 upstream static.zh-jieli.com {
48 server 127.0.0.1:808 weight=1;
49 }
50 #動態服務器組
51 upstream zh-jieli.com {
52 server 127.0.0.1:8080;
53 #server 192.168.8.203:8080;
54 }
55 #配置代理參數
56 proxy_redirect off;
57 proxy_set_header Host $host;
58 proxy_set_header X-Real-IP $remote_addr;
59 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
60 client_max_body_size 10m;
61 client_body_buffer_size 128k;
62 proxy_connect_timeout 65;
63 proxy_send_timeout 65;
64 proxy_read_timeout 65;
65 proxy_buffer_size 4k;
66 proxy_buffers 4 32k;
67 proxy_busy_buffers_size 64k;
68 #緩存配置
69 proxy_cache_key '$host:$server_port$request_uri';
70 proxy_temp_file_write_size 64k;
71 proxy_temp_path /dev/shm/JieLiERP/proxy_temp_path;
72 proxy_cache_path /dev/shm/JieLiERP/proxy_cache_path levels=1:2 keys_zone=cache_one:200m inactive=5d max_size=1g;
73 proxy_ignore_headers X-Accel-Expires Expires Cache-Control Set-Cookie;
74 
75 server{
76 listen 80;
77 server_name erp.zh-jieli.com;
78 location / {
79 index index; #默認主頁爲 /index
80 #proxy_pass http://jieli;
81 }
82 location ~ .*\.(js|css|ico|png|jpg|eot|svg|ttf|woff) {
83 proxy_cache cache_one;
84 proxy_cache_valid 200 304 302 5d;
85 proxy_cache_valid any 5d;
86 proxy_cache_key '$host:$server_port$request_uri';
87 add_header X-Cache '$upstream_cache_status from $host';
88 proxy_pass http://static.zh-jieli.com;
89 #全部靜態文件直接讀取硬盤
90 #   root /var/lib/tomcat7/webapps/JieLiERP/WEB-INF ;
91 expires 30d; #緩存30天
92 }
93 #其餘頁面反向代理到tomcat容器
94 location ~ .*$ {
95 index index;
96 proxy_pass http://zh-jieli.com;
97 }
98 }
99 server{
100 listen 808;
101 server_name static;
102 location / {
103 
104 }
105 location ~ .*\.(js|css|ico|png|jpg|eot|svg|ttf|woff) {
106 #全部靜態文件直接讀取硬盤
107 root /var/lib/tomcat7/webapps/JieLiERP/WEB-INF ;
108 expires 30d; #緩存30天
109 }
110 }
111 }

基本配置這個文件,就能夠實現負載均衡了。可是裏面的各類關係要了解就比較麻煩了。html

 

實例講解前端

如今假使有一臺電腦192.168.8.203這臺電腦,上面部署了Tomcat,裏面8080端口有J2EE的服務,經過瀏覽器能夠正常瀏覽網頁。如今有一個問題tomcat是一個比較全面的web容器,對靜態網頁的處理,應該是比較費資源的,特別是每次都要從磁盤讀取靜態頁面,而後返回。這中間會消耗Tomcat的資源,可能會使那些動態頁面解析性能影響。秉承Linux哲學,一個軟件只作一件事的原則。Tomcat就應該只處理JSP動態頁面。這裏就用到之前瞭解的Nginx來進行反向代理。第一步代理,實現動靜網頁分離。這個很簡單的java

1      worker_processes 8;
2 
3 pid /var/run/nginx.pid;
4 
5 worker_rlimit_nofile 65535;
6 
7 events{
8 use epoll;
9 worker_connections 65535;
10 }
11 
12 http{
13 include mime.types;
14 default_type application/octet-stream;
15 sendfile on;
16 tcp_nopush on;
17 tcp_nodelay on;
18 keepalive_timeout 65;
19 types_hash_max_size 2048;
20 
21 proxy_redirect off;
22 proxy_set_header Host $host;
23 proxy_set_header X-Real-IP $remote_addr;
24 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
25 client_max_body_size 10m;
26 client_body_buffer_size 128k;
27 proxy_connect_timeout 65;
28 proxy_send_timeout 65;
29 proxy_read_timeout 65;
30 proxy_buffer_size 4k;
31 proxy_buffers 4 32k;
32 proxy_busy_buffers_size 64k;
33 
34 server{
35 listen 80;
36 server_name xxx.com;
37 location / {
38 index index; 
39 }
40 location ~ .*\.(js|css|ico|png|jpg|eot|svg|ttf|woff) {
41 proxy_pass http://192.168.8.203:8080;
42 expires 30d; 
43 }
44 location ~ .*$ {
45 index index;
46 proxy_pass http://192.168.8.203:8080;
47 }
48 }
49 }

修改nginx的配置文件 /etc/nginx/nginx.conf 默認有個配置文件的。其實大部分都差很少,關鍵仍是server段的設置。這裏我設置server段如上所示,其餘段複製就能夠了。server段裏面的解釋以下:第35行爲監聽本機80端口。37-39行表示默認主頁,這裏的默認主頁我是index.jsp 對應到我項目中是一個index。 這裏根據須要能夠改成 node

 

index index.jsp index.html index.htm index.php

 

具體可參考其餘文章。 關鍵的第40行,這個是正則匹配,網上也有不少介紹。這裏匹配我項目中用到的全部靜態網頁後綴。第41行是代理地址。這裏我代理到個人web應用中。expires 30d緩存爲30天,這裏的緩存是對應到前端頁面,用戶的Cache-Control字段,nginx

第44行中那個正則是匹配無後綴的頁面。我項目中jsp頁面是無後綴的。這裏能夠根據須要進行修改。一樣代理到192.168.8.203:8080這裏。到這裏你可能會問,我艹,這有毛意思啊?固然不是這樣了。簡單的實現靜動分離,咱們能夠把第41行進行修改,改成web

root   /var/lib/tomcat7/webapps/JieLiERP/WEB-INF

 

表示不代理,直接從本地磁盤拿。經過查tomcat日誌能夠看到靜態頁面是沒有訪問到的。但這樣又有一個問題。這樣的靈活性很差,對下面要講到的內存緩存和集羣部署來講都是不友好的,因此又有了下面的這種寫法。再寫一個server段。redis

1 server{
2 listen 808;
3 server_name static;
4 location / {
5 
6 }
7 location ~ .*\.(js|css|ico|png|jpg|eot|svg|ttf|woff) {
8 #全部靜態文件直接讀取硬盤
9 root /var/lib/tomcat7/webapps/JieLiERP/WEB-INF ;
10 expires 30d; #緩存30天
11 }
12 }

此次監聽808端口,而後上上面的代碼41行就能夠修改成 proxy_pass http://192.168.8.203:808了,到這裏就實現了動靜分離了。若是多臺服務器,就修改對應的ip就能夠了。若是發現鏈接不上的,要檢查一下防火牆,權限等外部問題,這個配置是這樣的。

若是單純這樣的話,咱們會發現頁面直接傳輸過於佔用帶寬。對應web的優化,這裏想到的是經過對頁面進行gzip壓縮,而後傳到用戶那裏,再解壓,這樣能夠有效的減小帶寬。這裏就會用到Nginx 的gzip模塊了。默認的Nginx是集成有gzip模塊的。只需在http段增長下面配置便可。

1 gzip on;
2 gzip_min_length 1k;  #最小1K
3 gzip_buffers 16 64K;
4 gzip_http_version 1.1;
5 gzip_comp_level 6;
6 gzip_types text/plain application/x-javascript text/css application/xml application/javascript;
7 gzip_vary on;

 

給個首頁看看效果

不要在乎請求數不同,那兩個請求是谷歌插件來的。不用以爲我在騙你。

做爲假使有不少人訪問的網站來講,緩存確定是很重要的東西了。一開始是想經過插件,讓Nginx和Redis進行合成,而後Nginx使用Redis來緩存的,可是發現配置起來很麻煩,還要本身下載插件,從新編譯Nginx,比較麻煩,因此這裏以爲用Nginx自帶的緩存也是不錯的選擇。雖然效率比不上redis,可是有仍是比沒有好。Nginx默認的緩存是磁盤文件系統的緩存,而不是像Redis那樣的內存級別的緩存。一開始我覺得Nginx就只有這樣。後來查了寫資料,才知道是我太天真了,對Linux不是很瞭解致使的。Linux的一切皆文件。原來咱們能夠把文件緩存到內存對應的Linux文件系統中。我說的可能比較難以理解,請自行搜索/dev/shm 這個文件目錄。咱們把文件緩存到這個文件目錄裏,其實就至關與內存的緩存了。只不過仍是靠文件系統管理。因此比不上自定義格式的Redis那樣的內存緩存。

在http段進行基本配置

1 #緩存配置
2 proxy_cache_key '$host:$server_port$request_uri';
3 proxy_temp_file_write_size 64k;
4 proxy_temp_path /dev/shm/JieLiERP/proxy_temp_path;
5 proxy_cache_path /dev/shm/JieLiERP/proxy_cache_path levels=1:2 keys_zone=cache_one:200m inactive=5d max_size=1g;
6 proxy_ignore_headers X-Accel-Expires Expires Cache-Control Set-Cookie

  

 

1 location ~ .*\.(js|css|ico|png|jpg|eot|svg|ttf|woff) {
2 proxy_cache cache_one;
3 proxy_cache_valid 200 304 302 5d;
4 proxy_cache_valid any 5d;
5 proxy_cache_key '$host:$server_port$request_uri';
6 add_header X-Cache '$upstream_cache_status from $host';
7 proxy_pass http://192.168.8.203:808;
8 
9 expires 30d; #緩存30天
10 }

通過這兩個的配置就基本能實現了,這裏說幾個注意項,也是困擾我好久的問題。上面第一段代碼第6行,proxy_ignore_headers 若是web項目中的html的head頭裏面指定

1 <meta http-equiv="pragma" content="no-cache">
2 <meta http-equiv="cache-control" content="no-cache">
3 <meta http-equiv="expires" content="0">

這些不緩存的話,就要加上proxy_ignore_headers的配置項了。還有一點就是/dev/shm下面的文件系統權限默認只給root用戶,因此要chmod 777 -R /dev/shm 這樣不是很安全的作法,若是實際上線能夠給定某個用戶組,關於用戶組的設置是配置的第一行

 

user www www;

 

上面第二段代碼的第6行是增長一個header字段方便查看是否擊中緩存。

咱們rm -rf /dev/shm/JieLiERP/proxy_* 下面的全部文件(注意這裏若是是進行屢次測試的話要nginx -s reload 從新讀取配置或重啓服務,由於你rm -rf只是刪除了緩存文件,可是緩存的結構信息還在nginx進程裏面,結構還在,若是不重啓的話,是會出現訪問不到的)

因此要記得重啓哦。下面是運行效果

第一次訪問

第二次訪問,在瀏覽器中Ctrl+Shift+R 強制刷新

到這裏就能夠看到效果了。咱們查看一下/dev/shm這個裏面

到這裏已經快結束了。最後也是比較關鍵的一個技術點,就是集羣,集羣,集羣。這個就要用到upstream了,看到最開頭的配置文件了嗎,就是那個

負載均衡組
#靜態服務器組
upstream static {
server 127.0.0.1:808 weight=1;
server 192.168.8.203:808 weight=1;
}


#動態服務器組
upstream dynamic {
server 127.0.0.1:8080;
#server 192.168.8.203:8080;
}

上面那個就是集羣組了。upstream是關鍵字,static 和 dynamic是兩個服務器集羣組的名稱。以第一個爲例,server 127.0.0.1:808 是服務器地址,後面的weight=1 是權重。有多個就寫多個。親測試過,集羣中的一個壞了,不影響系統運行。至於更多的輪詢規則,能夠參考網上更多的資料。這裏很少說。至於怎麼使用呢? proxy_pass http://192.168.8.203:808 改成 proxy_pass http://static; 這樣便可實現均衡。

到這裏就結束了。把上面各個部分根據本身需求配置起來就能夠實現單機房負載均衡了。 上面這種作法有一個缺點就是在前面的那一臺nginx若是當機,後面因此機器就失去了被訪問的能力了,因此須要在前面實現多個nginx多機房的負載。關於這個就是另一個話題了。目前尚未研究。之後有機會再說了。

上面動態服務器組若是是那種須要保存用戶狀態的話,會有問題,就是session問題,好比我在server1進行登陸後,下一次動態服務器組進行輪詢後可能分配到server2,就會形成要從新登陸。治標的辦法是,配置輪詢規則,根據用戶請求的IP進行Hash,而後分配對應的服務器。具體配置以下:

1 upstream dynamic{
2 ip_hash;
3 server 127.0.0.1:8080;
4 server 192.168.0.203:8080;
5 }

 

這樣就能夠實現一個用戶對應一個服務器節點。這樣就不會有重複登陸的問題。

另外一種治本的辦法是,利用緩存系統進行session的統一存儲管理。具體的作法我尚未試驗過,參考資料有相關的文章,能夠了解一下。

Nginx增長SSL功能,一樣的Nginx默認是有SSL模塊功能,咱們不用額外安裝,只須要簡單的配置就能夠了。首先咱們先來生成一些必要的證書。製做的過程仍是比較簡單的

1 #製做CA證書
2 openssl genrsa -des3 -out ca.key 2048
3 openssl req -new -x509 -days 7305 -key ca.key -out ca.crt
4 
5 #生成Nginx服務器所需證書,並使用CA簽名
6 openssl genrsa -des3 -out client.key 1024
7 openssl req -new -key client.key -out client.csr
8 openssl x509 -req -in client.csr -out client.pem -signkey client.key -CA ca.crt -CAkey ca.key -CAcreateserial -days 3650
9 
10 #取消證書密碼
11 openssl rsa -in client.key -out client.key.unsecure

 下面就是配置Nginx了,咱們能夠把須要用到的client.pem, client.pem, client.key,unsecure這三個文件放到Nginx的一個目錄下,剩下的Nginx配置以下:

 

1 server{
2 server_name localhost;
3 listen 443 ssl;
4 root html;
5 location / {
6 index index.html index.html;
7 }
8 ssl on;
9 ssl_certificate keys/client.pem;
10 ssl_certificate_key keys/client.key.unsecure;
11 }

重啓Nginx,咱們就能夠訪問Https網站了。 可是他喵的出現這個

 

這個是沒有什麼問題,具體緣由是這個CA證書要獲得承認。因此咱們上面本身生成的https證書,只是本身生成的,若是要變成下面這種,就須要花錢購買了,剩下的這個本身上網解決。(雖然本身生成的證書能夠用,可是仍是抵擋不了DNS欺騙,因此這種不安全證書,跟沒有實際上是同樣的。不過聽說這樣能夠阻止運營商劫持。)

增長一個,就是在咱們輸入http鏈接時自動跳轉到安全的https鏈接。這個仍是比較實用的。方法仍是有多種的,具體能夠看參考資料裏面的博客。我是使用下面這一種,我以爲是比較簡單的,代碼改動比較少的。就是對80端口進行代理轉發。

1 server{
2 server_name localhost;
3 listen 80;
4 rewrite ^(.*)$ https://$host$1 permanent;
5 }
相關文章
相關標籤/搜索