額。博客名字有點長。。
。
前言
最終到這篇文章了,心情是有點激動的。
由於這篇文章會集中曾經博客講到的全部Nginx功能點。包含主要的負載均衡,還有動靜分離技術再加上這篇文章的重點。通過Keepalived實現的HA(High Available)。為什么要實現高可用呢?曾經在搭建的時候僅僅用了一台Nginxserver,這種話假設Nginxserver宕機了,那么整個站點就會掛掉。所以要實現Nginx的高可用,一台掛掉還會有還有一台頂上去。從而保證站點能夠持續的提供服務。
關於負載均衡和動靜分離在前面博客中都有相關的介紹,這篇博客就不在具體提了,僅僅會在配置文件里體現。不多說了,以下開始搭建。
拓撲環境
以下表格是這次測試須要的拓撲環境,幾台server。每台server上安裝什么,都有介紹。
server名稱 | 系統版本號 | 預裝軟件 | IP地址/VIP |
---|---|---|---|
Nginx主server | CentOS 7 最小安裝 | Nginx +Keepalived | 192.168.22.227/192.168.22.231 |
Nginx從server | CentOS 7 最小安裝 | Nginx +Keepalived | 192.168.22.228/192.168.22.231 |
WebserverA | CentOS 7 最小安裝 | tomcat+jdk | 192.168.22.229 |
WebserverB | CentOS 7 最小安裝 | tomcat+jdk | 192.168.22.230 |
前置條件
這是一個系列博客,假設有困難能夠查看之前的博客。
server配置VIP:http://blog.csdn.net/u010028869/article/details/50574907
Keepalived安裝見:http://blog.csdn.net/u010028869/article/details/50527817
Keepalived原理解析:http://blog.csdn.net/u010028869/article/details/50596805
Nginx動靜分離、負載均衡:http://blog.csdn.net/u010028869/article/details/50522033
原理圖

