作者:無腦仔的小明 鏈接:http://www.cnblogs.com/wunaozai/

0.前期準備

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

1.一份Nginx.conf配置文件

# 定義Nginx運行的用戶 和 用戶組 如果對應服務器暴露在外面的話建議使用權限較小的用戶 防止被入侵
# user www www;
#Nginx進程數, 建議設置爲等於CPU總核心數
worker_processes 8;
#開啓全局錯誤日誌類型
error_log /var/log/nginx/error.log info;
#進程文件
pid /var/run/nginx.pid;
#一個Nginx進程打開的最多文件描述數目 建議與ulimit -n一致
#如果面對高併發時 注意修改該值 ulimit -n 還有部分系統參數 而並非這個單獨確定
worker_rlimit_nofile 65535;
events{
#使用epoll模型提高性能
use epoll;
#單個進程最大連接數
worker_connections 65535;
}
http{
#擴展名與文件類型映射表
include mime.types;
#默認類型
default_type application/octet-stream;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
#日誌
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
#gzip 壓縮傳輸
gzip on;
gzip_min_length 1k; #最小1K
gzip_buffers 16 64K;
gzip_http_version 1.1;
gzip_comp_level 6;
gzip_types text/plain application/x-javascript text/css application/xml application/javascript;
gzip_vary on;
#負載均衡組
#靜態服務器組
upstream static.zh-jieli.com {
server 127.0.0.1:808 weight=1;
}
#動態服務器組
upstream zh-jieli.com {
server 127.0.0.1:8080;
#server 192.168.8.203:8080;
}
#配置代理參數
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;
client_max_body_size 10m;
client_body_buffer_size 128k;
proxy_connect_timeout 65;
proxy_send_timeout 65;
proxy_read_timeout 65;
proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
#緩存配置
proxy_cache_key '$host:$server_port$request_uri';
proxy_temp_file_write_size 64k;
proxy_temp_path /dev/shm/JieLiERP/proxy_temp_path;
proxy_cache_path /dev/shm/JieLiERP/proxy_cache_path levels=1:2 keys_zone=cache_one:200m inactive=5d max_size=1g;
proxy_ignore_headers X-Accel-Expires Expires Cache-Control Set-Cookie;
server{
listen 80;
server_name erp.zh-jieli.com;
location / {
index index; #默認主頁爲 /index
#proxy_pass http://jieli;
}
location ~ .*\.(js|css|ico|png|jpg|eot|svg|ttf|woff) {
proxy_cache cache_one;
proxy_cache_valid 200 304 302 5d;
proxy_cache_valid any 5d;
proxy_cache_key '$host:$server_port$request_uri';
add_header X-Cache '$upstream_cache_status from $host';
proxy_pass http://static.zh-jieli.com;
#所有靜態文件直接讀取硬盤
# root /var/lib/tomcat7/webapps/JieLiERP/WEB-INF ;
expires 30d; #緩存30天
}
#其他頁面反向代理到tomcat容器
location ~ .*$ {
index index;
proxy_pass http://zh-jieli.com;
}
}
server{
listen 808;
server_name static;
location / {
}
location ~ .*\.(js|css|ico|png|jpg|eot|svg|ttf|woff) {
#所有靜態文件直接讀取硬盤
root /var/lib/tomcat7/webapps/JieLiERP/WEB-INF ;
expires 30d; #緩存30天
}
}
}


基本配置這個文件,就可以實現負載了。但是裏面的各種關係要了解就比較麻煩了。這篇博客,也不是教學篇,是記錄一下,方便以後自己看了。

2.基礎講解

現在假使有一臺電腦192.168.8.203這臺電腦,上面部署了Tomcat,裏面8080端口有J2EE的服務,通過瀏覽器可以正常瀏覽網頁。現在有一個問題tomcat是一個比較全面的web容器,對靜態網頁的處理,應該是比較費資源的,特別是每次都要從磁盤讀取靜態頁面,然後返回。

這中間會消耗Tomcat的資源,可能會使那些動態頁面解析性能影響。秉承Linux哲學,一個軟件只做一件事的原則。Tomcat就應該只處理JSP動態頁面。這裏就用到以前瞭解的Nginx來進行反向代理。第一步代理,實現動靜網頁分離。這個很簡單的。

worker_processes 8;
pid /var/run/nginx.pid;
worker_rlimit_nofile 65535;
events{
use epoll;
worker_connections 65535;
}
http{
include mime.types;
default_type application/octet-stream;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
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;
client_max_body_size 10m;
client_body_buffer_size 128k;
proxy_connect_timeout 65;
proxy_send_timeout 65;
proxy_read_timeout 65;
proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
server{
listen 80;
server_name xxx.com;
location / {
index index;
}
location ~ .*\.(js|css|ico|png|jpg|eot|svg|ttf|woff) {
proxy_pass http://192.168.8.203:8080;
expires 30d;
}
location ~ .*$ {
index index;
proxy_pass http://192.168.8.203:8080;
}
}
}


修改nginx的配置文件 /etc/nginx/nginx.conf 默認有個配置文件的。其實大部分都差不多,關鍵還是server段的設置。這裏我設置server段如上所示,其他段複製就可以了。

