nginx

目录

HTTP介绍

HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于从万维网(WWW:World Wide Web )服务器传输超文本到本地浏览器的传送协议。

HTTP是一个基于TCP/IP通信协议来传递数据(HTML 文件, 图片文件, 查询结果等)。
HTTP 工作原理

1.客户端发起请求
当用户在浏览器中输入URL或者点击一个链接时,浏览器作为HTTP客户端会向指定的服务器发送HTTP请求。这个请求包括以下几个部分:

请求行:包含请求方法(如GET、POST等)、资源路径(URL中的路径部分)和HTTP版本。
请求头:提供关于请求或客户端的信息,比如接受的内容类型、语言、浏览器类型等。
请求体(可选):对于某些请求方法(如POST),可能包含要发送给服务器的数据。


2.服务器处理请求并返回响应
服务器接收到请求后,解析请求内容,根据请求的资源路径找到对应的资源,并执行必要的操作,构建HTTP响应,该响应也由几部分组成:

状态行:包含HTTP版本、状态码(表示请求的结果,如200表示成功)和简短的状态描述。
响应头:提供关于响应或服务器的信息,比如内容长度、内容类型、缓存指令等。
响应体:包含实际要传输给客户端的资源数据,如HTML文档、图片、JSON数据等。

3.响应传输到客户端
一旦响应被构建好,服务器就会将它通过网络传回给客户端。客户端接收响应后,根据响应内容采取相应的行动,比如渲染页面、显示错误信息等。


简单来说:
HTTP协议工作于客户端-服务端架构上。浏览器作为HTTP客户端通过URL向HTTP服务端即WEB服务器发送所有请求。

Web服务器有:Nginx,Apache服务器,IIS服务器(Internet Information Services)等。

Web服务器根据接收到的请求后,向客户端发送响应信息。

HTTP默认端口号为80,但是也可以改为其他端口。


HTTP三点注意事项:
- HTTP是无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。

- HTTP是媒体独立的:这意味着,只要客户端和服务器知道如何处理的数据内容,任何类型的数据都可以通过HTTP发送。客户端以及服务器指定使用适合的MIME-type内容类型。

- HTTP是无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息则它必须重传。

HTTP 请求访问的完整过程

1、建立连接:接收或拒绝连接请求

2、接收请求:接收客户端请求报文中对某资源的一次请求的过程Web访问响应模型(Web I/O)
- 单进程I/O模型:启动一个进程处理用户请求,而且一次只处理一个,多个请求被串行响应
- 多进程I/O模型:并行启动多个进程,每个进程响应一个连接请求
- 复用I/O结构:启动一个进程,同时响应N个连接请求
- 复用的多进程I/O模型:启动M个进程,每个进程响应N个连接请求,同时接收M*N个请求

3、处理请求:服务器对请求报文进行解析,并获取请求的资源及请求方法等相关信息,根据方法,资源,首部和可选的主体部分对请求进行处理
常用请求Method: GET、POST、HEAD、PUT、DELETE、TRACE、OPTIONS

4、访问资源:
 服务器获取请求报文中请求的资源web服务器,即存放了web资源的服务器,负责向请求者提供对方请求的静态资源,或动态运行后生成的资源

5、构建响应报文:
 一旦Web服务器识别除了资源,就执行请求方法中描述的动作,并返回响应报文。响应报文中 包含有响应状态码、响应首部,如果生成了响应主体的话,还包括响应主体。
响应实体:如果事务处理产生了响应主体,就将内容放在响应报文中回送过去。响应报文中通常包括:
- 描述了响应主体MIME类型的Content-Type首部
- 描述了响应主体长度的Content-Length
- 实际报文的主体内容
URL重定向:web服务构建的响应并非客户端请求的资源,而是资源另外一个访问路径
MIME类型: Web服务器要负责确定响应主体的MIME类型。多种配置服务器的方法可将MIME类型与资源管理起来

6、发送响应报文

7、记录日志

GET传递数据实例