開始搭建
一、配置VIP
關於VIP(即虛擬IP)的作用,上篇博客《Keepalived原理篇》已經介紹過了。
227和228server須要配置同樣的VIP。虛擬IP在某時刻僅僅能屬於某一個節點。還有一個節點作為備用節點存在。當主節點不可用時。備用節點接管虛擬IP。成為主節點(即虛擬IP漂移至從節點),提供正常服務。
這個VIP就像個牆頭草,兩頭跑,誰是主他就為誰服務。
配置VIP的博客。上面也有鏈接哦。
二、安裝軟件
依照上面的表格,在對應server上安裝軟件。安裝過程不再多說了,有問題能夠點擊上面的博客鏈接哦。
三、配置Nginx
227server上的Nginx配置:
user nobody;
worker_processes 2;
events{
worker_connections 1024;
}
http{
#設置默認類型為二進制流
default_type application/octet-stream;
server_names_hash_bucket_size 128;
#指定來自client請求頭的headerbuffer大小。設置為32KB
client_header_buffer_size 32k;
#指定client請求中較大的消息頭的緩存最大數量和大小,這里是4個32KB
large_client_header_buffers 4 32k;
#上傳文件大小
client_max_body_size 356m;
#nginx的HttpLog模塊指定,指定nginx日志的輸出格式,輸出格式為access
log_format access '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
#access日志存在未知
access_log /usr/local/nginx/logs/access.log access;
#開啟高效模式文件傳輸模式,將tcp_nopush和tcp_nodelay兩個指另設置為on,用於防止網絡堵塞。 sendfile on; tcp_nopush on; tcp_nodelay on; #設置client連接保持活動的超時時間 keepalive_timeout 65; server_tokens off; #client請求主體讀取緩存 client_body_buffer_size 512k; proxy_connect_timeout 5; proxy_send_timeout 60; proxy_read_timeout 5; proxy_buffer_size 16k; proxy_buffers 4 64k; proxy_busy_buffers_size 128k; proxy_temp_file_write_size 128k; #fastcgi_connect_timeout 300; #fastcgi_send_timeout 300; #fastcgi_read_timeout 300; #fastcgi_buffer_timeout 300; #fastcgi_buffers 4 64k; #fastcgi_busy_buffers_size 128k; #fastcgi_temp_file_write_size 128k; #開啟gzip gzip on; #同意壓縮的最小字節數 gzip_min_length 1k; #4個單位為16k的內存作為壓縮結果流緩存 gzip_buffers 4 16k; #設置識別HTTP協議版本號,默認是1.1 gzip_http_version 1.1; #gzip壓縮比,可在1~9中設置,1壓縮比最小,速度最快。9壓縮比最大。速度最慢,消耗CPU gzip_comp_level 2; #壓縮的類型 gzip_types text/plain application/x-javascript text/css application/xml; #讓前端的緩存server混村經過的gzip壓縮的頁面 gzip_vary on; upstream mycluster{ server 192.168.22.229:8080 weight=1; server 192.168.22.230:8080 weight=1; } server{ listen 8088; server_name 192.168.22.227; charset utf-8; #設置編碼為utf-8 #root html; #location / { # root html; # index index.html index.htm; #} #location ~ .*\.(jsp|do|action)$ location / { proxy_next_upstream http_502 http_504 error timeout invalid_header; proxy_pass http://mycluster; # 真實的clientIP proxy_set_header X-Real-IP $remote_addr; # 請求頭中Host信息 proxy_set_header Host $host; # 代理路由信息。此處取IP有安全隱患 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 真實的用戶訪問協議 proxy_set_header X-Forwarded-Proto $scheme; } #靜態文件交給nginx處理 location ~ .*\.(htm|html|gif|jpg|jpeg|png|bmp|swf|ioc|rar|zip|txt|flv|mid|doc|ppt|pdf|xls|mp3|wma)$ { root /usr/local/webapps; expires 30d; } #靜態文件交給nginx處理 location ~ .*\.(js|css)?
$ { root /usr/local/webapps; expires 1h; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } } }
228server上的Nginx配置:
user nobody;
worker_processes 2;
events{
worker_connections 1024;
}
http{
#設置默認類型為二進制流
default_type application/octet-stream;
server_names_hash_bucket_size 128;
#指定來自client請求頭的headerbuffer大小,設置為32KB
client_header_buffer_size 32k;
#指定client請求中較大的消息頭的緩存最大數量和大小,這里是4個32KB
large_client_header_buffers 4 32k;
#上傳文件大小
client_max_body_size 356m;
#nginx的HttpLog模塊指定。指定nginx日志的輸出格式,輸出格式為access
log_format access '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
#access日志存在未知
access_log /usr/local/nginx/logs/access.log access;
#開啟高效模式文件傳輸模式。將tcp_nopush和tcp_nodelay兩個指另設置為on。用於防止網絡堵塞。
sendfile on;
tcp_nopush on;
tcp_nodelay on;
#設置client連接保持活動的超時時間
keepalive_timeout 65;
server_tokens off;
#client請求主體讀取緩存
client_body_buffer_size 512k;
proxy_connect_timeout 5;
proxy_send_timeout 60;
proxy_read_timeout 5;
proxy_buffer_size 16k;
proxy_buffers 4 64k;
proxy_busy_buffers_size 128k;
proxy_temp_file_write_size 128k;
#fastcgi_connect_timeout 300;
#fastcgi_send_timeout 300;
#fastcgi_read_timeout 300;
#fastcgi_buffer_timeout 300;
#fastcgi_buffers 4 64k;
#fastcgi_busy_buffers_size 128k;
#fastcgi_temp_file_write_size 128k;
#開啟gzip
gzip on;
#同意壓縮的最小字節數
gzip_min_length 1k;
#4個單位為16k的內存作為壓縮結果流緩存
gzip_buffers 4 16k;
#設置識別HTTP協議版本號。默認是1.1
gzip_http_version 1.1;
#gzip壓縮比,可在1~9中設置。1壓縮比最小。速度最快。9壓縮比最大,速度最慢,消耗CPU
gzip_comp_level 2;
#壓縮的類型
gzip_types text/plain application/x-javascript text/css application/xml;
#讓前端的緩存server混村經過的gzip壓縮的頁面
gzip_vary on;
upstream mycluster{
server 192.168.22.229:8080 weight=1;
server 192.168.22.230:8080 weight=1;
}
server{
listen 8088;
server_name 192.168.22.228;
charset utf-8; #設置編碼為utf-8
#root html;
#location / {
# root html;
# index index.html index.htm;
#}
#location ~ .*\.(jsp|do|action)$
location / {
proxy_next_upstream http_502 http_504 error timeout invalid_header;
proxy_pass http://mycluster;
# 真實的clientIP
proxy_set_header X-Real-IP $remote_addr;
# 請求頭中Host信息
proxy_set_header Host $host;
# 代理路由信息,此處取IP有安全隱患
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 真實的用戶訪問協議
proxy_set_header X-Forwarded-Proto $scheme;
}
#靜態文件交給nginx處理
location ~ .*\.(htm|html|gif|jpg|jpeg|png|bmp|swf|ioc|rar|zip|txt|flv|mid|doc|ppt|pdf|xls|mp3|wma)$
{
root /usr/local/webapps;
expires 30d;
}
#靜態文件交給nginx處理
location ~ .*\.(js|css)?
$ { root /usr/local/webapps; expires 1h; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } } }
另外還須要在227,228server上新建一個文件夾/usr/local/webapps/drp/img,在img文件夾中存放圖片girl.jpg。
假設Nginxserver較多的話。能夠使用Rsync做服務端自己主動同步或者使用NFS、MFS分布式共享存儲,避免一個個復制文件。
還有。這塊Nginx配置是做過一些優化的,比方開啟gzip壓縮,開啟高效文件傳輸模式。設置緩存,動靜分離,負載均衡等,能夠直接拿到項目中使用。
四、配置Keepalived
227server上的Keepalived配置:
! Configuration File for keepalived
#配置郵件相關信息
global_defs {
notification_email {
acassen@firewall.loc
failover@firewall.loc
sysadmin@firewall.loc
}
notification_email_from Alexandre.Cassen@firewall.loc
smtp_server 192.168.200.1
smtp_connect_timeout 30
router_id LVS_DEVEL
}
#配置Nginx健康監測腳本
vrrp_script check_nginx {
script "</dev/tcp/127.0.0.1/8088"
interval 3
weight -2
}
vrrp_instance VI_1 {
state MASTER
#網卡名稱
interface eno16777736
virtual_router_id 151
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
track_script {
check_nginx
}
virtual_ipaddress {
192.168.22.231
}
}
228server上的Keepalived配置:
! Configuration File for keepalived
global_defs {
notification_email {
acassen@firewall.loc
failover@firewall.loc
sysadmin@firewall.loc
}
notification_email_from Alexandre.Cassen@firewall.loc
smtp_server 192.168.200.1
smtp_connect_timeout 30
router_id LVS_DEVEL
}
vrrp_script check_nginx {
#script "/opt/chknginx.sh"
script "</dev/tcp/127.0.0.1/8088"
interval 3
weight -2
}
vrrp_instance VI_1 {
state MASTER
interface eno16777736
virtual_router_id 151
priority 99
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
track_script {
check_nginx
}
virtual_ipaddress {
192.168.22.231
}
}
特別注意,Nginx健康監測腳本。
在本地寫一個shell腳本,Keepalived監測不到。不知道為什么,網上的博客都是這么寫的。可是在我這里就不行。最后直接在Keepalived配置文件的script標簽中寫了這段監測的腳本。才得以成功。
vrrp_script chk_http_port {
script "</dev/tcp/192.168.22.227/80"
interval 1
weight -10
}
另外,假設你不明確某些配置的意思。能夠查看上篇博客,里面針對每條配置文件都做了具體解析。
五、Tomcat配置
229server,加入默認頁
在Tomcat的webapps文件夾下新建文件夾drp,而且創建index.jsp頁面
<%@ page language="java" contentType="text/html; charset=GB18030" pageEncoding="GB18030"%>
<HTML>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=GB18030">
<title>Nginx+Keepalived高可用,負載均衡。動靜分離測試</title>
</head>
<body>
<h1>您正在訪問server:192.168.22.229</h1>
<img src="/drp/img/girl.jpg" alt="女孩" />
</body>
</html>
230server同上
六、啟動服務並測試
分別啟動各個server上的Nginx、Keepalived、Tomcat,並測試是否能正常訪問。
①啟動測試Tomcat


