Nginx动静分离实现负载均衡
轉載自? ?Nginx動靜分離實現負載均衡
前期準備
使用Debian環境。安裝Nginx(默認安裝),一個web項目,安裝tomcat(默認安裝)等。
Nginx.conf配置
??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;??#最小1K40?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;?#默認主頁為?/index80?#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?}基本配置這個文件,就可以實現負載均衡了。但是里面的各種關系要了解就比較麻煩了。
?
實例講解
現在假使有一臺電腦192.168.8.203這臺電腦,上面部署了Tomcat,里面8080端口有J2EE的服務,通過瀏覽器可以正常瀏覽網頁。現在有一個問題tomcat是一個比較全面的web容器,對靜態網頁的處理,應該是比較費資源的,特別是每次都要從磁盤讀取靜態頁面,然后返回。這中間會消耗Tomcat的資源,可能會使那些動態頁面解析性能影響。秉承Linux哲學,一個軟件只做一件事的原則。Tomcat就應該只處理JSP動態頁面。這里就用到以前了解的Nginx來進行反向代理。第一步代理,實現動靜網頁分離。這個很簡單的。
?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。 這里根據需要可以改為?
?index?index.jsp?index.html?index.htm?index.php具體可參考其他文章。 關鍵的第40行,這個是正則匹配,網上也有很多介紹。這里匹配我項目中用到的所有靜態網頁后綴。第41行是代理地址。這里我代理到我的web應用中。expires 30d緩存為30天,這里的緩存是對應到前端頁面,用戶的Cache-Control字段,
?
第44行中那個正則是匹配無后綴的頁面。我項目中jsp頁面是無后綴的。這里可以根據需要進行修改。同樣代理到192.168.8.203:8080這里。到這里你可能會問,我艸,這有毛意思啊?當然不是這樣了。簡單的實現靜動分離,我們可以把第41行進行修改,改為
root???/var/lib/tomcat7/webapps/JieLiERP/WEB-INF表示不代理,直接從本地磁盤拿。通過查tomcat日志可以看到靜態頁面是沒有訪問到的。但這樣又有一個問題。這樣的靈活性不好,對下面要講到的內存緩存和集群部署來說都是不友好的,所以又有了下面的這種寫法。再寫一個server段。
?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?20483?openssl?req?-new?-x509?-days?7305?-key?ca.key?-out?ca.crt4?5?#生成Nginx服務器所需證書,并使用CA簽名6?openssl?genrsa?-des3?-out?client.key?10247?openssl?req?-new?-key?client.key?-out?client.csr8?openssl?x509?-req?-in?client.csr?-out?client.pem?-signkey?client.key?-CA?ca.crt?-CAkey?ca.key?-CAcreateserial?-days?36509? 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?}?
總結
以上是生活随笔為你收集整理的Nginx动静分离实现负载均衡的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 4k电脑配置清单(4k 电脑配置)
- 下一篇: obs直播电脑配置要求(obs直播电脑配