Nginx那些事儿2

负载均衡

当访问的服务具有多个实例时,需要根据某种“均衡”的策略决定请求发往哪个节点,这就是所谓的负载均衡,目的是为了将数据流量分摊到多个服务器执行,减轻每台服务器的压力,从而提高了数据的吞吐量

负载均衡的种类
  • 常见的硬件有NetScaler、F5、Radware和Array等商用的负载均衡器
  • 常见的软件有LVS、Nginx等,它们是基于Linux系统并且开源的负载均衡策略
Nginx负载均衡配置
  • 利用upstream实现

  • upstream lbs {
       server localhost:8080;
       server localhost:8081;
    }
    
    server {
       # 跟路径 所有接口如果有统一的前缀就配置统一的前缀 比如 /api/,如果没有直接配置/
    	 location / {
    	 			# 这里的lbs 与 upstream后边的lbs相对应
            proxy_pass http://lbs;
            proxy_redirect default;
    		}
    }
    
负载均衡的集中策略
节点轮询
  • 默认策略
  • 简介:每个请求按顺序分配到不同的后端服务器
  • 适用于静态文件服务器
weight 权重配置
  • 简介:weight和访问比率成正比,数字越大,分配得到的流量越高

  • 服务器性能差异大的情况使用

  • 配置方式

    upstream lbs {
       server localhost:8080 weight=5;
       server localhost:8081 weight=10; 
    }
    
ip_hash
  • 简介:根据请求按访问ip的hash结果分配,每个用户就可以固定访问一个后端服务器

  • 服务器业务分区、业务缓存、Session需要单点的情况

  • 配置方式

    upstream lbs {
       ip_hash;
       server localhost:8080;
       server localhost:8081;
    }
    
利用upstream对节点进行设置
down:当前服务不参与负载
upstream lbs {
   server localhost:8080 down;
   server localhost:8081 weight=10; 
}
backup:其它所有的非backup机器down的时候,会请求backup机器
upstream lbs {
   server localhost:8080 backup;
   server localhost:8081 weight=10; 
}
Nginx探测后端节点可用性

思考:如果某个服务挂了,nginx无感知的情况下,还会将请求打到挂掉的服务上,此时会给用户带来很大的麻烦,如果是ip固定分发,就会造成很多用户使用不了我们的网站或者app,我们将如何解决这个问题呢?

配置参数解析:
  • max_fails:设定Nginx与后端节点通信的尝试失败的次数,默认值是1
  • fail_timeout:在fail_timeout参数定义的时间内,如果失败的次数达到max_fails设定值,Nginx就这个节点不可用
nginx认为的失败
  • 可以通过指令proxy_next_upstream来配置什么是失败的尝试
  • 注意默认配置时,http_404状态不被认为是失败的尝试
配置实操
upstream lbs {
                server localhost:8080 max_fails=2 fail_timeout=60s ;
                server localhost:8081 max_fails=2 fail_timeout=60s;
}

server {
		location / {
         proxy_pass http://lbs;
         # 这里就是配置nginx认为的失败
         proxy_next_upstream error timeout http_500 http_503 http_404;
		}
}
Nginx自定义全局异常
server {
    location / {
            proxy_pass http://lbs;
            proxy_set_header Host $host:$server_port;
            proxy_next_upstream error timeout http_500 http_503 http_404;
            # 存放用户的真实ip
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            #开启错误拦截配置,一定要开启
            proxy_intercept_errors on;
    }

    error_page   404 500 502 503 504  =200  /default_api;
    location = /default_api {
            default_type application/json;
            return 200 '{"code":"999","msg":"request method failed"}';
    }
}
Nginx配置浏览器跨域
location / {
                proxy_pass http://lbs;
                proxy_set_header Host $host:$server_port;
                proxy_next_upstream error timeout http_500 http_503 http_404;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_intercept_errors on;


                # 配置跨域
                add_header 'Access-Control-Allow-Origin' $http_origin;
                add_header 'Access-Control-Allow-Credentials' 'true';
                add_header 'Access-Control-Allow-Headers' 'DNT,web-token,app-token,Authorization,Accept,Origin,Keep-Alive,User-Agent,X-Mx-ReqToken,X-Data-Type,X-Auth-Token,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
                add_header Access-Control-Allow-Methods 'GET,POST,OPTIONS';

                if ($request_method = 'OPTIONS') {
                        add_header 'Access-Control-Max-Age' 1728000;
                        add_header 'Content-Type' 'text/plain; charset=utf-8';
                        add_header 'Content-Length' 0;
                        return 200;
                }
        }