能夠看到229和230server上的Tomcat已經能夠正常訪問。圖片沒有載入出來,是由於圖片沒有在Tomcatserver上存儲,而放在了Nginx上。
②啟動測試Nginx

能夠看到227和228上的Nginx啟動成功。而且實現了負載均衡和動靜分離的效果,圖片被成功的載入了出來。
③ 保證全部服務均可正常訪問后,啟動Keepalived測試。
啟動227。228server上的Keepalived。在瀏覽器中輸入地址:http://192.168.22.231:8088/drp/index.jsp

192.168.22.231是咱們設置的虛擬ip,在訪問站點的時候不在通過Nginx的ip了。而要通過這個vip進行訪問。
Keepalived啟動后咱們能夠通過查看/var/log 下的messages文件(日志文件),查看主從狀態。
查看227server/var/log/messages:

能夠看到227為Masterserver。那么咱們如今通過192.168.22.231訪問的就是227上的Nginx。
Nginx高可用測試
如今咱們通過兩個方面來測試高可用:
① server層的雙機熱備。模擬方式為關閉server。或者關閉Keepalived。
a. 關閉227Keepalived進程
如今提供服務的是227server,使用命令service keepalived stop將227上的Keepalived進程關閉掉之后。
查看227servermessas日志:

將192.168.22.231這個虛擬ip移除,關閉Keepalived。
查看228servermessages日志:

