nginx

94 阅读10分钟

跨域

需要添加到server中

# 允许跨域请求的域, * 代表所有
add_header 'Access-Control-Allow-Origin' *;
# 允许带上cookie请求
add_header 'Access-Control-Allow-Credentials' 'true';
# 允许请求方式 比如GET/POST/PUT/DELETE
add_header 'Access-Control-Allow-Methods' *;
# 允许请求的header
add_header 'Access-Control-Allow-Headers' *;

防爆连

# 对源站点进行验证
valid-refresh *.odliken.cn
# 对非法引入会进入下方判断
if ($invalid-refresh){
		return 404;
}

四层负载均衡

主要用于转发请求

  • F5 硬件负载均衡---基于硬件
  • LVS 四层负载均衡 --- Nginx内核负载均衡,与协议无关
  • Haproxy 四层负载均衡
  • Nginx 四层负载均衡 --- Nginx七层为主,http的负载均衡

七层负载均衡

用于http应用层的,可以对请求和响应请求,请求的ip,协议,端口号都可获知

  • Nginx 七层负载均衡
  • Haproxy 七层负载均衡
  • Apache 七层负载均衡

DNS 地域负载均衡

负载均衡配置

upstream tomcats{
    server 192.168.3.12:8080 weight=5;
    server 192.168.3.18:8080 weight=1;
    #server 162.14.111.170:8080;
    server 162.14.111.170:8088 weight=3;
}

server {
    listen  80;
    server_name www.tomcats.com;

    location / {
        proxy_pass http://tomcats;
    }
}

upstream 指令参数

  • max_conns 限制服务器连接的最大参数,默认值为0 不做设置(限流)
  • slow_start 缓慢启动,让其他节点缓慢的启动加入到集群,缓慢分配流量到对应的服务器,默认值为0并为关闭 商业版本才有
  • down 标识服务器的状态
  • nbackup 标识为备用机,在其他服务器宕机之后才会启用
  • max_fails 最大的失败次数,超过最大数值则会被认为当前服务器宕机,Nginx会将此服务剔出集群 默认值为1
  • fail_timeout 失败的时间段,需要和max_fails配合使用,当服务器最大失败数达到之后,在fail_timeout的时间内Nginx不会将新的请求分配到当前服务器,超时fail_timeout时间后则再会尝试分配请求到此服务器 默认值为10s

keepalive

配置长链接数,可以提高吞吐量

ip_hash负载均衡

在ip不变的情况下,用户的会话会在同一台服务器中,不发送到其他的服务器上,但是用户ip发生变化之后,Nginx有可能会分配到其他服务器,在需要移除某台服务器的时候不能直接注释或者直接删除server 而是需要在后面加上down

配置

upstream tomcats{
    ip_hash;

    server 192.168.3.12:8080 weight=5;
    server 192.168.3.18:8080 weight=1;
    #server 162.14.111.170:8080;
    server 162.14.111.170:8088 weight=3;
}

hash算法

实现的为ipv4 前端3段的只进行hash

hash算法带来的问题

在集群中某台服务器宕机之后,Nginx将会将请求进行重新hash,这会带来某些用户的会话丢失

一致性哈希算法

循环就近原则,当服务器宕机或者新增,则会按照ip递增就近原则选择相对应的服务器.

usl_hash 负载均衡

根据路由地址(request_uri)进行取模然后hash

配置

upstream tomcats{
    hash $request_uri;

    server 192.168.3.12:8080;
    server 192.168.3.18:8080;
    server 162.14.111.170:8080;
    server 162.14.111.170:8088;
}

least_conn

根据最小链接数进行请求,将新进入的链接放到最小连接数的服务器上

配置

upstream tomcats{
    least_conn;

    server 192.168.3.12:8080;
    server 192.168.3.18:8080;
    server 162.14.111.170:8080;
    server 162.14.111.170:8088;
}

缓存

304为缓存

expires指令

  • expires [time] 设置缓存过期时间
  • expires @ [time] 指定时间到期
  • expires - [time] 缓存提前过期
  • expires epoch 不设置缓存
  • expires off 关闭缓存,默认浏览器机制
  • expires max 最大时间,用不过期