Nginx配置websocket反向代理
server {
  listen    80;
  server_name xdclass.net;
  location / {
   proxy_pass http://lbs;
   proxy_read_timeout 300s; //websocket空闲保持时长
   proxy_set_header Host $host;
   proxy_set_header X-Real-IP $remote_addr;
   proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
   proxy_http_version 1.1;
   
   proxy_set_header Upgrade $http_upgrade;
   proxy_set_header Connection $connection_upgrade;
  } 
}
nginx重定向
rewrite 地址重定向语法:
rewrite regex replacement[flag]

server {
  listen    80;
  server_name xdclass.net;
  location / {
     proxy_pass http://lbs;
     proxy_read_timeout 300s; //websocket空闲保持时长
     proxy_set_header Host $host;
     proxy_set_header X-Real-IP $remote_addr;
     proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
     proxy_http_version 1.1;

     proxy_set_header Upgrade $http_upgrade;
     proxy_set_header Connection $connection_upgrade;
     rewrite ^/(.*)  https:787k.fun/$1 permanent
  } 
}

replacement部分是https://787k.fun/$1,$1是取自regex部分()里的内容即「.*」
flag参数
标记符号说明
last本条规则匹配完成后继续向下匹配新的location URI规则
break本条规则匹配完成后终止,不在匹配任何规则
redirect返回302临时重定向
permanent返回301永久重定向
正则表达式
字符描述
^匹配输入字符串的起始位置
$匹配输入字符串的结束位置
*匹配前面的字符零次或者多次
+匹配前面字符串一次或者多次
?匹配前面字符串的零次或者一次
.匹配除“\n”之外的所有单个字符
(pattern)匹配括号内的pattern
Nginx配置网关缓存
参数解析
  • /root/cache:本地路径,用来设置Nginx缓存资源的存放地址
  • levels=1:1:1
表示是三级目录,且每级目录数均为16个,总目录数为:16*16*16
  • key_zone:在共享内存中定义一块存储区域来存放缓存的 key 和 metadata
  • max_size:最大 缓存空间,如果不指定会使用掉所有磁盘空间。当达到 disk 上限后,会删除最少使用的 cache
  • inactive:某个缓存在inactive指定的时间内如果不访问,将会从缓存中删除
  • proxy_cache_valid:配置nginx cache中的缓存文件的缓存时间,proxy_cache_valid 200 304 2m 对于状态为200和304的缓存文件的缓存时间是2分钟
  • use_temp_path:建议为 off,则 nginx 会将缓存文件直接写入指定的 cache 文件中
  • proxy_cache:启用proxy cache,并指定key_zone,如果proxy_cache off表示关闭掉缓存
  • add_header Nging-Cache “$upstream_cache_status”:用于前端判断是否是缓存,miss、hit、expired(缓存过期)、updating(更新,使用旧的应答)
nginx配置缓存
proxy_cache_path /root/cache levels=1:2 keys_zone=just_cache:10m max_size=1g inactive=60m use_temp_path=off;

server {

      location /{
        ...     
        proxy_cache xd_cache;
        proxy_cache_valid 200 304 10m;
        proxy_cache_valid 404 1m; 
        proxy_cache_key $host$uri$is_args$args;
        add_header Nginx-Cache "$upstream_cache_status";
      }
  }
Nginx的压缩配置
#开启gzip,减少我们发送的数据量
gzip on;
gzip_min_length 1k;

#4个单位为16k的内存作为压缩结果流缓存
gzip_buffers 4 16k;

#gzip压缩比,可在1~9中设置,1压缩比最小,速度最快,9压缩比最大,速度最慢,消耗CPU
gzip_comp_level 4;

#压缩的类型
gzip_types application/javascript text/plain text/css application/json application/xml    text/javascript; 

#给代理服务器用的,有的浏览器支持压缩,有的不支持,所以避免浪费不支持的也压缩,所以根据客户端的HTTP头来判断,是否需要压缩
gzip_vary on;

#禁用IE6以下的gzip压缩,IE某些版本对gzip的压缩支持很不好
gzip_disable "MSIE [1-6].";

