写点什么

Nginx 配置以及热升级

  • 2024-07-03
    福建
  • 本文字数:8325 字

    阅读完需:约 27 分钟

Nginx 详解


Nginx 与 Apache 一样,都是 web 服务器,但是 Nginx 比 Apache 多一些功能,比如 Nginx 可以做代理,可以做负载均衡……


1. Nginx 关键特性


  • 支持高并发单机 Nginx 可支持十万级别的并发连接,经过优化后可支持百万级别并发

  • 内存资源消耗低在同级 web 中,Nginx 占用的内存最少,一万非活跃的 http 长连接仅消耗 2.5M 内存

  • 高扩展性和 Apache 一样,Nginx 采用模块化设计,并支持非常多丰富的第三方模块

  • 高可靠性 Nginx 采用 master-worker 模式,如果 worker 出现故障,master 可以快速开启一个新的 worker 来提供服务


2. Nginx 配置

[root@ceph conf.d]# grep -Ev "^#|^$|#" /etc/nginx/nginx.conf |cat -n     1	user nginx;     2	worker_processes auto;     3	error_log /var/log/nginx/error.log;     4	pid /run/nginx.pid;     5	include /usr/share/nginx/modules/*.conf;     6	events {     7	    worker_connections 1024;     8	}     9	http {    10	    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '    11	                      '$status $body_bytes_sent "$http_referer" '    12	                      '"$http_user_agent" "$http_x_forwarded_for"';    13	    access_log  /var/log/nginx/access.log  main;    14	    sendfile            on;    15	    tcp_nopush          on;    16	    tcp_nodelay         on;    17	    keepalive_timeout   65;    18	    types_hash_max_size 4096;    19	    include             /etc/nginx/mime.types;    20	    default_type        application/octet-stream;    21	    include /etc/nginx/conf.d/*.conf;    22	    server {    23	        listen       80;    24	        listen       [::]:80;    25	        server_name  _;    26	        root         /usr/share/nginx/html;    27	        include /etc/nginx/default.d/*.conf;    28	        error_page 404 /404.html;    29	            location = /40x.html {    30	        }    31	        error_page 500 502 503 504 /50x.html;    32	            location = /50x.html {    33	        }    34	    }    35	}
复制代码


由于之前很详细的写过 Apache 的配置了,这里就说一下这俩服务之间的差异,nginx 的配置文件每行配置结束必须以分号;结尾


  1. Nginx 也可以配置启动的用户,默认为 nginx,可以修改

  2. Nginx 工作进程,默认为 auto(与 CPU 核心数保持一致),也可以手动修改

  3. 定义 nginx 的错误日志

这两个都是 Apache 服务里面也有的,这里就简答说一下


2.1 event

第六行 event 这个是指定 nginx 的工作模式,默认的,Apache 也有这个模式,这个段落里面的内容

events {worker_connections 1024; 指定单个进程的连接数}


2.2 http

这个段落里面就是一些 http 的配置


2.2.1 log_format

首先就是定义日志的格式 log_format,然后就是 access.log 这个就不细写


2.2.2 sendfile

sendfile on;这个代表高效传输,也就是可以将文件直接从磁盘传输到网络中,而不先读到内存


2.2.3 tcp_nopush

tcp_nopush on 立刻回应 tcp 的请求


2.2.4 tcp_nodelay

tcp_nodelay on 对于小数据包直接回应


2.2.5 keepalive_timeout

keepalive_timeout 65,这个通过名字就可以知道,是长连接的超时时间


2.2.6 include

我跳过了 types_hash_max_size,这个是 hash 散列表,我也不知道是干嘛的

include /etc/nginx/mime.types; 这里是载入 nginx 能够识别的类型,你可以打开这个文件去看这里面都定义了什么,打开就一目了然了


2.2.7 default_type

default_type application/octet-stream; 二进制的文件可以直接下载


2.2.8 server