#proxy_cache_path设置缓存保存的位置
#			keys_zone设置共享内存及占用的空间大小
#			max_size设置缓存大小
#			inactive 超过此时间,缓存自动清零
#			use_temp_path 关闭零时目录
proxy_cache_path /usr/local/nginx/upstream_cache keys_zone=mycache:5m max_size=1g inactive=8h use_temp_path=off;
server {
    listen  80;
    server_name www.tomcats.com;

	#开启并使用缓存
	proxy_cache mycache;
	#针对200和304状态码的缓存设置过期时间
	proxy_cache_valid        200 304 8h;

    location / {
        proxy_pass http://tomcats;
    }
}

安装ssl证书

当对接域名有一个是https之后,其他的也必须是https,不然会显示为不安全 申请到ssl证书后会有crt和key文件 Nginx安装ssl需要提前安装好htto_ssl_module模块 进入到Nginx的目录中

配置

server {
    listen  443;
    server_name www.tomcats.com;

    #开启ssl
    ssl     on;
    #配置ssl证书
    ssl_certificate ***.crt;
    #配置证书秘钥
    ssl_certificate_key ***.key;
    #ssl会话cache
    ssl_session_cache shared:SSL:1m;
    #ssl会话超时时间
    ssl_session_timeout 5;

    #配置加密套件,写法遵循 openssl标准
    ssl_protocol TLSv1.1 TLSv1..2;
    ssl_criphers ECHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
    ssl_prefer_server_ciphers   in;

    location / {
        proxy_pass http://tomcats;
    }
}

动静分离

  • 分布式
  • 前后端解耦
  • 静态归nginx
  • 接口服务化
  • 静态数据:css/js/html/images/audios/videos/...
  • 动态数据:得到的响应可能和上一次不同

动静分离的方式 CDN

静态资源会放在第三方

动静分离的方式Nginx

动静分离的问题

  1. 跨域
    • SpringBoot
    • Nginx
    • jsonp
  2. 分布式会话
    • 分布式缓存中间件Redis

Nginx高可用 HA = High Availability

Nginx单节点启动时,为避免nginx宕机则需要准备一台备用机

keepaloved

  • 解决单点故障
  • 组件免费
  • 可以实现高可用HA机制
  • 基于VRRP协议

虚拟路由冗余协议 VRRP

  • Virtual Router Redundancy Protocol
  • 解决内网单机故障的路由协议
  • 构建多个路由器 MASTER BACKUP
  • 虚拟IP -VIP (Virtual IP Address)

keepalived 双机主备原理

主备机的配置应该相同 正常流程 主机宕机,keepalived会对主机进行心跳检测,当确认主机宕机后,启用备用机

配置

# 全局配置
global_defs {
   # 邮件通知信息
   notification_email {
     # 定义收件人
     acassen@firewall.loc
   }
   # 定义发件人
   notification_email_from Alexandre.Cassen@firewall.loc
   # SMTP服务器地址
   smtp_server 192.168.200.1
   smtp_connect_timeout 30
   # 路由器id:当前安装keepalived节点主机的标识符,全局唯一
   router_id LVS_DEVEL
   # VRRP的ipv4和ipv6的广播地址,配置了VIP的网卡向这个地址广播来宣告自己的配置信息,下面是默认值
   vrrp_mcast_group4 224.0.0.18
   vrrp_mcast_group6 ff02::12
}

# 定义用于实例执行的脚本内容,比如可以在线降低优先级,用于强制切换
vrrp_script SCRIPT_NAME {

}

# 计算机节点
vrrp_instance VI_1 {
    # 表示当前状态,可以是MASTER或者BACKUP
    state MASTER
    # 当前示列绑定的网卡
    interface ens33
    # 虚拟路由ID,如果是一组虚拟路由就定义一个ID,如果是多组就要定义多个,而且这个虚拟
    # ID还是虚拟MAC最后一段地址的信息,取值范围0-255,保证主备节点一致
    virtual_router_id 51
    # 使用哪个虚拟MAC地址
    use_vmac XX:XX:XX:XX:XX
    # 监控本机上的哪个网卡,网卡一旦故障则需要把VIP转移出去
    track_interface {
        eth0
        ens33
    }
    # 优先级/权重 谁的优先级搞,在MASTER挂掉以后,就能成为新的MASTER
    priority 100
    # 主备之间同步检车的时间间隔,默认1s,单位为秒
    advert_int 1
    # 认证授权的密码,防止非法节点进入,主备之间相同
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    # 设置虚拟VIP地址,
    virtual_ipaddress {
        # IP/掩码 dev 配置在哪个网卡
        192.168.200.16/24 dev eth1
        # IP/掩码 dev 配置在哪个网卡的哪个别名上
        192.168.200.17/24 dev label eth1:1
    }
    # 虚拟路由,在需要的情况下可以设置lvs主机 数据包在哪个网卡进来从哪个网卡出去
    virtual_routes {
        192.168.110.0/24 dev eth2
    }
    # 工作模式,nopreempt表示工作在非抢占模式,默认是抢占模式 preempt
    nopreempt|preempt
    # 如果是抢占默认则可以设置等多久再抢占,默认5分钟
    preempt delay 300
    # 追踪脚本,通常用于去执行上面的vrrp_script定义的脚本内容
    track_script {

    }
    # 三个指令,如果主机状态变成Master|Backup|Fault之后会去执行的通知脚本,脚本要自己写
    notify_master ""
    notify_backup ""
    notify_fault ""
}