server {
		location /static {
           alias /usr/local/software/static;
		}
		location / {
					 proxy_pass http://lbs;
           proxy_read_timeout 300s; //websocket空闲保持时长
           proxy_set_header Host $host;
           proxy_set_header X-Real-IP $remote_addr;
           proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
           proxy_http_version 1.1;

           proxy_set_header Upgrade $http_upgrade;
           proxy_set_header Connection $connection_upgrade;
           rewrite ^/(.*)  https:787k.fun/$1 permanent
		}
}
Nginx配置https
安装nginx的时候要这样执行
./configure --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module
make&make install
Nginx配置https证书
server {
    listen       80;
    server_name  localhost;

    #charset koi8-r;

    #access_log  logs/host.access.log  main;

    location / {
        root   html;
        index  index.html index.htm;
    }

    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   html;
    }

    # proxy the PHP scripts to Apache listening on 127.0.0.1:80
    #
    #location ~ \.php$ {
    #    proxy_pass   http://127.0.0.1;
    #}

    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    #location ~ \.php$ {
    #    root           html;
    #    fastcgi_pass   127.0.0.1:9000;
    #    fastcgi_index  index.php;
    #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
    #    include        fastcgi_params;
    #}

    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    #location ~ /\.ht {
    #    deny  all;
    #}
}


# another virtual host using mix of IP-, name-, and port-based configuration
#
#server {
#    listen       8000;
#    listen       somename:8080;
#    server_name  somename  alias  another.alias;

#    location / {
#        root   html;
#        index  index.html index.htm;
#    }
#}


# HTTPS server
#
server {
    listen       443 ssl;
    server_name  localhost;

    ssl_certificate      pem的路径;
    ssl_certificate_key  key的路径;

    ssl_session_cache    shared:SSL:1m;
    ssl_session_timeout  5m;

    ssl_ciphers  HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers  on;

    location / {
        root   html;
        index  index.html index.htm;
    }
}
Nginx高可用
部署Nginx集群LVS+keepalive
LVS

LVS是Linux Virtual Server,Linux虚拟服务器,是一个虚拟的服务器集群系统,解决的两个核心问题是:选谁、转发

  • 三种负载均衡转发技术

    NAT:数据进出都通过 LVS, 前端的Master既要处理客户端发起的请求,又要处理后台RealServer的响应信息,将RealServer响应的信息再转发给客户端, 容易成为整个集群系统性能的瓶颈; (支持任意系统且可以实现端口映射)

    DR: 移花接木,最高效的负载均衡规则,前端的Master只处理客户端的请求,将请求转发给RealServer,由后台的RealServer直接响应客户端,不再经过Master, 性能要优于LVS-NAT; 需要LVS和RS集群绑定同一个VIP(支持多数系统,不可以实现端口映射)

    TUNL:隧道技术,前端的Master只处理客户端的请求,将请求转发给RealServer,然后由后台的RealServer直接响应客户端,不再经过Master;(支持少数系统,不可以实现端口映射))

在这里插入图片描述

keepalive

监控并管理 LVS 集群系统中各个服务节点的状态,keepalived是一个类似于交换机制的软件,核心作用是检测服务器的状态,如果有一台web服务器工作出现故障,Keepalived将检测到并将有故障的服务器从系统中剔除,使用其他服务器代替该服务器的工作,当服务器工作正常后Keepalived自动将服务器加入到服务器群中,这些工作全部自动完成。

后来加入了vrrp(虚拟路由器冗余协议),除了为lvs提供高可用还可以为其他服务器比如Mysql、Haproxy等软件提供高可用方案

  • 需要在多台机器上安装keepalive

  • yum install -y gcc
    yum install -y openssl-devel
    yum install -y libnl libnl-devel
    yum install -y libnfnetlink-devel
    yum install -y net-tools
    yum install -y vim wget
    yum install -y keepalived
    安装路径
    cd /etc/keepalived
    
  • 启动和查看命令

  • #启动
    service keepalived start
    
    #停止
    service keepalived stop
    
    #查看状态
    service keepalived status
    
    #重启
    service keepalived restart
    
    #停止防火墙
    systemctl stop firewalld.service
    
keepalive配置
  • 配置文件地址:/etc/keepalived/keepalived.conf
! Configuration File for keepalived

