nginx的平滑升级添加新功能及location实战
一、nginx平滑升级
1、nginx平滑升级概述
随着nginx越来越流行,并且nginx的优势也越来越明显,nginx的版本迭代也来时加速模式,1.9.0版本的nginx更新了许多新功能,例如stream四层代理功能,伴随着nginx的广泛应用,版本升级必然越来越快,线上业务不能停,此时nginx的升级就是运维的工作了
Nginx方便地帮助我们实现了平滑升级。其原理简单概括,就是:
(1)在不停掉老进程的情况下,启动新进程。 (2)老进程负责处理仍然没有处理完的请求,但不再接受处理请求。 (3)新进程接受新请求。 (4)老进程处理完所有请求,关闭所有连接后,停止。 这样就很方便地实现了平滑升级。一般有两种情况下需要升级Nginx,一种是确实要升级Nginx的版本,另一种是要为Nginx添加新的功能。
2、nginx平滑升级原理
多进程模式下的请求分配方式
nginx默认工作在多进程模式下,即主进程启动完成配置加载和端口绑定等动作 ,fork出指定数量的工作进程,这些子进程会持有监听端口文件描述符(fd)并通过在该描述上添加监听事件来接受连接(accept)
信号的接受和处理
nginx主进程在启动完成后进入等待状态,负载相应各类系统消息,如SIGCHLD,SIGHUP.SIGUSR2等
3、nginx平滑升级过程
- 获取老版本的编译信息
- 获取新版本的安装包或功能包
- 配置新版本或功能,配置时加上老版本的编译信息和新版本功能(–add-module)
- 编译,编译完成后不能执行安装操作(make install)
- 备份老版本程序,使用复制的方式
- 停掉老版本程序的进程
- 将新版本程序复制到老版本所在位置替换掉老版本
- 最后启动新版本即可完成升级
注意:后四个步骤必须用一条命令完成操作,秒级完成,不可让用户感知到软件在升级。
4、nginx信号简介
TERM,INT | 立刻退出 |
---|
QUIT | 等待工作进程结束在退出 | KILL | 强制终止进程 | HUP | 重新加载配置文件,使用新的的配置启动工作进程,并逐步关闭日进程 | USR1 | 重新打开日志文件 | USR2 | 启动新的主进程,实现热升级 | WINCH | 逐步关闭工作进程 |
TERM,INT | 立刻退出 |
---|
QUIT | 等待请求处理结束后再退出 | USR1 | 重新打开日志文件 |
5、nginx平滑升级及添加新功能配置
//下载功能包
[root@nginx ~]
[root@nginx ~]
Cloning into 'nginx_module_echo'...
remote: Enumerating objects: 80, done.
remote: Counting objects: 100% (80/80), done.
remote: Compressing objects: 100% (34/34), done.
remote: Total 80 (delta 37), reused 80 (delta 37), pack-reused 0
Receiving objects: 100% (80/80), 14.34 KiB | 4.78 MiB/s, done.
Resolving deltas: 100% (37/37), done.
//下载nginx新版本软件包
[root@nginx ~]
--2022-10-12 14:32:07-- https://nginx.org/download/nginx-1.22.0.tar.gz
Resolving nginx.org (nginx.org)... 52.58.199.22, 3.125.197.172, 2a05:d014:edb:5702::6, ...
Connecting to nginx.org (nginx.org)|52.58.199.22|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 1073322 (1.0M) [application/octet-stream]
Saving to: ‘nginx-1.22.0.tar.gz’
nginx-1.22.0.tar.gz 100%[================>] 1.02M 691KB/s in 1.5s
2022-10-12 14:32:10 (691 KB/s) - ‘nginx-1.22.0.tar.gz’ saved [1073322/1073322]
[root@nginx ~]
anaconda-ks.cfg nginx-1.20.2.tar.gz nginx_module_echo
nginx-1.20.2 nginx-1.22.0.tar.gz
//查看当前nginx版本和编译参数
[root@nginx ~]
nginx version: nginx/1.20.2
built by gcc 8.5.0 20210514 (Red Hat 8.5.0-10) (GCC)
built with OpenSSL 1.1.1k FIPS 25 Mar 2021
TLS SNI support enabled
configure arguments: --prefix=/usr/local/nginx --user=nginx --group=nginx --with-debug --with-http_ssl_module --with-http_realip_module --with-http_image_filter_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_stub_status_module --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log
//解压软件包并进入解压目录
[root@nginx ~]
[root@nginx ~]
//进行编译并添加上新功能
[root@nginx nginx-1.22.0]
[root@nginx nginx-1.22.0]
//编译完成
[root@nginx nginx-1.22.0]
auto CHANGES.ru configure html Makefile objs src
CHANGES conf contrib LICENSE man README
[root@nginx nginx-1.22.0]
objs/nginx: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=09dd11fc9d1ba5d4f04372eddc9a5cf3c0492571, with debug_info, not stripped
[root@nginx nginx-1.22.0]
nginx version: nginx/1.22.0
//备份后停掉老版本,复制新版本后启动升级完成
[root@nginx nginx-1.22.0]
/root/nginx-1.22.0
[root@nginx nginx-1.22.0]
nginx version: nginx/1.20.2
[root@nginx nginx-1.22.0]
[root@nginx nginx-1.22.0]
nginx version: nginx/1.22.0
二、location实战
在nginx中location分为两类:普通location和正则location。
普通 location ”是以“ = ”或“ ^~ ”为前缀或者没有任何前缀的 /uri/,包括“/”;“正则 location ”是以“ ~ ”或“ ~* ”为前缀的 /uri/ 。
那么如果一个 server 块中编写了多个 location 的时候,Nginx对于客户端请求匹配顺序如何呢?
官网说明如下:先匹配普通location,取的最大前缀匹配,再匹配正则location,如果匹配到则按照正则匹配,如果有多个正则可以匹配到,则按照第一个匹配结果处理,如果正则匹配失败则使用普通location的最大前缀匹配。Nginx也设置了几种机制可以打断这种顺序,分别是“^~ ”、“= ”或者location精确匹配。
简单的讲顺序如下:
首先普通location“=”精确匹配;
然后普通location的URL精确匹配;
然后普通location”^~"配置;
然后正则匹配;
然后其他普通location匹配;
最后“/”通用匹配
location 匹配的优先级(与location在配置文件中的顺序无关) = 精确匹配会第一个被处理。如果发现精确匹配,nginx停止搜索其他匹配。 普通字符匹配,正则表达式规则和长的块规则将被优先和查询匹配,也就是说如果该项匹配还需去看有没有正则表达式匹配和更长的匹配。
^~ 则只匹配该规则,nginx停止搜索其他匹配,否则nginx会继续处理其他location指令。 最后匹配理带有"“和”*"的指令,如果找到相应的匹配,则nginx停止搜索其他匹配;当没有正则表达式或者没有正则表达式被匹配的情况下,那么匹配程度最高的逐字匹配指令会被使用。
常用修饰符说明:
修饰符 | 功能 |
---|
= | 精确匹配 | ~ | 正则表达式模式匹配,区分大小写 | ~* | 正则表达式模式匹配,不区分大小写 | ^~ | 前缀匹配,类似于无修饰符的行为,也是以指定模块开始,不同的是,如果模式匹配,那么就停止搜索其他模式了,不支持正则表达式 | @ | 定义命名location区段,这些区段客户端不能访问,只可以由内部产生的请求来访问,如try_files或error_page等 |
案例说明一
location / {
echo "hello world";
}
location = / {
echo "web1";
}
[root@nginx ~]
web1
修饰符等号为精确匹配,优先级更高,所以此时访问的时web1
案例说明二
location = / {
echo "[ configuration A ]";
}
location / {
echo "[ configuration B ]";
}
location /documents/ {
echo "[ configuration C ]";
}
location ^~ /images/ {
echo "[ configuration D ]";
}
location ~* \.(gif|jpg|jpeg)$ {
echo "[ configuration E ]";
}
[root@nginx ~]
[ configuration A ]
[root@nginx ~]
[ configuration B ]
[root@nginx ~]
[ configuration C ]
[root@nginx ~]
[ configuration D ]
[root@nginx ~]
[ configuration E ]
/index.html访问到b:
a的/后面没有任何配置,不会匹配到,c、d、e的/后面都有目录位置,也不会匹配到,所以最后会返回到b,以为b没有任何通配符,优先级最低
/documents/document.html访问到c:
虽然document.html文件不存在,但是直接定位到了/documents/目录然后访问到c
/images/1.gif访问到d:
通配符为前缀匹配,其优先级要高于正则表达式
/documents/1.jpg访问到e:
通配符为正则表达式匹配,比另一个又相同定位目录的优先级要高
查找顺序和优先级:由高到底依次为
- 带有
= 的精确匹配优先 - 正则表达式按照他们在配置文件中定义的顺序
- 带有
^~ 修饰符的,开头匹配 - 带有
~ 或~* 修饰符的,如果正则表达式与URI匹配 - 没有修饰符的精确匹配
优先级次序如下:
( location = 路径 ) --> ( location ^~ 路径 ) --> ( location ~ 正则 ) --> ( location ~* 正则 ) --> ( location 路径 )
|