客户端请求:
# curl -v http://www.testpm.cn
Connected to www.testpm.cn (47.244.247.240) port 80 (#0)
> GET /hello.txt HTTP/1.1   # 请求方式与版本协议。
> User-Agent: curl/7.29.0   #用什么客户端访问
> Host: www.testpm.cn  #主机名,域名。主机和端口号,
> Accept: */*  #匹配什么文件类型,“*” 是通用匹配。匹配所有类型

服务端响应:
< HTTP/1.1 200 OK       #请求返回的状态码
< Server: nginx/1.16.0  #请求的服务和版本号
< Date: Thu, 04 Jul 2024 08:19:40 GMT #当前时间,北京时间为GMT+8小时
< Content-Type: text/plain #mime类型,test/plain:普通文本,比如image/png...、video
< Content-Length: 12 #内容的长度
< Last-Modified: Thu, 04 Jul 2024 08:13:25 GMT #最后修改时间
< Connection: keep-alive  #是否支持长连接
< ETag: "5d1db525-c"  #标识,每次访问如果与最开始的值一样返回304否则校验不一致返回200
< Accept-Ranges: bytes #接受的范围单位

HTTP 状态码
当浏览者访问一个网页时,浏览者的浏览器会向网页所在服务器发出请求。当浏览器接收并显示网页前,此网页所在的服务器会返回一个包含HTTP状态码的信息头(server header)用以响应浏览器的请求。
下面是常见的HTTP状态码:

200 - 请求成功
301 - 资源(网页等)被永久转移到其它URL
404 - 服务器无法找到客户端请求的资源
500 - 服务器内部错误;一般是连接数据库失败,rewrite死循环
403 - 请求被禁止;一般是因为权限错误或主页文件不存在
502 - Bad Gateway;一般是后端服务端口没有打开,或后端服务不可用或关机
504 - 网关连接超时;一般是服务端口虽然打开,但服务返回结果时间过长
401 - 需要输入账号和密码认证方能访问资源

nginx介绍

Nginx 是一个轻量级,高性能的 HTTP 和 反向代理 服务,也是一个IMAP/POP3/SMTP服务。因它的稳定性、丰富的功能集、示例配置文件和低系统资源的消耗而闻名。
nginx的其它的二次发行版:

  • Tengine

由淘宝网发起的Web服务器项目。它在Nginx的基础上,针对大访问量网站的需求,添加了很多高
级功能和特性。Tengine的性能和稳定性已经在大型的网站如淘宝网,天猫商城等得到了很好的检
验。它的最终目标是打造一个高效、稳定、安全、易用的Web平台。从2011年12月开始,Tengine成为一个开源项目。
官网: http://tengine.taobao.org/

  • OpenResty

基于 Nginx 与 Lua 语言的高性能 Web 平台, 章亦春团队开发
官网:http://openresty.org/cn/

Nginx 功能介绍

* 静态的web资源服务器html,图片,js,css,txt等静态资源
* http/https协议的反向代理
* 结合FastCGI/uWSGI/SCGI等协议反向代理动态资源请求
* tcp/udp协议的请求转发(反向代理)
* imap4/pop3协议的反向代理

基础特性

* 模块化设计,较好的扩展性
* 高可靠性
* 支持热部署:不停机更新配置文件,升级版本,更换日志文件
* 低内存消耗:10000个keep-alive连接模式下的非活动连接,仅需2.5M内存
* event-driven,aio,mmap,sendfile

nginx的优势

* 高并发,高性能
* 高可靠---可以7*24小时不间断运行
* 可扩展性强--模块化设计,使得添加模块非常的平稳。
* 热部署--可以在不停止服务器的情况下升级nginx
* BSD许可证--nginx不止开源免费的我们还可以更具实际需求进行定制修改源代码

Nginx作为Web和反向代理服务器的优势
作为Web 服务器:相比 Apache,Nginx 使用更少的资源,支持更多的并发连接,体现更高的效率,这点使 Nginx 尤其受到虚拟主机提供商的欢迎。能够支持高达 50,000 个并发连接数的响应。

作为负载均衡服务器:可以进行自定义配置,支持虚拟主机,支持URL重定向,支持网络监控,支持流媒体传输等。Nginx 既可以在内部直接支持 Rails 和 PHP,也可以支持作为 HTTP代理服务器 对外进行服务。Nginx 用 C 编写, 不论是系统资源开销还是 CPU 使用效率都比 Perlbal 要好的多。

作为邮件代理服务器: Nginx 同时也是一个非常优秀的邮件代理服务器(最早开发这个产品的目的之一也是作为邮件代理服务器)。

Nginx 安装非常的简单,配置文件 非常简洁(还能够支持perl语法),Bugs非常少的服务器: Nginx 启动特别容易,并且几乎可以做到7*24不间断运行,即使运行数个月也不需要重新启动。还能够在不间断服务的情况下进行软件版本的升级。

Nginx 启动和 HTTP 连接建立

* Nginx 启动时,Master 进程,加载配置文件
* Master 进程,初始化监听的 socket
* Master 进程,fork 出多个 Worker 进程
* Worker 进程,竞争新的连接,获胜方通过三次握手,建立 Socket 连接,并处理请求

HTTP 处理过程
Nginx是一种高性能的Web服务器,可以处理大量的并发HTTP请求。Nginx在处理HTTP请求时采用了高效的事件驱动模型,使用异步IO等技术实现了高性能、低延迟的请求处理。

在处理HTTP请求时,Nginx会通过以下步骤进行处理:

  • 读取请求:当客户端发送HTTP请求时,Nginx会使用socket接口读取请求,包括请求头和请求体。
  • 解析请求:Nginx会对请求进行解析,包括解析请求方法、请求路径、查询参数等信息。Nginx还会对请求头进行解析,包括解析Host、User-Agent、Content-Type等字段,这些信息可以在后续处理中使用。
  • 处理请求:根据解析得到的请求信息,Nginx会进行请求处理。比如,如果请求路径对应的是一个静态文件,Nginx会直接返回文件内容;如果请求路径对应的是一个动态页面,Nginx会将请求转发给对应的后端应用服务器。
  • 处理请求体:如果请求包含请求体,Nginx会将请求体读取到内存中,以供后续处理使用。
  • 处理响应:当请求处理完成后,Nginx会根据处理结果生成响应,并发送给客户端。Nginx会将响应头和响应体一起发送给客户端,响应头中包含响应状态码、响应头字段等信息。
  • 关闭连接:当请求处理完成后,Nginx会关闭连接,释放资源,等待下一个请求。

Nginx 模块介绍
nginx 有多种模块

  • 核心模块:是 Nginx 服务器正常运行必不可少的模块,提供错误日志记录 、配置文件解析 、事件驱动机制 、进程管理等核心功能
  • 标准HTTP模块:提供 HTTP 协议解析相关的功能,比如: 端口配置 、 网页编码设置 、 HTTP响应头设置等
  • 可选HTTP模块:主要用于扩展标准的 HTTP 功能,让 Nginx 能处理一些特殊的服务,比如: Flash 多媒体传输 、解析 GeoIP 请求、 网络传输压缩 、 安全协议 SSL 支持等
  • 邮件服务模块:主要用于支持 Nginx 的 邮件服务 ,包括对 POP3 协议、 IMAP 协议和 SMTP协议的支持
  • Stream服务模块: 实现反向代理功能,包括TCP协议代理
  • 第三方模块:是为了扩展 Nginx 服务器应用,完成开发者自定义功能,比如: Json 支持、 Lua 支持等
  • nginx高度模块化,但其模块早期不支持DSO机制;1.9.11 版本支持动态装载和卸载

模块分类:

核心模块:core module
标准模块:
 HTTP 模块: ngx_http_*
 HTTP Core modules   #默认功能
 HTTP Optional modules #需编译时指定
 Mail 模块: ngx_mail_*
 Stream 模块 ngx_stream_*

nginx安装

Nginx 分为社区版和商业版,一般是社区版
Nginx版本:

  • Mainline version 主要开发版本,一般为奇数版本号,比如1.19
  • Stable version 当前最新稳定版,一般为偶数版本,如:1.20
  • Legacy versions 旧的稳定版,一般为偶数版本,如:1.18

安装方式:

  • Nginx安装可以使用yum或源码安装,但是推荐使用源码编译安装,编译安装可以更方便自定义相关路径,使用源码编译可以自定义相关功能,更方便业务的上的使用
  • yum/apt的系统仓库版本比较旧(包安装)
  • docker 容器直接运行

包安装
在新计算机上首次安装nginx之前,需要设置nginx软件包存储库。然后就可以从存储库安装和更新nginx。
官方包链接:
http://nginx.org/en/linux_packages.html
官方 yum 源链接:
http://nginx.org/en/linux_packages.html#RHEL-CentOS

[root@centos8 ~]#yum install yum-utils -y

[root@centos8 ~]#cat /etc/yum.repos.d/nginx.repo
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=0
enabled=1

#查看版本信息
[root@centos8 ~]#dnf info nginx

#安装指定版本
[root@centos8 ~]#yum -y install nginx-1.18.0

编译安装

#安装依赖包
[root@centos8 ~]#yum -y install gcc pcre-devel openssl-devel zlib-devel
[root@rocky8 ~]#yum -y install gcc make gcc-c++ libtool pcre pcre-devel zlib zlib-devel openssl openssl-devel perl-ExtUtils-Embed

#创建用户和组
[root@centos8 ~]#useradd -r -s /sbin/nologin nginx

[root@centos8 ~]#cd /usr/local/src/
#到官网下载源码
[root@centos8 src]#wget http://nginx.org/download/nginx-1.18.0.tar.gz
[root@centos8 src]#tar xf nginx-1.18.0.tar.gz 
[root@centos8 src]#cd nginx-1.18.0/

#可以自定义需要编译的模块
[root@centos8 nginx-1.18.0]#./configure --prefix=/apps/nginx \
--user=nginx \
--group=nginx \
--with-http_ssl_module \
--with-http_v2_module \
--with-http_realip_module \
--with-http_stub_status_module \
--with-http_gzip_static_module \
--with-pcre \
--with-stream \
--with-stream_ssl_module \
--with-stream_realip_module

[root@centos8 nginx-1.18.0]#make && make install

#修改权限
[root@centos8 nginx-1.18.0]#chown -R nginx.nginx /apps/nginx

验证版本及编译参数

[root@centos8 nginx-1.18.0]#ls /apps/nginx/sbin/nginx

[root@centos8 nginx-1.18.0]#ln -s /apps/nginx/sbin/nginx /usr/sbin/
#查看版本
[root@centos8 ~]#nginx -v
nginx version: nginx/1.18.0

#查看编译参数
[root@centos8 ~]#nginx -V
nginx version: nginx/1.18.0
built by gcc 8.3.1 20191121 (Red Hat 8.3.1-5) (GCC) 
built with OpenSSL 1.1.1c FIPS  28 May 2019
TLS SNI support enabled
configure arguments: --prefix=/apps/nginx --user=nginx --group=nginx --withhttp_ssl_module --with-http_v2_module --with-http_realip_module --withhttp_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream
--with-stream_ssl_module --with-stream_realip_module

nginx完成安装以后的四个主要目录

  • conf:保存nginx所有的配置文件,其中nginx.conf是nginx服务器的最核心最主要的配置文件,其他的.conf则是用来配置nginx相关的功能的,例如fastcgi功能使用的是fastcgi.conf和fastcgi_params两个文件,配置文件一般都有一个样板配置文件,是以.default为后缀,使用时可将其复制并将default后缀去掉即可。
  • html目录中保存了nginx服务器的web文件,但是可以更改为其他目录保存web文件,另外还有一个50x的web文件是默认的错误页面提示页面。
  • logs:用来保存nginx服务器的访问日志错误日志等日志,logs目录可以放在其他路径,比如/var/logs/nginx里面。
  • sbin:保存nginx二进制启动脚本,可以接受不同的参数以实现不同的功能。
[root@centos8 nginx-1.18.0]#ll /apps/nginx/
total 0
drwxr-xr-x 2 root root 333 Sep 22 12:49 conf
drwxr-xr-x 2 root root  40 Sep 22 12:49 html
drwxr-xr-x 2 root root   6 Sep 22 12:49 logs
drwxr-xr-x 2 root root  19 Sep 22 12:49 sbin

nginx启动方法

1.
[root@centos8 ~]# nginx
[root@centos8 ~]# nginx -s stop

2.
[root@centos8 ~]# systemctl start nginx
[root@centos8 ~]# systemctl stop nginx

注意:两种方法不可混用,第二种需要配置好启动文件才可以使用

nginx配置文件

创建Nginx自启动文件

#编译安装是nginx是没有nginx.service文件的
[root@centos8 ~]#vim /lib/systemd/system/nginx.service 
[Unit]
Description=nginx - high performance web server
Documentation=http://nginx.org/en/docs/
After=network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target
[Service]
Type=forking
#指定pid文件的目录,默认在logs目录下,可选配置
PIDFile=/apps/nginx/logs/nginx.pid
ExecStart=/apps/nginx/sbin/nginx -c /apps/nginx/conf/nginx.conf
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s TERM $MAINPID
LimitNOFILE=100000
[Install]
WantedBy=multi-user.target

[root@centos8 ~]#systemctl daemon-reload 
[root@centos8 ~]#systemctl enable --now nginx

Nginx 配置文件

# 全局参数设置
user nginx;  #设置nginx使用的用户
worker_processes  4;          #设置nginx启动进程的数量,一般设置成与逻辑cpu数量相同 
error_log  logs/error.log;    #指定错误日志 
pid        /var/run/nginx.pid; 
events { 
    worker_connections  1024; #设置一个进程的最大并发连接数 
}
# http 服务相关设置 
http { 
    include      mime.types; #关联mime类型,关联资源的媒体类型
    default_type  application/octet-stream; #根据文件的后缀来匹配相应的MIME类型
#MIME类型,浏览器一般会提示下载
#types {
#   text/html html;
#   image/gif gif;
#   image/jpeg jpg;
#}
    log_format  main  'remote_addr - remote_user [time_local] "request" '
                      'status body_bytes_sent "$http_referer" '
                      '"http_user_agent" "http_x_forwarded_for"'; 
    access_log  /var/log/nginx/access.log  main;    #设置访问日志的位置和格式 
    sendfile          on; #用于开启文件高效传输模式,一般设置为on,若nginx是用来进行磁盘IO负载应用时,可以设置为off,降低系统负载
    tcp_nopush        on;      # 减少网络报文段数量,当有数据时,先别着急发送, 确保数据包已经装满数据, 避免了网络拥塞
    tcp_nodelay       on;      # 提高I/O性能,确保数据尽快发送, 提高可数据传输效率 
    
    gzip              on;      #是否开启gzip压缩,将注释去掉开启 
    keepalive_timeout  65;     #设置长连接的超时时间,请求完成之后还要保持连接多久,
# 虚拟服务器的相关设置 
    server { 
        listen      80;        #设置监听的端口 
        server_name  localhost;        #设置绑定的主机名、域名或ip地址 
        charset koi8-r;        # 设置编码字符 
        location / { 
            root  /var/www/nginx;           #设置服务器默认网站的根目录位置,需要手动创建
            index  index.html index.htm;    #设置默认打开的文档 
            } 
        error_page  500 502 503 504  /50x.html; #设置错误信息返回页面 
        location = /50x.html { 
            root  html;        #这里的绝对位置是/usr/local/nginx/html
        } 
    } 

include /apps/nginx/conf.d/*.conf   #导入其他路径的配置文件
 }
#1.nginx.conf的组成:nginx.conf一共由三部分组成,分别为:全局块、events块、http块。在http块中又包含http全局块、多个server块。每个server块中又包含server全局块以及多个location块。在统一配置块中嵌套的配置快,各个之间不存在次序关系。

2.Nginx的组成:
nginx的二进制可执行文件----启动关闭,有各个模块编译出来的
nginx.conf配置文件----控制nginx
access.log访问日志--记录每条http请求
error.log 错误日志--定位问题

nginx虚拟主机配置

虚拟主机是一种特殊的软硬件技术,它可以将网络上的每一台计算机分成多个虚拟主机,每个虚拟主机可以独立对外提供www服务,这样就可以实现一台主机对外提供多个web服务,每个虚拟主机之间是独立的,互不影响。
nginx可以实现虚拟主机的配置,nginx支持三种类型的虚拟主机配置。

1、基于域名的虚拟主机 (server_name来区分虚拟主机——应用:外部网站)
2、基于ip的虚拟主机, (一块主机绑定多个ip地址)
3、基于端口的虚拟主机 (端口来区分虚拟主机——应用:公司内部网站,外部网站的管理后台)

基于域名的虚拟主机
配置通过域名区分的虚拟机

[root@localhost ~]# cat /etc/nginx/nginx.conf
worker_processes  4;

#error_log  logs/error.log;


events {
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;
    
    server {
        listen       80;
        server_name  web.testpm.com;  #域名
        location / {
            root   /var/www/nginx/;
            index  index.html index.htm;
            limit_rate	2k;
         }
        }
    
    server {
        listen       80;
        server_name  www.testpm.com;
        location / {
            root   /1000phone/html;
            index  index.html index.htm;
         }
        }
}

# 重新加载配置文件
# 如果编译安装的执行
[root@nginx]# /usr/local/nginx/sbin/nginx -s reload
# 如果 yum 安装的执行
[root@nginx]# nginx -s reload

#客户端配置路由映射
在 C:\Windows\System32\drivers\etc\hosts 文件中添加两行(linux:/etc/hosts)

基于ip的虚拟主机
配置通过ip区分的虚拟机

#绑定vip
[root@localhost ~]# ifconfig ens33:1 10.0.105.201/24

[root@localhost ~]# cat /etc/nginx/nginx.conf
user  root;
worker_processes  4;

#error_log  logs/error.log;


events {
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    server {
        listen       10.0.105.199:80;
        server_name  web.testpm.com;
        location / {
            root   /var/www/nginx/;
            index  index.html index.htm;
            limit_rate	2k;
        }
        
     server {
        listen       10.0.105.201:80;
        server_name  www.testpm.com;
        location / {
            root   /1000phone/html/;
            index  index.html index.htm;
         }
        }
}

#重新加载配置文件
[root@localhost ~]# /usr/local/nginx/sbin/nginx -s reload

#测试访问
浏览器输入:http://10.0.105.199
浏览器输入:http://10.0.105.201

#删除绑定的vip
[root@localhost ~]# ifconfig ens33:1 10.0.105.201/24 down
#重启nginx
[root@localhost ~]# systemctl restart nginx

基于端口的虚拟主机

[root@localhost ~]# cat /etc/nginx/nginx.conf
user  root;
worker_processes  4;


events {
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';


    sendfile        on;

    keepalive_timeout  65;


    server {
        listen       80;
        server_name  web.testpm.com;
        location / {
            root   /var/www/nginx/;
            index  index.html index.htm;
            limit_rate	2k;
        }
        
    
     server {
        listen       8080;
        server_name  www.testpm.com;
        location / {
            root   /1000phone/html/;
            index  index.html index.htm;
         }
        }
}

#重新加载配置文件
[root@localhost ~]# /usr/local/nginx/sbin/nginx -s reload

#测试访问
浏览器输入:http://web.testpm.com/
浏览器输入:http://web.1000phone.com:8080

nginx平滑升级和回滚

有时候需要对Nginx版本进行升级以满足对其功能的需求,例如添加新模块,需要新功能,而此时Nginx又在跑着业务无法停止,这时就可以选择平滑升级。
平滑升级原理简单概述

  • 在不停掉老进程的情况下,启动新进程。
  • 老进程负责处理仍然没有处理完的请求,但不再接受处理请求。
  • 新进程接受新请求。
  • 老进程处理完所有请求,关闭所有连接后,停止。

Nginx信号简介

主进程支持的信号

- TERM, INT: 立刻退出
- QUIT: 等待工作进程结束后再退出
- KILL: 强制终止进程
- HUP: 重新加载配置文件,使用新的配置启动工作进程,并逐步关闭旧进程。
- USR1: 重新打开日志文件
- USR2: 启动新的主进程,实现热升级
- WINCH: 逐步关闭工作进程

工作进程支持的信号

- TERM, INT: 立刻退出
- QUIT: 等待请求处理结束后再退出
- USR1: 重新打开日志文件

平滑升级流程

  1. 编译新版本,生成新版本的二进制文件。

  2. 用新Nginx程序文件替换旧Nginx二进制文件(注意先备份旧版本的二进制文件)。

  3. 向旧版本的master进程发送USR2信号启动新nginx进程;
    将新生成的master进程的PID存放至新生成的pid文件nginx.pid;
    master进程用新Nginx二进制文件启动新master进程及worker子进程成为旧master的子进程;
    系统中将有新旧两个Nginx主进程和对应的worker子进程并存。

  4. 当前新的请求由新或旧Nginx的worker进程进行处理;
    向旧的Nginx服务进程发送WINCH信号,使旧的Nginx worker进程平滑停止,旧的Nginx worker进程将不再接收新请求;
    当前新的请求由新Nginx的worker进程进行处理;
    旧的Nginx Master进程仍然存在;
    测试访问确认新版本是否正常工作。

  5. 如果发现升级正常,向旧master进程发送QUIT信号,关闭旧master,并删除nginx.pid.oldbin文件,到此旧版本的Nginx彻底下线,新版本正式上线。

  6. 如果发现升级有问题,可以回滚∶向旧master发送HUP,旧版本的worker开始接收新请求,向新master发送QUIT。

平滑升级和回滚案例

#启动nginx,注意:要使用systemd方法启动,不要用nginx直接启动,否则升级有问题
[root@centos8 ~]#systemctl start nginx

#下载最新稳定版
[root@centos8 ~]#wget http://nginx.org/download/nginx-1.20.1.tar.gz
[root@centos8 ~]#tar xvf nginx-1.20.1.tar.gz
[root@centos8 ~]#cd nginx-1.20.1

#查看当前使用的版本及编译选项
[root@centos8 nginx-1.20.1]#/apps/nginx/sbin/nginx -V
nginx version: nginx/1.18.0
built by gcc 8.3.1 20241214 (Red Hat 8.3.1-5) (GCC) 
built with OpenSSL 1.1.1g FIPS  21 Apr 2020
TLS SNI support enabled
configure arguments: --prefix=/apps/nginx --user=nginx --group=nginx --withhttp_ssl_module --with-http_v2_module --with-http_realip_module --withhttp_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream
--with-stream_ssl_module --with-stream_realip_module

#备份二进制文件和 nginx 的配置文件(期间nginx不会停止服务)
[root@centos8 nginx-1.20.1]#cp /apps/nginx/sbin/nginx /opt/nginx.old_$(date +%F)

#开始编译新版本
[root@centos8 nginx-1.20.1]#./configure --prefix=/apps/nginx --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module

#只执行make,不执行make install,如果执行make install,会将旧版本改名为nginx.old,新版为ngnix
[root@centos8 nginx-1.20.1]#make
[root@centos8 nginx-1.20.1]#objs/nginx -v
nginx version: nginx/1.20.1

#查看两个版本
[root@centos8 nginx-1.20.1]#ll objs/nginx /apps/nginx/sbin/nginx
-rwxr-xr-x 1 nginx nginx 7591096 Jun  7 16:28 /apps/nginx/sbin/nginx
-rwxr-xr-x 1 root root  7723272 Jun  7 17:27 objs/nginx
 
#把新版本的nginx命令复制过去覆盖旧版本程序文件,注意:需要加 -f 选项强制覆盖,否则会提示Text file busy
[root@centos8 nginx-1.20.1]#cp -f ./objs/nginx /apps/nginx/sbin/  

#检测新版本和配置文件语法兼职容性
[root@centos8 nginx-1.20.1]#/apps/nginx/sbin/nginx -t  

#发送信号USR2 平滑升级可执行程序,将存储有旧版本主进程PID的文件重命名为nginx.pid.oldbin,并启动新的nginx
#此时两个master的进程都在运行,只是旧的master不在监听,由新的master监听80
#此时Nginx开启一个新的master进程,且这个新master进程会生成新的worker进程,即升级后的Nginx进程,此时老的进程不会自动退出,新的请求仍由新和旧进程同时处理。

[root@centos8 nginx-1.20.1]#kill -USR2 `cat /apps/nginx/logs/nginx.pid`

#可以看到两个master,新的master是旧版master的子进程,并生成新版的worker进程
#注意:在Nginx-1.22.1版中如果看不到新版进程,需要重新使用service方式重新启动nginx服务再发送USR2信号
[root@centos8 nginx-1.20.1]#ps auxf|grep nginx

#如果有新请求,仍由新或旧版本提供服务
[root@ubuntu2204 ~]#curl -I http://192.168.93.200
HTTP/1.1 200 OK
Server: nginx/1.18.0

#先关闭旧nginx的worker进程,而不关闭旧nginx主进程方便回滚
#向原老的Nginx主进程发送WINCH信号,它会平滑关闭老的工作进程(主进程不退出),这时所有新请求都会由新版Nginx处理
#如果旧版worker进程有用户的旧的请求,会一直等待处理完后才会关闭,即平滑关闭
[root@centos8 nginx-1.20.1]#kill -WINCH `cat /apps/nginx/logs/nginx.pid.oldbin`

#如果有新请求,由新版本提供服务
[root@ubuntu2204 ~]#curl -I http://10.0.0.200
HTTP/1.1 200 OK
Server: nginx/1.20.1

#经过一段时间测试,新版本服务没问题,最后发送QUIT信号,退出老的master,完成全部升级过程
[root@centos8 nginx-1.20.1]#kill -QUIT `cat /apps/nginx/logs/nginx.pid.oldbin`  

#查看版本是不是已经是新版了
[root@centos8 nginx-1.20.1]#nginx -v
nginx version: nginx/1.20.1

#如果有旧的连接,不会立即关闭旧版本的Master和对应的Worker进程,直到所有旧连接断开,才会关闭所的旧的进程

######################回滚###########################################

#如果升级的新版本发现问题需要回滚,可以发送HUP信号,重新拉起旧版本的worker
[root@centos8 nginx-1.20.1]#kill -HUP `cat /apps/nginx/logs/nginx.pid.oldbin`

#最后关闭新版的master和worker,如果不执行上面的HUP信号,此步QUIT信号也可以重新拉起旧版本的worker进程
[root@centos8 nginx-1.20.1]#kill -QUIT `cat /apps/nginx/logs/nginx.pid`

#恢复旧版的文件
[root@rocky8 ~]#mv /opt/nginx.old   /apps/nginx/sbin/
mv: overwrite '/apps/nginx/sbin/nginx'? y

location指令详解

Nginx 的 HTTP 配置主要包括三个区块,结构如下:

http { 		# 这个是协议级别
  include mime.types;
  default_type application/octet-stream;
  keepalive_timeout 65;
  gzip on;
    server {	 # 这个是服务器级别
      listen 80;
      server_name localhost;
        location / {  # 这个是请求级别
          root html;
          index index.html index.htm;
        }
      }
}

location 前缀含义

#语法规则:
location [ = | ~ | ~* | ^~ ] uri { ... }

=    表示精确匹配,优先级也是最高的 
^~   表示uri以某个常规字符串开头,理解为匹配url路径即可 
~    表示区分大小写的正则匹配  
~*   表示不区分大小写的正则匹配
!~   表示区分大小写不匹配的正则
!~*  表示不区分大小写不匹配的正则
/    通用匹配,任何请求都会匹配到
@    内部服务跳转

#匹配优先级从高到低:
=, ^~, ~/~*, 不带符号

多个location配置的情况下匹配顺序为:首先匹配 =,其次匹配^~, 其次是按正则匹配,最后是交给 / 通用匹配。当有匹配成功时候,停止匹配,按当前匹配规则处理请求。

location 配置示例
精切匹配

=:必须与指定的模式精确匹配

server {
    listen       80;
    server_name  localhost;
    access_log  /var/log/nginx/http_access.log  main;

    location / {
        root /usr/share/nginx/html;
        index a.html index.htm;
    }
    location = / {
        root /usr/share/nginx/html;
        index b.html index.htm;
    }
}

测试:
http://192.168.1.9     # =/

http://192.168.1.9/a.html   # /

区分大小写

~ :指定的正则表达式要区分大小写

server {
server_name localhost;
  location ~ /abc {
                root /home/www/nginx;
                index 2.html index.html;
        }
}
测试访问:
http://192.168.1.9/abc
不正确的
http://192.168.1.9/ABC

========================================

#如果将配置文件修改为:
      location ~ /ABC {
            root /home/www/nginx;
            index 2.html index.html;
        }
#在创建目录和文件
[root@ansible-server html]# cd /home/www/nginx/
[root@ansible-server nginx]# mkdir ABC
[root@ansible-server nginx]# vim ABC/2.html
 #访问:
 http://192.168.1.9/ABC/
 
 结论:~ 需要区分大小写。而且目录需要根据大小写定义。

匹配案例-URI开始

location ^~ /images {
   root /data/nginx/;
   index index.html;
 }
location /api {
   alias /data/nginx/api;
   index index.html;
}  

#重启Nginx并访问测试,实现效果是访问/images和/app返回不同的结果
浏览器访问:
http://192.168.198.144/images/
images
http://192.168.198.144/api/
api web

匹配优先级

location优先级:(location =) > (location ^~ 路径) > (location ~,~* 正则顺序) > (location 完整路径) > (location 部分起始路径) > (/)

错误页面定制(location @重定向)

#如果出现异常,则重新定向到@error_404这个location上

server {
 listen 80;
 server_name web.testpm.com;
 root /data/www;
 location / {
 index index.html;
 }

error_page 404 @error_404;
 location @error_404 {
 default_type text/html;
 charset utf8;
 return 404 '你访问的页面可能走丢了!';
 }
}

反向代理

反向代理产生的背景
在计算机世界里,由于单个服务器的处理客户端(用户)请求能力有一个极限,当用户的接入请求蜂拥而入时,会造成服务器忙不过来的局面,可以使用多个服务器来共同分担成千上万的用户请求,这些服务器提供相同的服务,对于用户来说,根本感觉不到任何差别。

反向代理服务的实现
需要有一个负载均衡设备(即反向代理服务器)来分发用户请求,将用户请求分发到后端正真提供服务的服务器上。服务器返回自己的服务到负载均衡设备。负载均衡设备将服务器的服务返回用户。

正/反向代理的区别

正向代理
正向代理的过程隐藏了真实的请求客户端,服务器不知道真实的客户端是谁,客户端请求的服务都被代理服务器代替请求。我们常说的代理也就是正向代理,正向代理代理的是请求方,也就是客户端;比如我们要访问youtube,可是不能访问,只能先安装个FQ软件代你去访问,通过FQ软件才能访问,FQ软件就叫作正向代理。

反向代理
反向代理的过程隐藏了真实的服务器,客户不知道真正提供服务的人是谁,客户端请求的服务都被代理服务器处理。反向代理代理的是响应方,也就是服务端;我们请求www.baidu.com时这www.baidu.com就是反向代理服务器,真实提供服务的服务器有很多台,反向代理服务器会把我们的请求分转发到真实提供服务的各台服务器。Nginx就是性能非常好的反向代理服务器,用来做负载均衡。

两者的区别在于代理的对象不一样

正向代理中代理的对象是客户端。
反向代理中代理的对象是服务端。

nginx Proxy 配置
代理模块

ngx_http_proxy_module: #将客户端的请求以http协议转发至指定服务器进行处理
ngx_http_upstream_module #用于定义为proxy_pass,fastcgi_pass,uwsgi_pass等指令引用的后端服务器分组
ngx_stream_proxy_module:#将客户端的请求以tcp协议转发至指定服务器处理
ngx_http_fastcgi_module:#将客户端对php的请求以fastcgi协议转发至指定服务器助理
ngx_http_uwsgi_module: #将客户端对Python的请求以uwsgi协议转发至指定服务器处理

nginx proxy 具体配置详解

proxy_pass  #真实后端服务器的地址,可以是ip也可以是域名和url地址
proxy_redirect  #如果真实服务器使用的是的真实IP:非默认端口。则改成IP:默认端口。
proxy_set_header #重新定义或者添加发往后端服务器的请求头
proxy_set_header X-Real-IP $remote_addr; #只记录连接服务器的上一个ip地址信息。
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; #通过这个选项可以记录真正客户端机器的ip地址
proxy_connect_timeout 60s; #后端服务器连接的超时时间发起三次握手等候响应超时时间
proxy_send_timeout 30s; #后端服务器数据回传时间,就是在规定时间之内后端服务器必须传完所有的数据
proxy_read_timeout time; #nginx接收upstream(上游/真实) server数据超时, 默认60s, 如果连续的60s内没有收到1个字节, 连接关闭。像长连接

指定 location 实现反向代理

192.168.93.200是后端反向代理服务器(即本机)
[root@nginx-server ~]# vim /etc/nginx/conf.d/default.conf

    server {
    listen       80;
    server_name  localhost;

    location / {
    proxy_pass http://192.168.93.201:80;  #201是应用服务器(被访问的网站)
    proxy_redirect default;
    proxy_set_header Host $http_host; #转发主机头至后端服务器
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    proxy_connect_timeout 30;
    proxy_send_timeout 60;
    proxy_read_timeout 60;
    }
}

#重新加载nginx配置文件
[root@nginx-server ~]# nginx -s reload

使用PC客户端访问200服务器地址
浏览器中输入http://192.168.93.200 (也可以是后端代理服务器的域名)
成功访问201服务器页面

负载均衡

upstream配置

upstream testapp { 
      server 10.0.105.199:8081;
      server 10.0.105.202:8081;
    }
 server {
        ....
        location / {         
           proxy_pass  http://testapp;  #请求转向 testapp 定义的服务器列表         
        } 

负载均衡算法

upstream 支持4种负载均衡调度算法

1、轮询(默认):每个请求按时间顺序逐一分配到不同的后端服务器;

2、ip_hash:每个请求按访问IP的hash结果分配,同一个IP客户端固定访问一个后端服务器。可以保证来自同一ip的请求被打到固定的机器上,可以解决session问题。

3、url_hash:按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器。

4、fair:这是比上面两个更加智能的负载均衡算法。此种算法可以依据页面大小和加载时间长短智能地进行负载均衡,也就是根据后端服务器的响应时间来分配请求,响应时间短的优先分配。Nginx本身是不支持 fair的,如果需要使用这种调度算法,必须下载Nginx的 upstream_fair模块。

热备
热备:如果你有2台服务器,当一台服务器发生事故时,才启用第二台服务器给提供服务。服务器处理请求的顺序:AAAAA,突然A挂啦,BBBBB.....

upstream myweb { 
      server 172.17.14.2:8080; 
      server 172.17.14.3:8080 backup;  #热备     
    }

权重轮询
nginx默认就是轮询其权重都默认为1,服务器处理请求的顺序:ABABABABAB....

upstream myweb { 
      server 172.17.14.2:8080; 
      server 172.17.14.3:8080;      
    }

加权轮询
跟据配置的权重的大小而分发给不同服务器不同数量的请求。如果不设置,则默认为1。下面服务器的请求顺序为:ABBABBABBABBABB....

upstream myweb { 
      server 172.17.14.2:8080 weight=1;
      server 172.17.14.3:8080 weight=2;
}

ip_hash

upstream myweb { 
      server 172.17.14.2:8080; 
      server 172.17.14.3:8080;
      ip_hash;
    }

nginx负载均衡配置状态参数

- down,表示当前的server暂时不参与负载均衡。
- backup,预留的备份机器。当其他所有的非backup机器出现故障或者忙的时候,才会请求backup机器,因此这台机器的压力最轻。
- max_fails,允许请求失败的次数,默认为1。当超过最大次数时,返回proxy_next_upstream 模块定义的错误。
- fail_timeout,在经历了max_fails次失败后,暂停服务的时间单位秒。max_fails可以和fail_timeout一起使用。

upstream myweb { 
      server 172.17.14.2:8080 weight=2 max_fails=2 fail_timeout=2;
      server 172.17.14.3:8080 weight=1 max_fails=2 fail_timeout=1;    
    }

Nginx自定义访问日志

nginx 有一个非常灵活的日志记录模式,每个级别的配置可以有各自独立的访问日志, 所需日志模块 ngx_http_log_module 的支持,日志格式通过 log_format 命令来定义,日志对于统计和排错是非常有利的,下面总结了 nginx 日志相关的配置 包括 access_log、log_format、rewrite_log、error_log。

访问日志由 ngx_http_log_module 模块实现

# 设置访问日志
access_log path;
# 关闭访问日志
access_log off; 

path 指定日志的存放位置

可以应用access_log指令的作用域分别有http,server,location

access_log /var/logs/nginx-access.log

该例子指定日志的写入路径为/var/logs/nginx-access.log,日志格式使用默认的combined。

log_format 指令
Nginx 预定义了名为 combined 日志格式,如果没有明确指定日志格式默认使用该格式,如果不想使用Nginx预定义的格式,可以通过log_format指令来自定义。

og_format combined '$remote_addr - $remote_user [$time_local] '
                    '"$request" $status $body_bytes_sent '
                    '"$http_referer" "$http_user_agent"';

log_format 指令语法

log_format name [escape=default|json] string ...;

- name 格式名称。在 access_log 指令中引用。
- escape 设置变量中的字符编码方式是`json`还是`default`,默认是`default`。
- string 要定义的日志格式内容。该参数可以有多个。参数中可以使用Nginx变量。

log_format 指令中常用变量

$remote_addr, $http_x_forwarded_for   #记录客户端IP地址
$remote_user                    #记录客户端用户名称
$request                   #记录请求的URL和HTTP协议
$status                     #记录请求状态
$body_bytes_sent      #发送给客户端的字节数,不包括响应头的大小
$bytes_sent               #发送给客户端的总字节数
$connection               #连接的序列号
$connection_requests  #当前通过一个连接获得的请求数量。
$msec                      #日志写入时间。单位为秒,精度是毫秒。
$http_referer            #记录从哪个页面链接访问过来的,可以根据该参数进行防盗链设置
$http_user_agent      #记录客户端浏览器相关信息
$request_length        #请求的长度(包括请求行,请求头和请求正文)。
$request_time           #请求处理时间,单位为秒,精度毫秒; 从读入客户端的第一个字节开始,直到把最后一个字符发送给客户端后进行日志写入为止。
$time_iso8601           #ISO8601标准格式下的本地时间。
$time_local               #通用日志格式下的本地时间。

自定义日志格式的使用

access_log /var/logs/nginx-access.log main

log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                  '$status $body_bytes_sent "$http_referer" '
                  '"$http_user_agent" "$http_x_forwarded_for"';

注:如果Nginx位于负载均衡器,nginx反向代理之后,web服务器无法直接获取到客户端真实的IP地址。
$remote_addr获取的是反向代理的IP地址。反向代理服务器在转发请求的http头信息中,可以增加X-Forwarded-For信息,用来记录客户端IP地址。

JSON 格式的日志

http {
    log_format json '{"time_local":"$time_local",'
                    '"remote_addr":"$remote_addr",'
                    '"request":"$request",'
                    '"status":$status,'
                    '"body_bytes_sent":$body_bytes_sent,'
                    '"http_referer":"$http_referer",'
                    '"http_user_agent":"$http_user_agent"}';
  
}

error_log 指令
配置错误日志文件的路径和日志级别

error_log file [level];
Default: 
error_log logs/error.log error;

file 参数指定日志的写入位置
level 参数指定日志的级别。level可以是debug, info, notice, warn, error, crit, alert,emerg中的任意值
默认值是error

扩展日志级别:
 debug级别:低级别,包含的信息非常详细
 info级别:稍微的高一点了。用的多一些。
 notice 和warning
 notice:相当于提示
 warning:警告 和warn 一样
 err和error 一样。
 crit:比较严重了
 alert:告警,很严重
 emerg: 恐慌级别, 级别最高的

基本用法

error_log /var/logs/nginx/nginx-error.log

配置段: http, server, location作用域
例子中指定了错误日志的路径为:/var/logs/nginx/nginx-error.log,日志级别使用默认的 error。

Nginx编译安装脚本

#!/bin/bash

# 定义变量
NGINX_VERSION="1.24.0"  
PREFIX="/usr/local/nginx"
DOWNLOAD_URL="http://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz"

# 更新系统包列表并安装依赖
install_dependencies() {
    echo "正在安装依赖..."
    sudo yum install -y epel-release
    sudo yum install -y gcc pcre pcre-devel zlib zlib-devel openssl openssl-devel make
}

# 下载并解压Nginx源码
download_and_extract_nginx() {
    echo "下载 Nginx ${NGINX_VERSION} 源码..."
    wget $DOWNLOAD_URL -O nginx.tar.gz
    tar -zxvf nginx.tar.gz
    cd nginx-${NGINX_VERSION}
}

# 配置编译选项
configure_nginx() {
    echo "配置 Nginx..."
    ./configure --prefix=$PREFIX \
                --with-http_ssl_module \
                --with-http_v2_module \
                --with-http_realip_module \
                --with-http_stub_status_module \
                --with-http_gzip_static_module \
                --with-threads \
                --with-stream \
                --with-stream_ssl_module \
                --with-stream_realip_module \
                --with-compat \
                --with-file-aio
}

# 编译并安装
compile_and_install_nginx() {
    echo "编译并安装 Nginx..."
    make
    sudo make install
}

# 创建启动脚本(systemd service)
create_startup_script() {
    echo "创建 systemd 服务文件..."
    cat << EOF | sudo tee /etc/systemd/system/nginx.service
[Unit]
Description=The NGINX HTTP and reverse proxy server
After=network.target remote-fs.target nss-lookup.target

[Service]
Type=forking
PIDFile=${PREFIX}/logs/nginx.pid
ExecStartPre=${PREFIX}/sbin/nginx -t
ExecStart=${PREFIX}/sbin/nginx
ExecReload=${PREFIX}/sbin/nginx -s reload
ExecStop=${PREFIX}/sbin/nginx -s stop
PrivateTmp=true

[Install]
WantedBy=multi-user.target
EOF
    sudo systemctl daemon-reload
    sudo systemctl enable nginx
}

# 执行步骤
install_dependencies
download_and_extract_nginx
configure_nginx
compile_and_install_nginx
create_startup_script

echo "安装完成"
posted @ 2024-12-26 14:47  三两螺蛳粉  阅读(17)  评论(0编辑  收藏  举报