global_defs {

   router_id LVS_DEVEL # 设置lvs的id,在一个网络内应该是唯一的
   enable_script_security #允许执行外部脚本
}


#配置vrrp_script,主要用于健康检查及检查失败后执行的动作。
vrrp_script chk_real_server {
#健康检查脚本,当脚本返回值不为0时认为失败
    script "/usr/local/software/conf/chk_server.sh"
#检查频率,以下配置每2秒检查1次
    interval 2
#当检查失败后,将vrrp_instance的priority减小5
    weight -5
#连续监测失败3次,才认为真的健康检查失败。并调整优先级
    fall 3
#连续监测2次成功,就认为成功。但不调整优先级
    rise 2

    user root
}

#配置对外提供服务的VIP vrrp_instance配置

vrrp_instance VI_1 {

#指定vrrp_instance的状态,是MASTER还是BACKUP主要还是看优先级。
    state MASTER

#指定vrrp_instance绑定的网卡,最终通过指定的网卡绑定VIP
    interface ens33

#相当于VRID,用于在一个网内区分组播,需要组播域内内唯一。
    virtual_router_id 51

#本机的优先级,VRID相同的机器中,优先级最高的会被选举为MASTER
    priority 100

#心跳间隔检查,默认为1s,MASTER会每隔1秒发送一个报文告知组内其他机器自己还活着。
    advert_int 1

    authentication {
        auth_type PASS
        auth_pass 1111
    }

#定义虚拟IP(VIP)为787k.fun,可多设,每行一个
    virtual_ipaddress {
        787k.fun
    }

    #本vrrp_instance所引用的脚本配置,名称就是vrrp_script 定义的容器名
  track_script {
      chk_real_server
    }
}

# 定义对外提供服务的LVS的VIP以及port
virtual_server 787k.fun 80 {
    # 设置健康检查时间,单位是秒
    delay_loop 6

    # 设置负载调度的算法为rr
    lb_algo rr

    # 设置LVS实现负载的机制,有NAT、TUN、DR三个模式
    lb_kind NAT

    # 会话保持时间
    persistence_timeout 50

   #指定转发协议类型(TCP、UDP)
    protocol TCP

    # 指定real server1的IP地址

    real_server 真实ip(192.168.1.1) 80 {
        # 配置节点权值,数字越大权重越高
        weight 1

        # 健康检查方式
        TCP_CHECK {                  # 健康检查方式
            connect_timeout 10       # 连接超时
            retry 3           # 重试次数
            delay_before_retry 3     # 重试间隔
            connect_port 80          # 检查时连接的端口
        }

    }

}
  • 注意事项
router_id后面跟的自定义的ID在同一个网络下是一致的

state后跟的MASTER和BACKUP必须是大写;否则会造成配置无法生效的问题

interface 网卡ID;要根据自己的实际情况来看,可以使用以下方式查询 ip a  查询

在BACKUP节点上,其keepalived.conf与Master上基本一致,修改state为BACKUP,priority值改小即可

authentication主备之间的认证方式,一般使用PASS即可;主备的配置必须一致,不能超过8位
  • 两个机器全部启动nginx和keepalive后根据虚拟ip(787k.fun)来访问
如果某个Nginx挂了,但是该机器上的keepalive正常,请求依旧可以过来但是响应会失败,如何解决?
  • 需要关闭selinux
getenforce 查看
setenforce 0 关闭
  • 创建/usr/local/software/conf目录
  • 通过脚本实现监听
#配置vrrp_script,主要用于健康检查及检查失败后执行的动作。
vrrp_script chk_real_server {
#健康检查脚本,当脚本返回值不为0时认为失败
    script "/usr/local/software/conf/chk_server.sh"
#检查频率,以下配置每2秒检查1次
    interval 2
#当检查失败后,将vrrp_instance的priority减小5
    weight -5
#连续监测失败3次,才认为真的健康检查失败。并调整优先级
    fall 3
#连续监测2次成功,就认为成功。但不调整优先级
    rise 2
    user root
}
  • chk_server.sh脚本内容(需要 chmod +x chk_server.sh)
#!/bin/bash
#检查nginx进程是否存在
counter=$(ps -C nginx --no-heading|wc -l)
if [ "${counter}" -eq "0" ]; then
    service keepalived stop
    echo 'nginx server is died.......'
fi
  • 重启keepalive,重启nginx
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

乐观的Terry

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值