xiaoyi's blog
首页
  • 后端文章

    • PHP
  • 学习笔记

    • 《Git》学习笔记
  • MySQL
  • NoSQL
  • 中间件
  • Linux
  • Nginx
  • 网络
  • Mac
  • 学习笔记

    • 《Nginx》学习笔记
  • 学习
  • 博客搭建
  • 技术文档
  • GitHub技巧
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
  • 网站
  • 资源
  • 分类
  • 标签
  • 归档
GitHub

xuexuguang

后端新秀
首页
  • 后端文章

    • PHP
  • 学习笔记

    • 《Git》学习笔记
  • MySQL
  • NoSQL
  • 中间件
  • Linux
  • Nginx
  • 网络
  • Mac
  • 学习笔记

    • 《Nginx》学习笔记
  • 学习
  • 博客搭建
  • 技术文档
  • GitHub技巧
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
  • 网站
  • 资源
  • 分类
  • 标签
  • 归档
GitHub
  • Nginx进阶
    • worker抢占机制
    • 传统服务器事件处理
    • Nginx事件处理
    • 同步阻塞与异步阻塞
    • Nginx常用命令及指令
    • 日志切割
    • Nginx实现跨域请求
    • Nginx配置静态资源防盗链
    • upstream指令参数
    • keepalive
    • Ip_hash
    • 一致性hash算法
      • 是什么?
      • 基本原理
      • 解决的问题
    • url_hash
    • Nginx缓存
      • 控制浏览器的缓存
      • 反向代理缓存
    • Keepalived双机主备原理
      • master
      • backup
      • 进程常驻
  • lvs+keepalived高可用集群
  • 《Nginx》学习笔记
xuexuguang
2020-12-02

Nginx进阶

# worker抢占机制

master:一次性fork多个worker进程

worker:基于互斥锁进行抢占client的请求,然后开始进行处理 image-20201202220701359

# 传统服务器事件处理

客户端阻塞时,master进程通过fork进程来处理进程,大量的连接进来会耗尽服务器资源

image-20201203101228122

# Nginx事件处理

Nginx通过使用epoll模型,使用异步非阻塞的形式监听客户端连接,当阻塞的时候,会自动切换到另一个客户端连接上。

一个worker进程处理的最大连接数受限于nginx的worker_connections配置

image-20201202211428938

# 同步阻塞与异步阻塞

方式 说明
同步阻塞 客户端阻塞等待服务器处理完成
同步非阻塞 客户端阻塞等待服务器处理,服务器可以异步处理其他任务
异步阻塞 客户端异步发送请求到服务器,服务器处理完回调客户端
异步非阻塞 客户端与服务端都是异步处理任务,处理完成回调给客户端

同步与异步的区别在于客户端是否阻塞等待,阻塞与非阻塞的区别在于服务器是否阻塞等待

# Nginx常用命令及指令

常用命令

命令 说明
nginx -s stop 强制停止nginx
nginx -s quit 等待nginx处理完请求再退出
nginx -c nginx.conf 指定nginx配置文件,可以解决invalid nginx pid的问题

指令

指令 说明
root location中会追加到root后面
alias location中会以alias的路径为主

# 日志切割

该方式会将现有的access.log和error.log的内容copy到新的文件中,新的请求进来内容依然会写到access.log

#!/bin/bash

# 指定日志目录
LOG_PATH="/var/log/nginx/"

# 指定切割的日志格式
RECORD_TIME=$(date -d "yesterday"+%Y-%m-%d)
PID=/var/run/nginx/nginx.pid

# 将默认的access_log和error_log重命名为拆分后的格式
mv ${LOG-PATH}/access.log ${LOG-PATH}/access.${RECORD_TIME).log
mv ${LOG-PATH}/error.log ${LOG-PATH}/error.${RECORD_TIME}.Log

# 向Nginx主进程发送信号,用于重新打开日志文件
kill -USR1 `cat $PID`

# 记得修改权限 chmod +x cut_log.sh 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

也可以通过定时任务去实现自动切割,这种方式相对比较老,更新的日志分割可以结合nginx变量实现区分

# Nginx实现跨域请求

