@saltyang
2018-06-19T11:40:22.000000Z
字数 8869
阅读 1186
Nginx
Keepalived
需求情况:
- Web Server需要多台来支持数据流量的大并发,且保持双活, 且客户端和Web Server之间通过https进行通信,且要求双向认证。
方案介绍
- LVS主要用于多服务器的负载均衡。它工作在网络层,可以实现高性能,高可用的服务器集群技术。它廉价,可把许多低性能的服务器组合在一起形成一个超级服务器。它易用,配置非常简单,且有多种负载均衡的方法。它稳定可靠,即使在集群的服务器中某台服务器无法正常工作,也不影响整体效果。另外可扩展性也非常好。
- LVS可分为三部分:
- Load Balancer:这是LVS的核心部分,它好比我们网站MVC模型的Controller。它负责将客户的请求按照一定的算法分发到下一层不同的服务器进行处理,自己本身不做具体业务的处理。另外该层还可用监控下一层的状态,如果下一层的某台服务器不能正常工作了,它会自动把其剔除,恢复后又可用加上。该层由一台或者几台Director Server组成。
- Server Array:该层负责具体业务。可有WEB Server、mail Server、FTP Server、DNS Server等组成。注意,其实上层的Director Server也可以当Real server用的。
- Shared Storage:主要是提高上一层数据和为上一层保持数据一致
- LVS负载均衡机制:
- NAT模式:网络地址转换
- IP隧道技术实现虚拟服务器。它跟NAT模式基本一样,但是Real server是直接返回数据给客户端,不需要经过Diretor server,这大大降低了Diretor server的压力。
- DR模式:DR通过改写请求报文的MAC地址,将请求发送到Real Server,而Real Server将响应直接返回给客户,免去了IP隧道技术中的IP隧道开销。目前大型网站使用最广泛的一种负载均衡手段.
- LVS Sample Refrence
- HAProxy支持两种主要的代理模式:"tcp"也即4层(大多用于邮件服务器、内部协议通信服务器等),和7层(HTTP)。在4层模式 下,HAProxy仅在客户端和服务器之间转发双向流量。7层模式下,HAProxy会分析协议,并且能通过允许、拒绝、交换、增加、修改或者删除请求 (request)或者回应(response)里指定内容来控制协议,这种操作要基于特定规则。
- Nginx不单可以作为强大的web服务器,也可以作为一个反向代理服务器,而且nginx还可以按照调度规则实现动态、静态页面的分离,可以按照轮询、ip哈希、URL哈希、权重等多种方式对后端服务器做负载均衡,同时还支持后端服务器的健康检查。
- Nginx负载均衡策略:Round Robin、IP hash、Weight、fair、url_hash。(fair/url_hash需要编译nginx第三方模块)
- RR: 默认情况提供轮询作为负载均衡策略。
- IP hash: 保证一个 client 每次请求都将到达同一个 backend。当然,如果所 hash 到的 backend 当前不可用,则请求会被转移到其他 backend。可以解决session的问题
- Weight: 默认情况下 为 1,如果第一个 server 的权重取默认值 1,第二个是 4,所以相当于第一个 server 接收 20% 的请求,第二接收 80% 的。要注意的是 weight 与 ip_hash 是不能同时使用的,原因很简单,他们是不同且彼此冲突的策略。(指定概率的轮询)
- fair: 按后端服务器的响应时间来分配请求,响应时间短的优先分配。
- url_hash: 按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,后端服务器为缓存时比较有效。
- 重试策略
max_fails默认值为1,fail_timeout默认值为10秒。nginx可以通过设置max_fails(最大尝试失败次数)和fail_timeout(失效时间,在到达最大尝试失败次数后,在fail_timeout的时间范围内节点被置为失效,除非所有节点都失效,否则该时间内,节点不进行恢复)对节点失败的尝试次数和失效时间进行设置,当超过最大尝试次数或失效时间未超过配置失效时间,则nginx会对节点状会置为失效状态,nginx不对该后端进行连接,直到超过失效时间或者所有节点都失效后,该节点重新置为有效,重新探测.
Nginx 重试策略参考- 备机策略
down: 表示单前的server暂时不参与负载
backup:其它所有的非backup机器down或者忙的时候,请求backup机器
- 是Linux下一个轻量级别的高可用解决方案。高可用(High Avalilability,HA),广义上讲,是指整个系统的高可用性,狭义上来说就是主机的冗余和接管;
为什么是轻量级呢,keepalived通过VRRP(Vritrual Router Redundancy Protocol,虚拟路由冗余协议)实现网络不间断稳定运行;与HeartBeat RoseHA相比,HeartBeat提供了完整的HA基本功能,比如:心跳检测,资源接管,检测集群中的服务,在集群节点转移共享ip地址所有者等等。虽然功能强大,但是部署使用相对麻烦,而keepalived只需一个配置文件就可搞定
- 整个方案中,Nginx充当反向代理服务器,使用两台,通过Keepalived来实现服务高可用,避免IP单点故障。
主服务器通过绑定的虚拟IP地址(VIP)对外提供负载均衡服务,热备服务器处于待机状态;当主服务器发生故障(Nginx异常、Keepalived异常、服务器宕机)时,热备服务器接管主服务器的公网虚拟IP,并提供负载均衡服务。双向认证是在反向代理服务器(主服务器或热备服务器)上进行,认证通过后,反向代理服务器将请求导到后端真正的Web Server服务器上,进行后端的程序处理。WebServer服务器保持双活,反向代理服务器根据后端Web Server服务器的连接负载情况均衡的分发请求到每台机器上。
Software Version
Linux: Centos 6.9
master_nginx ip: 192.168.1.141
salve_nginx ip: 192.168.1.142
VIP: 192.168.1.145
Web_server1 ip: 192.168.1.144:8080
Web_server2 ip: 192.168.1.144:18080
ENV Prepare
yum install keepalived nginx;
chkconfig keepalived on; chkconfig nginx on;
Nginx Config
vim /etc/nginx/nginx.conf
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log info;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
client_max_body_size 100m;
proxy_connect_timeout 600;
proxy_send_timeout 600;
proxy_read_timeout 600;
send_timeout 600;
#gzip on;
include /etc/nginx/conf.d/*.conf;
upstream real_server_pool {
server 192.168.1.144:8080 weight=1 max_fails=2 fail_timeout=30s;
server 192.168.1.144:18080 weight=1 max_fails=2 fail_timeout=30s;
#server 192.168.1.144:28443 weight=1 max_fails=2 fail_timeout=30s;
}
server {
listen 443;
ssl on;
server_name 192.168.1.141;
ssl_certificate /etc/nginx/server.crt;
ssl_certificate_key /etc/nginx/server.key;
ssl_client_certificate /etc/nginx/ca.crt;
ssl_session_timeout 5m;
ssl_verify_client on;
ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
ssl_prefer_server_ciphers on;
location ~ ^/(api|o)/ {
include uwsgi_params;
proxy_next_upstream http_502 http_504 error timeout invalid_header;
proxy_pass http://real_server_pool;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
}
}
}
Keepalived Config
! Configuration File for keepalived
global_defs {
notification_email {
salt_yang@puyacn.com
}
notification_email_from service@webackup.cn
smtp_server smtp.mxichina.cn
smtp_connect_timeout 30
router_id Recevier_MASTER
}
vrrp_script check_nginx {
script "/etc/keepalived/checknginx.sh check"
interval 30
}
vrrp_instance RE_MASTER {
state BACKUP
interface eth5
virtual_router_id 53
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.1.145
}
track_script {
check_nginx
}
debug
nopreempt
notify_master "/etc/keepalived/checknginx.sh master"
notify_backup "/etc/keepalived/checknginx.sh backup"
}
! Configuration File for keepalived
global_defs {
notification_email {
salt_yang@puyacn.com
}
notification_email_from service@webackup.cn
smtp_server smtp.mxichina.cn
smtp_connect_timeout 30
router_id Recevier_MASTER
}
vrrp_script check_nginx {
script "/etc/keepalived/checknginx.sh check"
interval 30
}
vrrp_instance RE_MASTER {
state BACKUP
interface eth5
virtual_router_id 53
priority 90
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.1.145
}
track_script {
check_nginx
}
debug
nopreempt
notify_master "/etc/keepalived/checknginx.sh master"
notify_backup "/etc/keepalived/checknginx.sh backup"
}
#!/bin/dash
# Script to handle Nginx from keepalived.
#
# Usage: checknginx.sh action
#
# Where action is :
#
# check : Nginx is running
#
# backup: set to backup state.
# fault : set to fault state. Killing Nginx
# master: set to master state. start Nginx
#
# Usage func :
[ "$1" = "--help" ] && { sed -n -e '/^# Usage:/,/^$/ s/^# \?//p' < $0; exit; }
#
# CONFIG
#
# Nginx server settings
NGINXPID="/var/run/nginx.pid"
NGINXINIT="/etc/init.d/nginx"
NGINX_FLAG="nginx"
# Keepalived
KEEPALIVEDPID=/var/run/keepalived.pid
KEEPALIVED=/etc/init.d/keepalived
# warmup delay
MAXWAIT=240
# maintenance flag: used to do maintenance on MySQL without switch between nodes
MAINTENANCE="/etc/keepalived/maintenance"
#
# CONFIG LOGGER
#
LOG="logger -t KeepNGINX[$$] -p syslog" # do not use -i
LOGWARN="$LOG.warn"
LOGERR="$LOG.err"
check() {
# master and slave need check nginx status,
# if nginx is down in master ,need switch master to slave. But it's not needed in salve.
if ip addr | grep "${VIP}"
then
if check_nginx
then
$LOGWARN "Nginx is ok"
else
$NGINXINIT restart
$LOGWARN "Restart Nginx service"
if check_nginx
then
$LOGWARN "After restart Nginx service, but it's also down. Switch keepalive status"
$KEEPALIVED restart
fi
fi
else
$LOGWARN "This is Nginx Salve."
if check_nginx
then
$LOGWARN "Nginx is ok"
else
$NGINXINIT restart
$LOGWARN "Restart Nginx service"
if check_nginx
then
$LOGWARN "After restart Nginx service, but it's also down. Switch keepalive status"
fi
fi
fi
return $?
}
# WARNING set_master is called at keepalived start
# So if already in "good" state we must do nothing :)
set_master() {
# Starting Nginx
if [ $( pidof nginx | wc -w ) -gt 0 ]
then
$LOGWARN "Nginx already started ? What did I have to do ?"
else
$LOGWARN "Starting Nginx ..."
$NGINXINIT start
$LOGWARN "Waiting for Nginx ..."
for i in $( seq 1 $MAXWAIT )
do
sleep 1
if check_nginx
then
break
fi
done
fi
if check_nginx
then
$LOGWARN "Nginx start success..."
else
$LOGWARN "Nginx start failed and need a manual repair :("
fi
}
# Check that Nginx is responding
# Return:
# 0 if everything is OK (or in maintenance mode)
# 1 if Nginx did not return the expected string
check_nginx() {
flag_exists=$(ps -ef | grep "${NGINX_FLAG}" | grep -v grep | wc -l)
if [ "${flag_exists}" -eq 0 ]
then
$LOGWARN "[Nginx service is unavailable.]"
return 1
else
return 0
fi
}
case "$1" in
check)
check
exit $?
;;
backup)
$LOGWARN "=> set to backup state <="
set_master
exit $?
;;
master)
$LOGWARN "=> set to master state <="
set_master
exit $?
;;
esac
#设定http服务器,利用它的反向代理功能提供负载均衡支持
http {
#设定mime类型,类型由mime.type文件定义
include /etc/nginx/mime.types;
default_type application/octet-stream;
#设定日志格式
access_log /var/log/nginx/access.log;
#省略上文有的一些配置节点
#。。。。。。。。。。
#设定负载均衡的服务器列表
upstream mysvr {
#weigth参数表示权值,权值越高被分配到的几率越大
server 192.168.8.1x:3128 weight=5;
#本机上的Squid开启3128端口,不是必须要squid
server 192.168.8.2x:80 weight=1;
server 192.168.8.3x:80 weight=6;
}
upstream mysvr2 {
#weigth参数表示权值,权值越高被分配到的几率越大
server 192.168.8.x:80 weight=1;
server 192.168.8.x:80 weight=6;
}
#第一个虚拟服务器
server {
#侦听192.168.8.x的80端口
listen 80;
server_name 192.168.8.x;
#对aspx后缀的进行负载均衡请求
location ~ .*.aspx$ {
#定义服务器的默认网站根目录位置
root /root;
#定义首页索引文件的名称
index index.php index.html index.htm;
#请求转向mysvr 定义的服务器列表
proxy_pass http://mysvr ;
#以下是一些反向代理的配置可删除.
proxy_redirect off;
#后端的Web服务器可以通过X-Forwarded-For获取用户真实IP
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;
#nginx跟后端服务器连接超时时间(代理连接超时)
proxy_connect_timeout 90;
#连接成功后,后端服务器响应时间(代理接收超时)
proxy_read_timeout 90;
#设置代理服务器(nginx)保存用户头信息的缓冲区大小
proxy_buffer_size 4k;
#proxy_buffers缓冲区,网页平均在32k以下的话,这样设置
proxy_buffers 4 32k;
#高负荷下缓冲大小(proxy_buffers*2)
proxy_busy_buffers_size 64k;
#设定缓存文件夹大小,大于这个值,将从upstream服务器传
proxy_temp_file_write_size 64k;
}
}
}