# 定义LVS集群服务,可以是IP+PORT;也可以是fwmark 数字,也就是防火墙规则
# 所以通过这里就可以看出来keepalive天生就是为ipvs而设计的
virtual_server 10.10.10.2 1358 {
    delay_loop 6
    # 算法
    lb_algo rr|wrr|lc|wlc|lblc|sh|dh 
    # LVS的模式
    lb_kind NAT|DR|TUN
    # 子网掩码,这个掩码是VIP的掩码
    nat_mask 255.255.255.0
    # 持久连接超时时间
    persistence_timeout 50
    # 定义协议
    protocol TCP
    # 如果后端应用服务器都不可用,就会定向到那个服务器上
    sorry_server 192.168.200.200 1358

    # 后端应用服务器 IP PORT
    real_server 192.168.200.2 1358 {
        # 权重
        weight 1
        # MSIC_CHECK|SMTP_CHEKC|TCP_CHECK|SSL_GET|HTTP_GET这些都是
        # 针对应用服务器做健康检查的方法
        MISC_CHECK {}
        # 用于检查SMTP服务器的
        SMTP_CHEKC {}

        # 如果应用服务器不是WEB服务器,就用TCP_CHECK检查
        TCP_CHECK {
          # 向哪一个端口检查,如果不指定默认使用上面定义的端口
          connect_port <PORT>
          # 向哪一个IP检测,如果不指定默认使用上面定义的IP地址
          bindto <IP>
          # 连接超时时间
          connect_timeout 3
        }

        # 如果对方是HTTPS服务器就用SSL_GET方法去检查,里面配置的内容和HTTP_GET一样
        SSL_GET {}

        # 应用服务器UP或者DOWN,就执行那个脚本
        notify_up "这里写的是路径,如果脚本后有参数,整体路径+参数引起来"
        notify_down "/PATH/SCRIPTS.sh 参数"

        # 使用HTTP_GET方法去检查
        HTTP_GET {
            # 检测URL
            url { 
              # 具体检测哪一个URL
              path /testurl/test.jsp
              # 检测内容的哈希值
              digest 640205b7b0fc66c1ea91c463fac6334d
              # 除了检测哈希值还可以检测状态码,比如HTTP的200 表示正常,两种方法二选一即可
              status_code 200
            }
            url { 
              path /testurl2/test.jsp
              digest 640205b7b0fc66c1ea91c463fac6334d
            }
            url { 
              path /testurl3/test.jsp
              digest 640205b7b0fc66c1ea91c463fac6334d
            }
            # 向哪一个端口检查,如果不指定默认使用上面定义的端口
            connect_port <PORT>
            # 向哪一个IP检测,如果不指定默认使用上面定义的IP地址
            bindto <IP>
            # 连接超时时间
            connect_timeout 3
            # 尝试次数
            nb_get_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
            nb_get_retry 3
            delay_before_retry 3
        }
    }
}

精简配置

# 计算机节点
vrrp_instance VI_1 {
    # 表示当前状态,可以是 MASTER 或者 BACKUP
    state MASTER
    # 当前示列绑定的网卡
    interface ens33
    # 虚拟路由 ID,如果是一组虚拟路由就定义一个 ID,如果是多组就要定义多个,而且这个虚拟
    # ID 还是虚拟 MAC 最后一段地址的信息,取值范围 0-255,保证主备节点一致
    virtual_router_id 51
    # 优先级/权重 谁的优先级搞,在 MASTER 挂掉以后,就能成为新的 MASTER
    priority 100
    # 主备之间同步检车的时间间隔,默认 1s,单位为秒
    advert_int 1
    # 认证授权的密码,防止非法节点进入,主备之间相同
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    # 设置虚拟 VIP 地址,
    virtual_ipaddress {
       192.168.1.161
    }
}
  • 当keepalived正常运行,但nginx宕机是,服务停止,所以需要编写对应脚本去监听nginx是否运行,若没有运行则需要尝试着重启nginx或者将本机keepalived的MESTER让出