server {
    listen 90;
    server_name localhost;
    
    # 允许跨域请求的域, *代表所有
    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' *;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

跨域是浏览器的一种同源策略的限制,解决方法本质都是通过header头部的设置,除此之外还可以发送jsonp请求来解决跨域问题

# Nginx配置静态资源防盗链

server {
    listen 90;
    server_name localhost;
    
    # 通过验证refer头部来校验是否合法资源请求
    valid_referers *.imooc.com;
    # 非法引入会进入下方判断
    if ($invalid_referer) { 
        return 404;
    }
}
1
2
3
4
5
6
7
8
9
10
11

# upstream指令参数

upstream主要用于配置nginx的负载均衡,下面是对常用的指令的整理

# 负载均衡配置
upstream tomcats {
    # max_conns表示该server支持的最大连接数   
    server 192.168.1.173:8080 max_conns=1;
    
    # weight表示权重值,请求大概率会打到该服务器上
    server 192.168.1.174:8080 weight=6;
 
    # 1、通过server指令的slow_start参数来让其权重从0缓慢的恢复到正常值,避免大流量直接打进来再次压垮服务
    # 2、商业版使用,该参数不能用在hash、randomloadbalancing中,如果只有一台服务器会失效
    # 3、注意如果一个组里面只有一个server,那么max_fails,fail_timeout和slow_start参数都会被忽略。并且这个服务器永远都不会被认为是不可用的
    server 192.168.1.175:8080 slow_start=60s;
   
    # down用于标记服务节点不可用
    server 192.168.1.173:8080 down;
      
    # backup表示当前服务器节点是备用机,只有在其他的服务器都宕机以后,自己才会加入到集群中,被用户访问到,参数不能使用在hash和randomloadbalancing中
    server 192.168.1.173:8080 down;
    
    # 表示在15秒内请求某一server失败达到2次后,则认为该server已经挂了或者宕机了,随后再过15秒,这15秒内不会有新的请求到达刚刚挂掉的节点上,而是会运作的server,15秒后会再有新请求尝试连接挂掉的server,如果还是失败,重复上一过程
    server 192.168.1.173:8080 max_fails=2 fail_timeout=15s;
    
    # 保持的活跃的链接,避免频繁的创建连接,带来的性能损耗
    keepalive 32;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# keepalive

主要是保持与后端的连接数,避免请求nginx的时候,不断的与后端建立连接带来的性能损耗。

详细的可以参考keepalive的说明

upstream tomcats {
    server 192.168.1.174:8080 weight=6;  
    # 通过保持与客户端的长连接,来提高吞吐量,32为长连接的个数 
    keepalive 32;
}

server {
    location /http/ {
        proxy_pass http://tomcats;
        # 设置长连接使用的版本号 
        proxy_http_version 1.1;
        # 设置cookie头的connection为空 
        proxy_set_header Connection "";       
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# Ip_hash

ip_hash可以保证用户访问可以请求到上游服务中的固定的服务器,前提是用户ip没有发生更改。 使用ip_hash的注意点:不能把后台服务器直接移除,只能标记为down

upstream tomcats {
    ip_hash ;
    server 192.168.1.174:808;     
    server 192.168.1.174:8080 down;     
}

server {
    location /http/ {
        proxy_pass http://tomcats;       
    }
}
1
2
3
4
5
6
7
8
9
10
11

hash算法:通过对ip进行hash计算,对节点个数进行求模,最后决定落到哪个节点

image-20201202211638113

计算方式

参数 描述
node_counts 服务器的节点个数
index 服务器对应的索引

主要是通过hash(ip) % node_counts = index 最后计算得到index,根据index来匹配对应的服务器节点

算法是根据ip的前3段来进行计算的,所以,同一段落的ip会落在同一台服务器上。

# 一致性hash算法

hash算法存在节点个数的变更,导致命中的服务器的index发生变化,为了解决该问题,出现了一致性hash算法

# 是什么?

一致性hash算法本质上是一个从0-2的32次方的线,最终形成的圆

image-20201202211832557

# 基本原理

  1. 通过对服务器的节点(ip或者主机)、用户的ip进行hash后,最终确认服务器节点的位置和用户所在的位置。
  2. 按照顺时针的方向,选择最近的节点作为访问的节点

# 解决的问题

传统的hash算法,节点个数的变更,会导致全部的用户的请求发生变化。

一致性hash算法通过将服务器节点和用户的ip进行hash后,用户顺时针访问就近的节点,这样增加会移除节点影响的只是少部分用户。

# url_hash

根据url来路由到服务器的节点,计算方式:

image-20201202211909626

具体的配置

upstream tomcats {
    # 根据url进行hash,计算得到index作为服务器的索引
    url hash;
    # 路由请求到后端最少连接数的服务器上
    # least_conn; 
    server 192.168.1.174:808;     
    server 192.168.1.174:8080 down;     
}

server {
    location /http/ {
        proxy_pass http://tomcats;       
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

通过hash(url) % node_counts计算得到index`如果url中带有/,计算得到的hash结果是不一样的,会落到不同的服务节点上的。

# Nginx缓存

主要是缓存后端server的请求到服务器上,来缓解服务器本身的压力

image-20201202212013586

# 控制浏览器的缓存

location /html {
   alias /html;
   # 10s后失效
   expires 10s;
   # 到达指定的时间后失效
   # expires @22h30m;
   # 1小时前失效
   # expires -1h;
   # 不进行缓存
   # expires epoch;
   # 关闭,与epoch的区别在于off后浏览器保留默认的缓存机制
   # expires off;
   # 永不过期
   # expires max;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

如果文件内容发生了变化,会重新请求浏览器,max-age表示缓存内容的有效期

# 反向代理缓存

# 设置缓存保存的路径
#   key_zone:设置共享空间和占用的空间大小
#   max_size:设置缓存大小   
#   inactive:设置缓存的有效期,超过此时间缓存自动清理  
#   use_temp_path:关闭临时目录 

# nginx会把请求服务器的内容缓存到该目录下,8h后会自动清理  
proxy_cache_path /usr/local/nginx/upsteam_cache keys_zone=mycache:5m max_size=1g inactive=8h use_temp_path=off;

server {
    # 启用缓存,和keys_zone一致
    proxy_cache mycache;
    # 针对200、304的状态码保留8h的有效期  
    proxy_cache_valid 200 304 8h;
    location /http/ {
        proxy_pass http://tomcats;       
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# Keepalived双机主备原理

keepalived具有以下特点:

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

通过主备节点争抢ip的方式来保证负载均衡节点的高可用

# master

通过在192.168.1.171、192.168.1.172两台物理机上安装keepalived,来实现双机主备

在机器192.168.1.171上配置msater节点

global_defs {
    # 路由id:当前安装keepalived的节点主机标识符,保证全局唯一
    router_id keep_171
}

vrrp_instance VI_1 {
    # 表示状态是master主机还是backup备用机
    state MASTER
    # 该实例绑定的网卡 
    interface ens33
    # 保证主备节点一致即可  
    virtual_router_id 51
    # 权重, master权重一般高于backup,如果有多个,那就是选举,谁的权重高,谁就当选
    priority 100
    # 主备之间同步检查时间间隔,单位秒 
    adver_int 2
    # 认证权限密码,防止非法节点进入
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    
    # 虚拟出来的ip,可以有多个vip
    virtual_ipaddress {
        192.168.1.161
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

服务启动后观察ip addr,发现192.168.1.161绑定到了网卡上了

image-20201202212247198

# backup

在192.168.1.172上配置backup节点

global_defs {
    # 路由id:当前安装keepalived的节点主机标识符,保证全局唯一
    router_id keep_172
}

vrrp_instance VI_1 {
    # 表示状态是master主机还是backup备用机
    state BACKUP
    # 该实例绑定的网卡,当master节点宕机后,备用节点会替代master,会看到ens33的网卡下绑定了虚拟ip
    interface ens33
    # 保证主备节点一致即可  
    virtual_router_id 51
    # 权重, 权重低于master节点
    priority 80
    # 主备之间同步检查时间间隔,单位秒 
    adver_int 2
    # 认证权限密码,防止非法节点进入
    authentication {
        auth_type PASS
        auth_pass 1111
    }
       
    virtual_ipaddress {
        # 主备节点绑定的是同一个vip
        192.168.1.161
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

为支持syetemctl的使用,注册keepalived为系统服务

# 切换到keepalived的源目录下 
cd /usr/local/software/keepalived-2.0.20/keepalived/etc
# 将init.d目录中的keepalived文件拷贝到/etc/init.d目录中
cp init.d/keepalived /etc/init.d/
# 将sysconfig目录中的keepalived文件拷贝到/etc/sysconfig目录中
cp sysconfig/keepalived  /etc/sysconfig/
# 重新加载服务的配置文件
systemctl daemon-reload
1
2
3
4
5
6
7
8

启动keepalived

# 启动keepalived
syetemctl start keepalived
# 停止keepalived
syetemctl stop keepalived
# 重启keepalived
syetemctl restart keepalived
# 查看进程是否存在
ps-ef|grepkeepalived
1
2
3
4
5
6
7
8

使用keepalived使nginx进程常驻

# 脚本存放到keepalived的配置目录下
vim /etc/keepalived/check_nginx_alive_or_not.sh
1
2

# 进程常驻

新增检查nginx进程脚本

# !bin/bash
nginx_process_total = `ps -c nginx --no-header | wc -l`

if [$nginx_process_total -eq 0]:then
    /usr/local/sbin/nginx
    # 等待一小会再次检查nginx,如果没有启动成功,则停止keepalived,使其启动
    sleep 3

		# 保证nginx进程常驻,如果没有正常拉起,则杀死keepalived,保证backup节点工作
    if [`ps -c nginx --no-header | wc -l` -eq 0]:then
        killall keepalived
    fi
fi
1
2
3
4
5
6
7
8
9
10
11
12
13

新增脚本执行权限

chmod +x /etc/keepalived/check_nginx_alive_or_not.sh
1

配置keepalived监听nginx脚本

global_defs {
    router_id keep_172
}

vrrp_script check_nginx_alive {
    script "/etc/keepalived/check_nginx_alive_or_not.sh"
    interval 2 # 每搁两秒运行一次脚本
    weight 10 # 脚本执行失败,则权重+10
}

vrrp_instance VI_1 {        
    # vrrp_instance 中新增监听的脚本
    track_script {
        check_nginx_alive # 追踪nginx脚本
    }         
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

重启keepalived脚本

systemctl restart keepalived
1
编辑
上次更新: 2020/12/31, 06:55:18
lvs+keepalived高可用集群

lvs+keepalived高可用集群→

最近更新
01
MVC对比
12-31
02
负载均衡
12-31
03
数据库缓存优化
12-31
更多文章>
Theme by Vdoing | Copyright © 2020-2020 Evan Xu | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式