server段裏面的解釋如下:第35行爲監聽本機80端口。37-39行表示默認主頁,這裏的默認主頁我是index.jsp 對應到我項目中是一個index。 這裏根據需要可以改爲

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


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

Nginx+Tomcat 動靜分離實現負載均衡

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

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


表示不代理,直接從本地磁盤拿。通過查tomcat日誌可以看到靜態頁面是沒有訪問到的。但這樣又有一個問題。

這樣的靈活性不好,對下面要講到的內存緩存和集羣部署來說都是不友好的,所以又有了下面的這種寫法。再寫一個server段。

server{
listen 808;
server_name static;
location / {
}
location ~ .*\.(js|css|ico|png|jpg|eot|svg|ttf|woff) {
#所有靜態文件直接讀取硬盤
root /var/lib/tomcat7/webapps/JieLiERP/WEB-INF ;
expires 30d; #緩存30天
}
}


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

如果單純這樣的話,我們會發現頁面直接傳輸過於佔用帶寬。對應web的優化,這裏想到的是通過對頁面進行gzip壓縮,然後傳到用戶那裏,再解壓,這樣可以有效的減少帶寬。這裏就會用到Nginx 的gzip模塊了。默認的Nginx是集成有gzip模塊的。只需在http段增加下面配置即可。

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


給個首頁看看效果

Nginx+Tomcat 動靜分離實現負載均衡

不要在意請求數不一樣,那兩個請求是谷歌插件來的。不用覺得我在騙你。

作爲假使有很多人訪問的網站來說,緩存肯定是很重要的東西了。

一開始是想通過插件,讓Nginx和Redis進行合成,然後Nginx使用Redis來緩存的,但是發現配置起來很麻煩,還要自己下載插件,重新編譯Nginx,比較麻煩,所以這裏覺得用Nginx自帶的緩存也是不錯的選擇。

雖然效率比不上redis,但是有還是比沒有好。Nginx默認的緩存是磁盤文件系統的緩存,而不是像Redis那樣的內存級別的緩存。一開始我以爲Nginx就只有這樣。後來查了寫資料,才知道是我太天真了,對Linux不是很瞭解導致的。Linux的一切皆文件。

原來我們可以把文件緩存到內存對應的Linux文件系統中。我說的可能比較難以理解,請自行搜索/dev/shm 這個文件目錄。我們把文件緩存到這個文件目錄裏,其實就相當與內存的緩存了。只不過還是靠文件系統管理。所以比不上自定義格式的Redis那樣的內存緩存。

在http段進行基本配置

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


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


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





這些不緩存的話,就要加上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進程裏面,結構還在,如果不重啓的話,是會出現訪問不到的)

Nginx+Tomcat 動靜分離實現負載均衡

所以要記得重啓哦。下面是運行效果

第一次訪問

Nginx+Tomcat 動靜分離實現負載均衡

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

Nginx+Tomcat 動靜分離實現負載均衡

到這裏就可以看到效果了。我們查看一下/dev/shm這個裏面

Nginx+Tomcat 動靜分離實現負載均衡

到這裏已經快結束了。最後也是比較關鍵的一個技術點,就是集羣,集羣,集羣。這個就要用到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,然後分配對應的服務器。具體配置如下:

upstream dynamic{
ip_hash;
server 127.0.0.1:8080;
server 192.168.0.203:8080;
}


這樣就可以實現一個用戶對應一個服務器節點。這樣就不會有重複登錄的問題。另一種治本的辦法是,利用緩存系統進行session的統一存儲管理。具體的做法我還沒有試驗過,參考資料有相關的文章,可以瞭解一下。

Nginx增加SSL功能,同樣的Nginx默認是有SSL模塊功能,我們不用額外安裝,只需要簡單的配置就可以了。首先我們先來生成一些必要的證書。製作的過程還是比較簡單的。

#製作CA證書
openssl genrsa -des3 -out ca.key 2048
openssl req -new -x509 -days 7305 -key ca.key -out ca.crt
#生成Nginx服務器所需證書,並使用CA簽名
openssl genrsa -des3 -out client.key 1024
openssl req -new -key client.key -out client.csr
openssl x509 -req -in client.csr -out client.pem -signkey client.key -CA ca.crt -CAkey ca.key -CAcreateserial -days 3650
#取消證書密碼
openssl rsa -in client.key -out client.key.unsecure


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

server{
server_name localhost;
listen 443 ssl;
root html;
location / {
index index.html index.html;
}
ssl on;
ssl_certificate keys/client.pem;
ssl_certificate_key keys/client.key.unsecure;
}


重啓Nginx,我們就可以訪問Https網站了。 但是他喵的出現這個

Nginx+Tomcat 動靜分離實現負載均衡


這個是沒有什麼問題,具體原因是這個CA證書要得到認可。所以我們上面自己生成的https證書,只是自己生成的,如果要變成下面這種,就需要花錢購買了,剩下的這個自己上網解決。

(雖然自己生成的證書可以用,但是還是抵擋不了DNS欺騙,所以這種不安全證書,跟沒有其實是一樣的。不過據說這樣可以阻止運營商劫持。)

Nginx+Tomcat 動靜分離實現負載均衡


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

server{
server_name localhost;
listen 80;
rewrite ^(.*)$ https://$host$1 permanent;
}


好了,暫時到這裏,後續如果學到更多知識,再進行補充。

相關文章