面對網站服務器端負載增大的問題,是「拿15萬¥買一臺服務器」來解決,仍是靠「加三倍服務器」來解決?仍是用其它一些辦法?javascript
對於一個訪問量日益增長的網站架構而言,從單機到集羣、從集羣到分佈式,架構演化是必然的。php
接手環境,分析瓶頸,擴展架構css
筆者如今的環境在剛接手時算是單機LAMP環境。在單機LAMP環境時,因爲訪問量逐漸變大,網站會常常出現打不開的狀況,爲了解決這個問題在LAMP前端臨時加了一臺vanish來緩存一些靜態文件,從而減輕了web服務器的負載。再到後來爲了知足業務訪問需求,將架構改成CDN+Nginx負載均衡(反向代理)+LNMP+代碼層緩存+MySQL主從,從而將網站總體負載性能提高15倍,且訪問速度也獲得很大提高。前端
負載均衡爲何要選擇使用Nginx呢?java
普通負載均衡用LVS,文藝負載均衡用Nginx/F5/HAproxy,XX負載均衡用NLBnode
LVS:四層負載均衡的典型表明,目前已經被添加到linux發行版的內核。LVS用於較爲成熟,所以再也不作類述,在此推薦一篇不錯的LVS文章:《互聯網運營智慧》第六章負載均衡及服務器集羣(LVS)。linux
Nginx/F5/HAproxy:均爲七層負載均衡,F5爲商業設備,功能強大,但價格不菲,因此在此不作討論;HAproxy爲重量級的七層負載均衡/反向代理程序,通常應用於大中型站點;而Nginx雖然屬於輕量級產品,可是功能絕不遜色與HAproxy,如能夠對靜態文件能夠實現緩存、能夠經過URL、目錄結構、靜動分離對網站實現分流,還能夠實現對後端服務器狀態碼健康檢測、對網絡依賴較小、對虛擬主機支持友好等等,這也是筆者選擇Nginx來作負載均衡的緣由。nginx
NLB:windows下的東東,性能、可操做性可想而知。在此也提醒一下各位同仁,針對HTTP類的應用千萬不要選擇使用windows,如一樣的業務放linux上只需兩臺服務器,而放windows上可能會須要三臺甚至更多,運維/硬件採購成本也會增長,同時license也是一筆不小的費用。國內較大的一些web站點後端架構爲windows的分別有京東商城、噹噹網、凡客誠品、麥包包。web
使用Nginx構建負載均衡時須要注意的幾個問題redis
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
#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-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; } }
另外,還有兩個關於日誌設置的問題:
負載均衡上是否須要開啓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 } }
#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的配置與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 } }
#/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
一、打開瀏覽器,分別訪問Nginx-proxy-master、Nginx-proxy-backup、vip,如都能訪問到後端web內容,則說明如上全部配置正確
二、殺死Nginx-proxy-master服務器上的Nginx進程,觀察keepalived進程是否自動消失、觀察vip是否已經轉移到了Nginx-proxy-backup服務器上,如殺死Nginx進程後,keepalived進程也隨之消失,且vip已經轉移到Nginx-proxy-backup服務器,則說明Nginx-proxy-master可正常實現故障轉移
三、依次啓動 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)。