server {listen 80;listen [::]:80;server_name _;root /usr/share/nginx/html;include /etc/nginx/default.d/*.conf;error_page 404 /404.html;location = /40x.html {}error_page 500 502 503 504 /50x.html;location = /50x.html {}}}
复制代码


这里的 server 对应的就是 Apache 的虚拟主机

listen 监听的端口,他这里默认监听了 2 个,一个是 IPv4,另一个是 IPv6

server_name:对外提供的服务名,也就是域名

root:网站根目录

include: 定义虚拟主机的特性,可以将一些其他的特性卸载 conf.d/下之后他会自动加载配置

error_page 404 :这个是错误页,当 404 出现的时候,nginx 会返回网站根目录下的 404.html

locatioin: 这个是 nginx 的重头戏,叫做路由规则,你可以将路由策略写在这,他就会根据你的策略来处理流量,这个我们稍后细讲

error_page 500 当服务发生 500 以上的错误的时候,nginx 返回网站根目录下的 50x.html


3. 配置 Nginx 虚拟主机


Nginx 也支持 3 种虚拟主机,与 Apache 一样

  • 基于端口的虚拟主机

  • 基于 IP 的虚拟主机

  • 基于域名的虚拟主机


3.1 基于端口


虚拟主机我们可以在 conf.d 下进行配置

[root@ceph conf.d]# vim virthost.confserver {  listen 81;  root /web1;} server {  listen 82;  root /web2;}[root@ceph conf.d]# echo 81 > /web1/index.html[root@ceph conf.d]# echo 82 > /web2/index.html[root@ceph conf.d]# systemctl restart nginx[root@ceph conf.d]# curl localhost:8282[root@ceph conf.d]# curl localhost:8181
复制代码


基于端口的虚拟主机这样就配好了


3.2 基于 IP


首先配置一个临时 IP

[root@ceph conf.d]# sudo ip addr add 192.168.1.100/24 dev ens33[root@ceph conf.d]# ip a |grep 192.168.1.100    inet 192.168.1.100/24 scope global ens33
复制代码


虚拟的 IP 就配置好了,接下来配置 nginx

[root@ceph conf.d]# vim virthost.conf server {  listen 81;  root /web1;} server {  listen 82;  root /web2;} server {  listen 192.168.200.210:80;  root /web3;} server {  listen 192.168.1.100:80;  root /web4;}
复制代码


然后我们创建对应的网站根目录以及 index.html

[root@ceph conf.d]# echo 192.168.200.210 > /web3/index.html[root@ceph conf.d]# echo 192.168.1.100 > /web4/index.html[root@ceph conf.d]# systemctl restart nginx[root@ceph conf.d]# curl 192.168.200.210192.168.200.210[root@ceph conf.d]# curl 192.168.1.100192.168.1.100
复制代码


可以看到,通过不同的 ip 访问回显是不同的内容


3.3 基于域名

[root@ceph conf.d]# vim virthost.conf server {  listen 80;  server_name test.com;  root /web5;} server {  listen 80;  server_name example.com;  root /web6;}
复制代码


创建根目录以及重启服务,还需要做 hosts 解析

[root@ceph conf.d]# echo web5 > /web5/index.html[root@ceph conf.d]# echo web6 > /web6/index.html[root@ceph conf.d]# systemctl restart nginx[root@ceph conf.d]# vim /etc/hosts192.168.200.210 test.com192.168.200.210 example.com[root@ceph conf.d]# curl test.comweb5[root@ceph conf.d]# curl example.comweb6
复制代码


这样也是可以访问到对应的文件的


4. Location


这个是 nginx 最重要的配置了,在 Apache 里面访问控制是用DirectoryFiles来做的,那么在 nginx 里面的做法就是 location 了


4.1 拒绝访问


我不想你访问网站根目录下的/test.html,那么我的路由规则就应该这样写,还是在虚拟主机里定义

[root@ceph conf.d]# vim virthost.conf server {  listen 80;  server_name test.com;  root /web5;  location /test.html {    return 403;  }}
复制代码


我们来创建这个 test.html 文件,并尝试访问

[root@ceph conf.d]# echo "test file" > /web5/test.html[root@ceph conf.d]# systemctl restart nginx[root@ceph conf.d]# curl 192.168.200.210/test.html<html><head><title>403 Forbidden</title></head><body><center><h1>403 Forbidden</h1></center><hr><center>nginx</center></body></html>
复制代码


看到了吗?他就返回的是 403,这样做之后,访问 test.html 的请求就被拒绝掉了,但是如果我们需要拒绝掉所有以 test 开头的文件呢?也是跟 Apache 一样使用 * 号吗?不,Nginx 是另外的做法


4.2 拒绝访问 test 开头的所有文件

[root@ceph conf.d]# vim virthost.confserver {  listen 80;  server_name test.com;  root /web5;  location ^~ /test {    return 403;  }}[root@ceph conf.d]# echo test > /web5/test.1[root@ceph conf.d]# echo test > /web5/test.2[root@ceph conf.d]# systemctl restart nginx
复制代码


我们在/web5 下创建了 test.1 和 test.2 包括之前创建的 test.html 一共有 3 个 test 开头的文件,那我们现在来尝试访问一下

[root@ceph conf.d]# curl 192.168.200.210/test.html -I HTTP/1.1 403 ForbiddenServer: nginxDate: Tue, 02 Jul 2024 09:09:49 GMTContent-Type: text/htmlContent-Length: 146Connection: keep-alive [root@ceph conf.d]# curl 192.168.200.210/test.1 -I HTTP/1.1 403 ForbiddenServer: nginxDate: Tue, 02 Jul 2024 09:09:56 GMTContent-Type: text/htmlContent-Length: 146Connection: keep-alive[root@ceph conf.d]# curl 192.168.200.210/test.xxx -I HTTP/1.1 403 ForbiddenServer: nginxDate: Tue, 02 Jul 2024 09:10:12 GMTContent-Type: text/htmlContent-Length: 146Connection: keep-alive
复制代码


看到了吧,尽管我们访问一个不存在的文件,按道理应该是返回 404,但是这个文件是以 test 开头,那么他会被拒绝访问,不管这个文件存不存在


但是这样配置,只能拒绝掉以 test 开头的,我如果访问的是 Test,那么他就不会被拒绝了

[root@ceph conf.d]# curl 192.168.200.210/Test -I HTTP/1.1 404 Not FoundServer: nginxDate: Tue, 02 Jul 2024 09:12:57 GMTContent-Type: text/htmlContent-Length: 146Connection: keep-alive
复制代码


对吧,因为我们没有这个资源,所以他返回了 404,而不是 403,说明没有被拒绝,如果想忽略大小写,可以这样做


4.3 忽略大小写

[root@ceph conf.d]# vim virthost.conf server {  listen 80;  server_name test.com;  root /web5;  location ~* /test {    return 403;  }}
复制代码


只需要将^~这个地方改为~*,我们来访问一下看看

[root@ceph conf.d]# curl -I 192.168.200.210/testHTTP/1.1 403 ForbiddenServer: nginxDate: Tue, 02 Jul 2024 09:15:17 GMTContent-Type: text/htmlContent-Length: 146Connection: keep-alive [root@ceph conf.d]# curl -I 192.168.200.210/TestHTTP/1.1 403 ForbiddenServer: nginxDate: Tue, 02 Jul 2024 09:15:21 GMTContent-Type: text/htmlContent-Length: 146Connection: keep-alive [root@ceph conf.d]# curl -I 192.168.200.210/TEstHTTP/1.1 403 ForbiddenServer: nginxDate: Tue, 02 Jul 2024 09:15:23 GMTContent-Type: text/htmlContent-Length: 146Connection: keep-alive
复制代码


现在的配置,不管你的大写的 TEST 还是小写的 test,亦或者是大小写都有的,一律都会被拒绝访问


4.4 反向代理


我们还可以通过 location 来做反向代理,比如你现在访问我网站下的/那我就直接给你代理到baidu.com去,你要搜索啥你自己去搜吧,你以为这个百度是我给你提供的,其实不然,我是把你的请求给到百度了

[root@ceph conf.d]# vim virthost.conf server {  listen 80;  server_name test.com;  root /web5;  location  / {    proxy_pass https://www.baidu.com;  }}
复制代码



看到了吗?这是货真价实的百度哦,可以搜索内容的



怎么样,你现在就搭建了一个反向代理,客户端只知道他访问的是 192.168.200.210 这个 IP,他并不知道你把他的请求给了百度,所以客户端会以为你就是百度


5. 配置 https


nginx 配置 https 的方式其实跟 Apache 是差不多的,直接告诉他你的密钥文件放在哪,有 2 种方式可以配置 https,第一种是直接改主配置文件,主配置文件里是有 https 段落的,只不过默认被注释了。


第二种方式就是自己写一个虚拟主机,我这里直接修改主配置文件

[root@ceph nginx]# vim nginx.conf    server {        listen       443 ssl http2;        listen       [::]:443 ssl http2;        server_name  _;        root         /usr/share/nginx/html;         ssl_certificate "/etc/nginx/server.crt";        ssl_certificate_key "/etc/nginx/server.key";         # Load configuration files for the default server block.        include /etc/nginx/default.d/*.conf;         error_page 404 /404.html;            location = /40x.html {        }         error_page 500 502 503 504 /50x.html;            location = /50x.html {        }    }
复制代码


将这一段的注释全部给放开,ssl 只保留需要的这 2 行内容,然后将证书地址改为你的证书的实际目录就可以了,然后重启 nginx 服务


6. Nginx 热升级


Nginx 热升级是指可以做到不停机升级 Nginx 的版本,yum 安装的 Nginx 是不支持热升级的,如果想要热升级 Nginx,那么你的 Nginx 必须是源码编译安装的


编译安装流程:

  1. 下载源码包

  2. 解压源码包

  3. 执行预编译 ./configure

  4. 编译 make

  5. 编译安装 make install

这是编译安装的流程


在执行到第 5 步的时候,他就会将编译好的二进制文件放在 objs 目录下,就是依赖于这个目录下的二进制文件我们才可以做到版本共存


nginx 的热升级原理主要依赖于以下几个关键步骤:


  1. 启动新版本的 nginx 进程:在进行热升级时,首先启动一个新版本的 nginx 进程,这个进程会使用新的配置文件和程序文件。

  2. 旧版本 nginx 进程继续服务:启动新版本 nginx 进程后,旧版本的 nginx 进程仍然继续运行,继续处理客户端的请求。

  3. 新旧版本的协调切换:新版本 nginx 进程启动后,会逐渐接管处理新的客户端请求。同时,旧版本 nginx 进程在处理完当前已有的请求后逐渐退出。

  4. 共享监听端口:新旧版本的 nginx 进程可以通过共享监听的网络端口来实现平滑过渡。在大多数情况下,nginx 会采用 SO_REUSEPORT 选项来允许多个进程监听同一个端口。

  5. 无缝切换:由于新旧版本 nginx 进程可以并行运行并共享端口,因此在没有中断服务的情况下完成从旧版本到新版本的切换,实现了热升级。


6.1 环境清理


如果你已经使用 yum 安装了,先卸载 nginx

[root@ceph ~]# yum remove -y nginx
复制代码


6.2 编译安装旧版本 Nginx


Nginx下载地址


在这里面找一个相对旧一点的版本,我这里下载一个 1.26.1,然后将 1.26.1 升级到 1.27.0

[root@ceph ~]# cd /opt/[root@ceph opt]# wget https://nginx.org/download/nginx-1.26.1.tar.gz[root@ceph opt]# tar -zxf nginx-1.26.1.tar.gz [root@ceph opt]# cd nginx-1.26.1/[root@ceph nginx-1.26.1]# lsauto     CHANGES.ru  configure  html     man     srcCHANGES  conf        contrib    LICENSE  README[root@ceph nginx-1.26.1]# ./configure --prefix=/usr/local/nginx
复制代码


在这里执行的时候他可能会报错,根据他的报错你安装相对应的软件包就好了

Configuration summary  + using system PCRE2 library  + OpenSSL library is not used  + using system zlib library   nginx path prefix: "/usr/local/nginx"  nginx binary file: "/usr/local/nginx/sbin/nginx"  nginx modules path: "/usr/local/nginx/modules"  nginx configuration prefix: "/usr/local/nginx/conf"  nginx configuration file: "/usr/local/nginx/conf/nginx.conf"  nginx pid file: "/usr/local/nginx/logs/nginx.pid"  nginx error log file: "/usr/local/nginx/logs/error.log"  nginx http access log file: "/usr/local/nginx/logs/access.log"  nginx http client request body temporary files: "client_body_temp"  nginx http proxy temporary files: "proxy_temp"  nginx http fastcgi temporary files: "fastcgi_temp"  nginx http uwsgi temporary files: "uwsgi_temp"  nginx http scgi temporary files: "scgi_temp"
复制代码


他执行完之后会这样输出就是没有错误,可以继续往下做

[root@ceph nginx-1.26.1]# make -j 4
复制代码


  • -j 指定并行编译的进程数为 4

[root@ceph nginx-1.26.1]# make install
复制代码


6.3 启动旧版 nginx


由于我们指定的安装路径是/usr/local/nginx,所以他会在这个目录下生成一个 sbin 的目录,这个目录里面有一个二进制文件 nginx,执行他就可以启动 nginx

[root@ceph nginx-1.26.1]# cd /usr/local/nginx/sbin/[root@ceph sbin]# ./nginx [root@ceph sbin]# curl -I 192.168.200.210 HTTP/1.1 200 OKServer: nginx/1.26.1Date: Tue, 02 Jul 2024 11:27:47 GMTContent-Type: text/htmlContent-Length: 615Last-Modified: Tue, 02 Jul 2024 11:25:09 GMTConnection: keep-aliveETag: "6683e395-267"Accept-Ranges: bytes
复制代码


在 server 这一栏我们可以看见 nginx 的版本是 1.26.1


6.4 下载新版 nginx


现在我们将 nginx 升级到 1.27.0

[root@ceph sbin]# cd /opt/[root@ceph opt]# wget https://nginx.org/download/nginx-1.27.0.tar.gz[root@ceph opt]# tar -zxf nginx-1.27.0.tar.gz[root@ceph opt]# cd nginx-1.27.0/[root@ceph nginx-1.27.0]# ./configure --prefix=/usr/local/nginx [root@ceph nginx-1.27.0]# make -j 4
复制代码


这里非常需要注意,一定不要去执行make install了,因为执行这个命令的话会将原来的 nginx 全部覆盖掉,我们只需要替换掉 nginx 的二进制文件就好了


我们来到 objs 目录

[root@ceph nginx-1.27.0]# lsauto     CHANGES.ru  configure  html     Makefile  objs    srcCHANGES  conf        contrib    LICENSE  man       README[root@ceph nginx-1.27.0]# cd objs/[root@ceph objs]# lsautoconf.err  nginx    ngx_auto_config.h   ngx_modules.c  srcMakefile      nginx.8  ngx_auto_headers.h  ngx_modules.o
复制代码


这里面就有一个 nginx 的二进制文件,先别着急启动,我们先将老版本的 nginx 二进制文件进行备份

[root@ceph objs]# cp /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.bak[root@ceph objs]# cd /usr/local/nginx/sbin/[root@ceph sbin]# cp /opt/nginx-1.27.0/objs/nginx .cp: overwrite './nginx'? y[root@ceph sbin]# ./nginx -vnginx version: nginx/1.27.0
复制代码


现在我们就已经将 1.27.0 的二进制文件拷贝到这个地方来了,接下来我们需要将 nginx1.27.0 也给启动起来。


你这时候可能会有疑问,80 端口不是已经被老版本的 nginx 给占用了吗,我现在在启动不会报错吗?答案肯定是会,所以我们在启动之前还需要进行一个操作,给老版本的 nginx'发送一个USR2的信号

[root@ceph sbin]# ps -ef |grep nginxroot       46538       1  0 19:27 ?        00:00:00 nginx: master process ./nginxnobody     46539   46538  0 19:27 ?        00:00:00 nginx: worker processroot       49680   15412  0 19:36 pts/0    00:00:00 grep --color=auto nginx
复制代码


我们查到 nginx master 的进程 id 是 46538,接下来就是发信号了

[root@ceph sbin]# kill -s USR2 46538# 然后我们再启动nginx[root@ceph sbin]# ps -ef |grep nginxroot       46538       1  0 19:27 ?        00:00:00 nginx: master process ./nginxnobody     46539   46538  0 19:27 ?        00:00:00 nginx: worker processroot       49708   46538  0 19:37 ?        00:00:00 nginx: master process ./nginxnobody     49709   49708  0 19:37 ?        00:00:00 nginx: worker processroot       49761   15412  0 19:38 pts/0    00:00:00 grep --color=auto nginx
复制代码


看到了吗?除了老版本的 46538 之外,还有一个新的 nginx master 进程,49708


尝试访问

[root@ceph sbin]# curl 192.168.200.210 -I HTTP/1.1 200 OKServer: nginx/1.27.0Date: Tue, 02 Jul 2024 11:39:04 GMTContent-Type: text/htmlContent-Length: 615Last-Modified: Tue, 02 Jul 2024 11:25:09 GMTConnection: keep-aliveETag: "6683e395-267"Accept-Ranges: bytes
复制代码


看,他现在处理连接的版本就是 1.27.0 了,如果老版本的 nginx 还有连接在处理的话也是不会受到影响的,等我们确认没问题之后我们只需要将老版本给 kill 掉

[root@ceph sbin]# kill 46538[root@ceph sbin]# ps -ef |grep nginxroot       49708       1  0 19:37 ?        00:00:00 nginx: master process ./nginxnobody     49709   49708  0 19:37 ?        00:00:00 nginx: worker processroot       49913   15412  0 19:40 pts/0    00:00:00 grep --color=auto nginx
复制代码


这个时候老版本就成功退役了,所有的连接都交由新版本的 nginx 来处理,我们的热升级就搞定了


文章转载自:FuShudi

原文链接:https://www.cnblogs.com/fsdstudy/p/18280454

体验地址:http://www.jnpfsoft.com/?from=infoq

用户头像

还未添加个人签名 2023-06-19 加入

还未添加个人简介

评论

发布
暂无评论
Nginx配置以及热升级_nginx_不在线第一只蜗牛_InfoQ写作社区