check_nginx_alive_or_not.sh 脚本

注意权限sh文件,让keepalived定时监听nginx运行状态

#!/bin/bash

A=`ps -C nginx --no-header |wc -l`
#判断nginx是否宕机,如果宕机,尝试重启
if [ $A -eq 0 ]; then
    # nginx启动命令
    /usr/local/nginx/sbin/nginx
    #等待一会儿在次检查nginx,如果没有启动成功,则停止keepalived,使其启动备用机
    sleep 3
    if [ `ps -C nginx --no-header |wc -l` -eq 0 ]; then
        killall keepalived
    fi
fi

keepalived配置

在keepalived中的configuration文件中修改

vrrp_script check_nginx_alive_or_not {
	#sh文件路径
    script  "/etc/keepalived/check_nginx_alive_or_not.sh"
	interval 2 # 每隔两秒运行上一行脚本
	# weight 10 # 如果脚本运行升高,则升级计算机节点中的权重+10
	weight -10 # 如果脚本运行失败,则降低计算机节点中的权重-10
}
# 调用时则只需要将改脚本函数添加到vrrp_instance中即可
track_script {
	check_nginx_alive_or_not # 追踪 nginx 脚本
}

keepalived双主热备

双主热备配置:设置两份配置文件内容,一份为主,一份为备即可实现双主热备

# 计算机节点
vrrp_instance VI_1 {
    # 表示当前状态,可以是 MASTER 或者 BACKUP
    state MASTER
    # 当前示列绑定的网卡
    interface ens33
    # 虚拟路由 ID,如果是一组虚拟路由就定义一个 ID,如果是多组就要定义多个,而且这个虚拟
    # ID 还是虚拟 MAC 最后一段地址的信息,取值范围 0-255,保证主备节点一致
    virtual_router_id 51
    # 优先级/权重 谁的优先级搞,在 MASTER 挂掉以后,就能成为新的 MASTER
    priority 100
    # 主备之间同步检车的时间间隔,默认 1s,单位为秒
    advert_int 1
    # 认证授权的密码,防止非法节点进入,主备之间相同
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    # 设置虚拟 VIP 地址,
    virtual_ipaddress {
       192.168.1.161
    }
}
#备用设置
vrrp_instance VI_2{
    # 表示当前状态,可以是 MASTER 或者 BACKUP
    state BACKUP
    # 当前示列绑定的网卡
    interface ens33
    # 虚拟路由 ID,如果是一组虚拟路由就定义一个 ID,如果是多组就要定义多个,而且这个虚拟
    # ID 还是虚拟 MAC 最后一段地址的信息,取值范围 0-255,保证主备节点一致
    virtual_router_id 52
    # 优先级/权重 谁的优先级搞,在 MASTER 挂掉以后,就能成为新的 MASTER
    priority 80
    # 主备之间同步检车的时间间隔,默认 1s,单位为秒
    advert_int 1
    # 认证授权的密码,防止非法节点进入,主备之间相同
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    # 设置虚拟 VIP 地址,
    virtual_ipaddress {
       192.168.1.162
    }
}

DNS负载均衡

在域名的购买商除,解析多个相同域名不同的服务器ip则可实现DNS的负载均衡,默认为轮询

LVS负载均衡

LVS网络拓扑图

  • Linux Virtual Server
  • 章文嵩博士主导的开源负载均衡项目
  • LVS (ipvs) 已被集成到Linux内核中
  • 负载均衡调度器 ----四层负载均衡

LVS+Nginx原因

  • LVS基于四层,工作效率高
  • 单个Nginx承受不了压力,去需要集群
  • LVS充当Nginx集群的调度者
  • Nginx接受请求来回,LVS可以只接受不响应

Nginx网络拓扑图 nginx会对请求和响应都做处理

LVS网络拓扑图 LVS只会处理请求,不会处理响应,而是通过后边的服务直接返回响应

LVS模式之NAT

LVS 模式之TUN

ip隧道,所有的计算机节点都必要要有网卡,服务节点都需要公网ip 用户所有的请求,上行通过LVS,下行则不会直接通过LVS

LVS模式之DR

也是会通过虚拟ip 和TUN相比,DR模式会将后边的节点打包起来,通过Router返回到用户,服务节点就不需要公网ip,被虚拟ip隐藏起来了。