Nginx负载均衡和双主热备
CORS配置
server {
listen 80;
server_name localhost;
#允许跨域请求的域
add_header 'Access-Control-Allow-Origin' *;
#允许带上cookie请求
add_header 'Access-Control-Allow-Credentials' 'true';
#允许请求的方法,如POST/GET/DELETE/PUT
add_header 'Access-Control-Allow-Methods' *;
#允许请求的header
add_header 'Access-Control-Allow-Headers' *;
......
}
防盗链配置
server {
#对源站点的验证,验证域名是否是 *.naga.com
valid_referers *.naga.com;
#非法引入会进入下方判断
if ($invalid_referer) {
return 403;
}
}
集群负载均衡
四层负载均衡是基于IP+端口的负载均衡,负载转发,记录连接由哪个服务器处理,后续这个连接的请求用同一台服务器处理。相当于长连接,基于TCP/UDP传输层的协议,一般用LVS(linux内核)的方式
七层负载均衡 基于url 或 ip,基本上是处理http协议的负载均衡,它会处理请求(压缩、缓存js css等),而四层只是转发不会处理请求。
DNS地域负载均衡,分配近的服务器地址
搭建负载均衡
假设有4台服务器 192.168.0.172(Nginx) 173、174、175都是后台服务
http {
#配置上游服务器 custom.name自定义名称
upstream custom.name {
server 192.168.0.173:8080;
server 192.168.0.174:8080;
server 192.168.0.175:8080;
}
server {
listen 80;
server_name www.naga.com;
#proxy_pass 当有请求过来,匹配/web之后,就会匹配到后面的请求; 它的值就是上面的upstream
location /web {
proxy_pass http://custom.name;
client_max_body_size 100M;
proxy_set_header Host $host;
}
}
}
负载均衡类型
1、轮询是默认的分配方式
2、加权的方式是给upstream 后加weight ----
upstream custom.name {
server 192.168.0.173:8080 weight=1;
server 192.168.0.174:8080 weight=5;
server 192.168.0.175:8080 weight=2;
}
3、ip_hash 根据用户的ip 进行 hash运算了之后指向一天服务器,ip不变则访问的服务不会变
hash (ip) % node_counts = index
一致性hash算法,运用了类似redis一样的hash环
upstream custom.name {
ip_hash;
server 192.168.0.173:8080;
server 192.168.0.174:8080;
server 192.168.0.175:8080;
}
4、url_hasp 就是把url进行hash运算(url尾巴有'/' 和没有这个斜杠,hash的结果是不一样 的)
hash (ip) % node_counts = index
upstream custom.name {
hash $request_uri; 开启
server 192.168.0.173:8080;
server 192.168.0.174:8080;
}
5、least_conn :哪一台连接数最少,就去请求哪一台
upstream custom.name {
least_conn; 开启
server 192.168.0.173:8080;
server 192.168.0.174:8080;
}
upstream 指令参数
max_conns=number:默认是0,限制一台服务器同时最大的连接数. 指的是一个worker进程的限制
server 192.168.0.173:8080 max_conns=100;
slow_start=time:服务器慢启动,默认是0;##商业版才能用## 不适用于hash和random两种负载均衡方式
server 192.168.0.173:8080 slow_start=60s;
down:表示这一台服务目前不可用
backup: 表示这一台是备用机,只有其他服务器全挂了备用机才能访问。
max_fails=number: 最大的失败次数,超过了次数集群将之提交,默认值是1
fail_timeout=time: 失败的时间段,失败了一段时间后,会再次询问此服务器能不能用,能用的话可以重新处理请求,默认值是10s
upstream xxx {
server 192.168.0.172:8080 slow_start=60s; 商业版才可用
server 192.168.0.173:8080 down; 此服务器不可用
server 192.168.0.174:8080 weight=5; 权重为5
server 192.168.0.175:8080 weight=2 max_conns=20; 权重为2,worker最大连接数20
server 192.168.0.176:8080 backup; 备用机,刚刚开始不能用,其他服务器全挂了才能用
server 192.168.0.176:8080 max_fails=2 fail_timeout=1s;
}
使用keepalive提高连接数
upstream xxx {
server 192.168.0.172:8080;
server 192.168.0.173:8080;
keepalive 32; 1、配置长连接的数量,保持连接可以提高吞吐量
}
server {
...
location /http/ {
proxy_pass http://xxx;
proxy_http_version 1.1; 2、代表上面长连接的版本号,(默认1.0,但1.0不是长链接)
proxy_set_header Connection ""; 3、用于connection里面的信息
}
}
控制浏览器缓存
1、设置静态内容的过期时间(expires time;)
location /static {
alias /home/naga;
expires 10s;
}
2、固定时间 expires @[time]
expires @22h30s; 代表晚上10:30pm失效,浏览器会自动计算时间差
3、 expires -[time]
expires -1h; 距离现在的1小时之前就失效了,相当于不用缓存
4、expires eposh; 不使用缓存
5、expires off; 默认值,其实就是不管,由浏览器自己使用自己的默认缓存
6、expires max; 缓存不会过期,除非修改过。
上游服务静态内容缓存
keys_zone 是内存缓存 max_size 是硬盘缓存
upstream xxx { ... }
# proxy_cache_path 设置缓存保存的地址,目录会自动创建
# keys_zone 设置共享内存,以及占用的空间大小 ## 内存缓存 ## (mycache是共享内存名,下面)
# max_size 设置缓存大小
# inactive 超过此时间,缓存自动清理
# user_temp_path=off 关闭临时目录
proxy_cache_path /usr/local/nginx/upstream_cache keys_zone=mycache:50m max_size=30g inactive=8h user_temp_path=off;
server {
listen 80;
server_name www.naga.cn;
#开启并且使用缓存
proxy_cache mycache;
#针对200和304状态码的缓存设置过期时间
proxy_cache_valid 200 304 8h;
}
配置SSL
1、云上申请证书,审核完成后将证书下载下来,nginx包含两个文件,一个crt证书文件,一个key密钥文件
2、将文件上传到云服务器,可以放在conf下
3、修改nginx.conf (事先在nginx里面加入ssl模块 --with-http_ssl_module, 安装后通过 ./nginx -V 查看 )
server {
listen 443;
server_name localhost;
# 开启ssl
ssl on;
# 配置ssl证书 因为放在conf下的,和nginx.conf同一路径,就这样写就行
ssl_certificate 1_www.imoocdsp.com_bundle.crt;
# 配置证书秘钥
ssl_certificate_key 2_www.imoocdsp.com.key;
# ssl会话cache
ssl_session_cache shared:SSL:1m;
# ssl会话超时时间
ssl_session_timeout 5m;
# 配置加密套件,写法遵循 openssl 标准
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
ssl_prefer_server_ciphers on;
}
### 将http的请求转发到https
server {
listen 80;
server_name localhost;
# 排除法
if ($http_name ~* "^online$" ) {
rewrite ^/(.*)$ https://localhost/online/ permanent;
}
rewrite ^ https://$host$1 permanent;
}
Nginx 高可用HA keepalived 双机主备
keepalived 使用的是虚拟路由冗余协议 VRRP ,这个协议的特点如下:
1、解决内网单机故障的路由协议,
2、用于构建过个路由MASTER BACKUP,将几台提供相同服务的路由器组成一个路由器组。一个路由就是nginx
3、虚拟IP-VIP(Virtual IP Address)
过程:用户不直接访问nginx,访问虚拟IP,这个虚拟IP是绑定了nginx的master节点,会根据这个关系解析出来结果。 master主节点挂了,心跳检测到后会让虚拟IP找到备用机,多个备用机会根据权重选择。
此外,主备节点的硬件配置应一样
安装keepalived
解压后进入文件夹进行配置,类似nginx,但是需要用 --sysconf=/etc指定配置文件地址
yum -y install libnl libnl-devel
./configure --prefix=/usr/local/keepalived --sysconf=/etc
make && make install
配置文件
!Configuration File for keepalived
# 全局配置
global_defs {
# 节点故障,切换了节点之后会通知管理员,下面还要配置邮箱的协议等,可以不要
notification_email {
123456@qq.com
}
notification_email_from Alexandre.Cassen@firewall.loc
smtp_server 192.168.200.1
smtp_connect_timeout 30
# 路由ID:当前安装keepalived节点主机的标识符,全局唯一
router_id naga_170
vrrp_skip_check_adv_addr
vrrp_strict
vrrp_garp_interval 0
vrrp_gna_interval 0
}
#基于VRRP协议的对象,计算机节点
vrrp_instance VI_1 {
state MASTER # 表示当前为nginx的master主节点
interface eth0 # 当前实例绑定的网卡, 用 ip addr查看
virtual_router_id 51 #虚拟路由ID,主备节点需要一致
priority 100 #权重,备机优先级越高就成为新的master
advert_int 1 # 主备心跳检查,时间间隔1s
authentication { # 认证授权,防止非法节点。每个节点一样就可以
auth_type PASS
auth_pass 1111
}
virtual_ipaddress { # 虚拟IP,用一个就可以了
192.168.17.17
#192.168.200.17
#192.168.200.18
}
}
#下面的都可以不要
virtual_server 192.168.200.100 443 {
delay_loop 6
lb_algo rr
lb_kind NAT
persistence_timeout 50
protocol TCP
real_server 192.168.201.100 443 {
weight 1
SSL_GET {
url {
path /
digest ff20ad2481f97b1754ef3e12ecd3a9cc
}
url {
path /mrtg/
digest 9b3a0c85a887a256d6939da88aabd8cd
}
connect_timeout 3
retry 3
delay_before_retry 3
}
}
}
virtual_server 10.10.10.2 1358 {
delay_loop 6
lb_algo rr
lb_kind NAT
persistence_timeout 50
protocol TCP
sorry_server 192.168.200.200 1358
real_server 192.168.200.2 1358 {
weight 1
HTTP_GET {
url {
path /testurl/test.jsp
digest 640205b7b0fc66c1ea91c463fac6334d
}
url {
path /testurl2/test.jsp
digest 640205b7b0fc66c1ea91c463fac6334d
}
url {
path /testurl3/test.jsp
digest 640205b7b0fc66c1ea91c463fac6334d
}
connect_timeout 3
retry 3
delay_before_retry 3
}
}
real_server 192.168.200.3 1358 {
weight 1
HTTP_GET {
url {
path /testurl/test.jsp
digest 640205b7b0fc66c1ea91c463fac6334c
}
url {
path /testurl2/test.jsp
digest 640205b7b0fc66c1ea91c463fac6334c
}
connect_timeout 3
retry 3
delay_before_retry 3
}
}
}
virtual_server 10.10.10.3 1358 {
delay_loop 3
lb_algo rr
lb_kind NAT
persistence_timeout 50
protocol TCP
real_server 192.168.200.4 1358 {
weight 1
HTTP_GET {
url {
path /testurl/test.jsp
digest 640205b7b0fc66c1ea91c463fac6334d
}
url {
path /testurl2/test.jsp
digest 640205b7b0fc66c1ea91c463fac6334d
}
url {
path /testurl3/test.jsp
digest 640205b7b0fc66c1ea91c463fac6334d
}
connect_timeout 3
retry 3
delay_before_retry 3
}
}
real_server 192.168.200.5 1358 {
weight 1
HTTP_GET {
url {
path /testurl/test.jsp
digest 640205b7b0fc66c1ea91c463fac6334d
}
url {
path /testurl2/test.jsp
digest 640205b7b0fc66c1ea91c463fac6334d
}
url {
path /testurl3/test.jsp
digest 640205b7b0fc66c1ea91c463fac6334d
}
connect_timeout 3
retry 3
delay_before_retry 3
}
}
}
示例:
#### 第一台 ####
global_defs {
# 路由ID:当前安装keepalived节点主机的标识符,全局唯一
router_id naga_170
}
#基于VRRP协议的对象,计算机节点
vrrp_instance VI_1 {
state MASTER # 表示当前为nginx的master主节点
interface eth0 # 当前实例绑定的网卡, 用 ip addr查看
virtual_router_id 51 #虚拟路由ID,主备节点需要一致
priority 100 #权重,备机优先级越高就成为新的master
advert_int 1 # 主备心跳检查,时间间隔1s
authentication { # 认证授权,防止非法节点。每个节点一样就可以
auth_type PASS
auth_pass 1111
}
virtual_ipaddress { # 虚拟IP,用一个就可以了
192.168.17.17
#192.168.200.17
#192.168.200.18
}
}
#### 第二台 ####
global_defs {
# 路由ID:当前安装keepalived节点主机的标识符,全局唯一
router_id naga_171
}
#基于VRRP协议的对象,计算机节点
vrrp_instance VI_1 {
state BACKUP # 表示当前为nginx的备用机节点节点
interface eth0 # 当前实例绑定的网卡, 用 ip addr查看
virtual_router_id 51 #虚拟路由ID,主备节点需要一致
priority 50 #权重,备机优先级越高就成为新的master
advert_int 1 # 主备心跳检查,时间间隔1s
authentication { # 认证授权,防止非法节点。每个节点一样就可以
auth_type PASS
auth_pass 1111
}
virtual_ipaddress { # 虚拟IP,用一个就可以了
192.168.17.17
}
}
keepalived配置Nginx自动启动
这时如果nginx挂了,keepalived没有挂,还是会无法访问。
- 脚本
cd /etc/keepalived
vim check_nginx_alive.sh
#!/bin/bash
A=`ps -C nginx --no-header | wc -l`
# 进程数是0的话,就尝试重启nginx
if [ $A -eq 0]; then
/usr/local/nginx/sbin/nginx
# 等一会儿再次检查ngxin,如果nginx没有启动成功,则停止当前机器的keepalived,使用备用机器
sleep 3
if [`ps -C nginx --no-header | wc -l` -eq 0]; then
killall keepalived
fi
fi
-
让keepalived监听脚本,配置文件中加入一下内容
vrrp_instance VI_1 {
......
authentication { # 认证授权,防止非法节点。每个节点一样就可以
auth_type PASS
auth_pass 1111
}
# 给对象加方法
track_script {
check_nginx_alive # 如下面vrrp_script的名字一样
}virtual_ipaddress { # 虚拟IP,用一个就可以了 192.168.17.17 }
}
vrrp_script check_nginx_alive {
script "/etc/keepalived/check_nginx_alive.sh" #脚本路径
interval 2 #每隔2s运行一次脚本
weight 0
# weight 10 #如果脚本运行成功,则升级权重+10
# weight -10 #如果脚本运行成功,则升级权重-10
}
双机主备缺点
浪费资源,主机没有挂之前,备用机没有白白浪费资源
Keepalived 双主热备
双机使用两个虚拟IP,互为主备。
使用DNS轮询两个虚拟IP进行访问,这样两台服务器都可以使用了。解析域名的时候,给域名解析两个云服务器的ip地址,再均衡权重即可。
配置(服务器一):
global_defs {
router_id naga_170
}
vrrp_script check_nginx_alive {
script "/etc/keepalived/check_nginx_alive.sh"
interval 2
weight 10
}
vrrp_instance VI_1 {
state MASTER
interface eth0
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
track_script {
check_nginx_alive
}
virtual_ipaddress {
192.168.17.17
}
}
vrrp_instance VI_2 { #名字要改
state BACKUP
interface eth0
virtual_router_id 52 #换了一组实例,改
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
track_script {
check_nginx_alive
}
virtual_ipaddress {
192.168.17.18 #VIP更改 虚拟ip virtual IP
}
}
配置(服务器二):
global_defs {
router_id naga_171
}
global_defs {
router_id naga_170
}
vrrp_script check_nginx_alive {
script "/etc/keepalived/check_nginx_alive.sh"
interval 2
weight 10
}
vrrp_instance VI_1 {
state BACKUP # 表示当前为nginx的备用机节点节点
interface eth0 # 当前实例绑定的网卡, 用 ip addr查看
virtual_router_id 51 #虚拟路由ID,主备节点需要一致
priority 100 #权重,备机优先级越高就成为新的master
advert_int 1 # 主备心跳检查,时间间隔1s
authentication { # 认证授权,防止非法节点。每个节点一样就可以
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.17.17
}
}
rrp_instance VI_2 { #第二组实例
state BACKUP
interface eth0
virtual_router_id 52 #第二组router_id
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 1111
}
virtual_ipaddress {
192.168.17.18 #改为第二个虚拟ip
}
}