面對網站伺服器端負載增大的問題,是“拿15萬¥買一台伺服器”來解決,還是靠“加三倍伺服器”來解決?還是用其它一些辦法?
對於一個訪問量日益增加的網站架構而言,從單機到集群、從集群到分散式,架構演化是必然的。
接手環境,分析瓶頸,擴展架構
筆者現在的環境在剛接手時算是單機LAMP環境。在單機LAMP環境時,由於訪問量逐漸變大,網站會經常出現打不開的情況,為了解決這個問題在LAMP前端臨時加了一台vanish來緩存一些靜態文件,從而減輕了web伺服器的負載。再到後來為了滿足業務訪問需求,將架構改為CDN+Nginx負載均衡(反向代理)+LNMP+代碼層緩存+MySQL主從,從而將網站整體負載性能提升15倍,且訪問速度也得到很大提升。
負載均衡為什麼要選擇使用Nginx呢?
普通負載均衡用LVS,文藝負載均衡用Nginx/F5/HAproxy,XX負載均衡用NLB
LVS:四層負載均衡的典型代表,目前已經被添加到linux發行版的內核。LVS用於較為成熟,因此不再做類述,在此推薦一篇不錯的LVS文章:《互聯網運營智慧》第六章負載均衡及伺服器集群(LVS)。
Nginx/F5/HAproxy:均為七層負載均衡,F5為商業設備,功能強大,但價格不菲,所以在此不做討論;HAproxy為重量級的七層負載均衡/反向代理程序,一般應用於大中型站點;而Nginx雖然屬於輕量級產品,但是功能毫不遜色與HAproxy,如可以對靜態文件可以實現緩存、可以通過URL、目錄結構、靜動分離對網站實現分流,還可以實現對後端伺服器狀態碼健康檢測、對網路依賴較小、對虛擬主機支持友好等等,這也是筆者選擇Nginx來做負載均衡的原因。
NLB:windows下的東東,性能、可操作性可想而知。在此也提醒一下各位同仁,針對HTTP類的應用千萬不要選擇使用windows,如同樣的業務放linux上只需兩台伺服器,而放windows上可能會需要三台甚至更多,運維/硬體採購成本也會增加,同時license也是一筆不小的費用。國內較大的一些web站點後端架構為windows的分別有京東商城、噹噹網、凡客誠品、麥包包。
使用Nginx構建負載均衡時需要注意的幾個問題
Session同步:由於筆者所維護的架構硬體預算受限,所以在整個架構中沒有共享存儲,針對於session處理,筆者使用ip_hash來解決後端伺服器session問題。另外,關於存儲session,推薦使用redis或memcached(感謝小衛、小灰狼 兩位兄弟的建議)。
網站代碼存儲:還是由於沒有共享存儲,所以筆者每台web伺服器本地均存放一份代碼,為了保證多台web伺服器的代碼數據一致性,使用rsync+inotify實現動態同步(具體實現方法會在後面的文章中介紹)。倘若硬體條件允許的情況下,推薦使用NFS來存儲;若考慮到NFS無法滿足性能需求,可以將NFS的硬碟換成SSD或者使用分散式文件系統來解決。
負載均衡模式選擇:在不受session困擾的情況下,負載均衡模式可以使用weight,因為ip_hash會有導致後端伺服器負載不均的情況出現。
開始部署Nginx和Keepalived
為了避免負載均衡出現單點故障,所以使用keepalived對Nginx負載均衡做了HA,也就是說當主負載均衡發生軟硬體故障時,負載均衡服務將有備用負載均衡伺服器自動接管服務,環境拓撲如下:
Vip:192.168.1.100
Nginx-proxy-master:192.168.1.101
Nginx-proxy-backup:192.168.1.102
安裝Nginx與Keepalived
在Nginx-proxy-master和Nginx-proxy-backup上分別安裝Nginx、Keepalived,兩台主機安裝步驟相同
安裝Nginx
#yum -y install pcre pcre-devel #useradd www -s /sbin/nologin #tar zxvf nginx-0.7.62.tar.gz #cd nginx-0.7.62 #./configure \ --prefix=/usr/local/nginx \ --user=www \ --group=www \ --with-http_stub_status_module \ --with-http_ssl_module #make && make install
安裝Keepalived
#tar zxvf keepalived-1.1.17.tar.gz #cd cd keepalived-1.1.17 #./configure --prefix=/usr/local/keepalived #make && make install #rm -rf /usr/local/keepalived/etc/keepalived/keepalived.conf #mkdir /etc/keepalived
配置Nginx
註:Nginx-proxy-master和Nginx-proxy-backup的Nginx配置相同
#more /usr/local/nginx/conf/nginx.conf user www www; worker_processes 4; error_log logs/error.log crit; pid logs/nginx.pid; worker_rlimit_nofile 51200; events { use epoll; worker_connections 51200; } http { include mime.types; default_type application/octet-stream; server_names_hash_bucket_size 256; client_header_buffer_size 256k; large_client_header_buffers 4 256k; keepalive_timeout 120; client_max_body_size 50m; client_body_buffer_size 256k; server_tokens off; gzip on; gzip_min_length 1k; gzip_buffers 4 1024k; gzip_http_version 1.1; gzip_comp_level 6; gzip_types text/plain application/x-javascript text/css application/xml; #gzip_vary on; proxy_hide_header Vary; proxy_connect_timeout 600; proxy_read_timeout 600; proxy_send_timeout 600; proxy_buffer_size 16k; proxy_buffers 4 64k; proxy_busy_buffers_size 128k; proxy_temp_file_write_size 128k; sendfile on; tcp_nodelay on; # add_header Cache-Control no-cache; upstream blog.luwenju.com { ip_hash; server 192.168.1.201:80; server 192.168.1.202:80; server 192.168.1.203:80; } server { listen 80; server_name blog.luwenju.com; location / { index index.php; proxy_pass http://blog.luwenju.com; proxy_set_header Host $host; proxy_next_upstream error timeout invalid_header http_500 http_502 http_504; proxy_set_header X-Forwarded-For $remote_addr; } location /NginxStatus { stub_status on; allow 192.168.1.0/24; } log_format blog.luwenju.com '$remote_addr - $remote_user [$time_local] $upstream_addr $upstream_status $request' '"$status" $body_bytes_sent "$http_referer"' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /usr/local/nginx/logs/blog.luwenju.com_access.log blog.luwenju.com; } }
說明:upstream為伺服器池。以本配置文件為例,upstream中共包含三台web伺服器,負載均衡方式為ip_hash。server為主機,用於為upstream內的三台web伺服器實現反向代理,從而到達負載均衡的目的。在本配置文件中只設置了一個主機(server),如果要實現虛擬主機,將一個server分別對應一個upstream即可。
另外,還有兩個關於日誌設置的問題:
負載均衡上是否需要開啟access_log:系統/程序剛上線時需要開啟,用於Nginx調試,後期運行穩定后建議將日誌列印關閉,因為對於訪問量較大的網站來說大量日誌寫入磁碟也會導致磁碟性能下降。
如何設置日誌格式:可能使用Nginx部署過負載均衡的朋友都知道,當把Nginx反向代理伺服器部署在web前端時,web伺服器的access_log就無法獲取用戶的真實ip地址了,針對這個問題的解決辦法會放到後面的文章中<Nginx日誌設置及日誌分析>
在Nginx-proxy-master伺服器上配置Keepalived
#more /etc/keepalived/keepalived.conf ! Configuration File for keepalived global_defs { router_id nginx-proxy-ha } vrrp_script check_nginx { script "/etc/keepalived/check_nginx.sh" interval 2 weight 2 } vrrp_instance VI_1 { state MASTER interface eth0 virtual_router_id 51 priority 200 advert_int 1 authentication { auth_type PASS auth_pass 1234 } track_interface { eth0 } track_script { check_nginx } virtual_ipaddress { 192.168.1.100 } }
有關check_nginx.sh的說明:如果Nginx-proxy-master上的nginx進程由於某種原因停止了,但是keepalived進程還正常運行著,這時候Nginx-proxy-backup上的keepalived會認為Nginx-proxy-master是正常的(因為master檢測到backup的keepalived進程還存在),所以在這種情況下當Nginx進程死亡的時候Keepalived也不會發生故障轉移。那麼這個腳本的作用就是讓keepalived實時監控Nginx進程,當發現Nginx進程不存在的時候自動將本機的keepalived進程殺死,從而實現故障轉移,腳本內容如下(註:Nginx-proxy-master和Nginx-proxy-backup上此腳本內容均一樣)
#more /etc/keepalived/check_nginx.sh #!/bin/bash if [ "$(ps -ef | grep "nginx: master process"| grep -v grep )" == "" ] then killall -9 keepalived fi
在Nginx-proxy-backup伺服器上配置Keepalived
註:Nginx-proxy-backup上keepalived的配置與Nnginx-proxy-master只有兩處不同,state為BACKUP、優先順序低於master
#more /etc/keepalived/keepalived.conf ! Configuration File for keepalived global_defs { router_id nginx-proxy-ha } vrrp_script check_nginx { script "/etc/keepalived/check_nginx.sh" interval 2 weight 2 } vrrp_instance VI_1 { state BACKUP interface eth0 virtual_router_id 51 priority 180 advert_int 1 authentication { auth_type PASS auth_pass 1234 } track_interface { eth0 } track_script { check_nginx } virtual_ipaddress { 192.168.1.100 } }
啟動Nginx和Keepalived
#/usr/local/nginx/sbin/nginx #/usr/local/keepalived/sbin/keepalived –D #echo “/usr/local/nginx/sbin/nginx”>>/etc/rc.local #echo “/usr/local/keepalived/sbin/keepalived –D” >>/etc/rc.local
測試負載均衡是否正常工作
1、打開瀏覽器,分別訪問Nginx-proxy-master、Nginx-proxy-backup、vip,如都能訪問到後端web內容,則說明如上所有配置正確
2、殺死Nginx-proxy-master伺服器上的Nginx進程,觀察keepalived進程是否自動消失、觀察vip是否已經轉移到了Nginx-proxy-backup伺服器上,如殺死Nginx進程后,keepalived進程也隨之消失,且vip已經轉移到Nginx-proxy-backup伺服器,則說明Nginx-proxy-master可正常實現故障轉移
3、依次啟動 Nginx-proxy-master的Nginx、Keepalived(必須先啟動Nginx后啟動Keepalived。如果先啟動Keepalived,Keepalived檢測到Nginx沒有啟動還是會執行殺死自己進程的腳本),然後將Nginx-proxy-backup的Nginx進程殺死,看vip是否會自動轉移到Nginx-proxy-master伺服器上,如殺死Nginx進程后,keepalived進程也隨之消失,且vip已經轉移到Nginx-proxy-master伺服器,則說明Nginx-proxy-backup可正常實現故障轉移
至此,Nginx負載均衡配置完畢。另外,Nginx非常穩定,筆者的Nginx負載均衡運行在HP DL380伺服器上(一顆至強E5620CPU,16G內存,萬轉SAS硬碟),運行四個月以來,從未出現過任何問題。在負載性能上,2000併發情況下load average:僅為0.02, 0.01, 0.00,CPU使用率僅為3%,內存使用為1G(算上linux系統本身使用,系統為64bit)。
作者簡介:陸文舉(微博),85后,一個整天跟機器打交道的山東人。
[火星人 ] 使用Nginx、Keepalived構建文藝負載均衡已經有810次圍觀