228原來為從server。當227server宕機后,228server由從server升級為主server,而且綁定上192.168.22.231這個虛擬IP,以繼續提供服務。站點能夠繼續訪問。
b. 啟動227Keepalived
查看227servermessas日志:

Keepalived成功啟動后。227server繼續接管192.168.22.231,成為MASTERserver,繼續提供服務。
查看228servermessages日志:

對應的228server。轉變為BACKUPserver,而且移除VIP。
② 應用層的雙機熱備。模擬方式為Kill掉Nginx進程
a. 關閉227Nginx
查看227servermessages日志:

VRRP_Script(check_nginx) failed ,意思是健康監測腳本運行失敗,表明Nginx服務壞掉,或者沒有啟動。然后Keepalived會使227server轉變為BACKUP狀態,移除VIP。
查看228servermessages日志:

當然不出所料,228server已經變為MASTER狀態。從而繼續提供服務。
b. 又一次啟動227Nginx
查看227servermessages日志:

VRRP_Script(check_nginx) succeeded 。意思是健康監測腳本運行成功。Nginx正常運行。
然后227server就會轉變為MASTER狀態。並提供服務。
查看228servermessages日志:

228server已經變為BUCKUP狀態。
小結
至此,高可用的一系列測試就已經完畢了。在整個測試過程中,不管是關閉某台server的Nginx。Keepalived還是整個server宕機。站點一直沒有中斷提供服務,這已經達到了主要的高可用;可是還有個缺陷就是假設Nginx主server不出問題的話,那么備用server將長期處於備份狀態。這種巨大資源浪費是不能容忍的。
當然這也有對應的方案來解決:Nginx雙主集群+DNS輪詢。敬請期待。。
。
這就是一個架構不斷演變。進化的過程。