科普文:一文搞懂nginx原理和实战

1. Nginx简介与核心架构

图片

1.1 Nginx简介

        Nginx (engine x) 是一个高性能的 HTTP 和反向代理服务器,也是一个 IMAP/POP3/SMTP 邮件代理服务器。

        由 Igor Sysoev 于2004年首次发布,其设计目标是解决 C10K 问题,即在一台服务器上同时处理一万个并发连接。

       Nginx 以其高并发处理能力、低资源消耗和模块化设计而闻名,广泛应用于 Web 服务器、反向代理、负载均衡等场景。

1.1.1 主要特性
  • 高并发处理能力:Nginx 使用异步、非阻塞事件驱动架构,能够高效地处理大量并发连接。

  • 低资源消耗:相对于传统的进程或线程模型,Nginx 使用更少的内存和 CPU 资源。

  • 模块化设计:Nginx 的功能通过模块实现,用户可以根据需求加载不同的模块。

  • 高可扩展性:通过第三方模块和 Lua 脚本,Nginx 能够轻松扩展其功能。

  • 丰富的功能:支持 HTTP/2、反向代理、负载均衡、缓存、SSL/TLS、WebSocket 等。

1.1.2 工作流程
  • 当有新的 HTTP 请求到达时,master 进程会将其分发给一个工作进程。

  • 工作进程处理请求,根据配置文件进行请求的处理,包括反向代理、负载均衡、静态文件服务等。

  • 处理完成后,工作进程将响应返回给客户端。

1.1.3 工作模式

        Nginx有两种工作模式,分别为单进程工作模式多进程工作模式

        单进程工作模式:除了一个主进程外,还有一个工作进行。这个工作进程是单线程的。默认的工作模式

        多进程工作模式:除了一个主进程外,还有一个工作进行,每一个进程包含多个线程。

1.1.4 nginx目录结构

        安装完Nginx后,我们先来熟悉一下Nginx的目录结构,重点目录/文件如下:

  • conf/nginx.conf ---- nginx配置文件
  • html ---- 存放静态文件 (html、CSS、Js等)
  • logs ---- 日志目录,存放日志文件
  • sbin/nginx ---- 二进制文件,用于启动、停止Nginx服务
1.1.5 nginx常用命令
1. ./nginx -t #检查配置文件的语法的正确性,并尝试打开配置文件中所引用到的文件。
2. ./nginx -c /home/xx/nginx.conf #指定一个配置文件,来代替缺省的。
3. ./nginx -v #nginx 的版本。
4. ./nginx -s reload #reload 会重新加载配置文件,Nginx服务不会中断。而且reload时会测试conf语法等。
5. ./nginx #启动nginx。
6. ./nginx -s stop #stop 会立即停止服务,这种方法比较强硬,无论进程是否在工作,都直接停止进程。
7. ./nginx -s quit #quit 较stop相比就比较温和一些了,需要进程完成当前工作后再停止。

1.2 核心架构

        Nginx 的核心架构设计是其高性能和高可用性的关键。核心架构包括模块化设计、事件驱动模型、Master-Worker 进程模型和高效的请求处理流程。

1.2.1 模块化设计

        Nginx 采用模块化设计,核心功能和扩展功能都通过模块实现。模块分为核心模块、标准 HTTP 模块和第三方模块。用户可以根据需要启用或禁用模块,灵活配置 Nginx 的功能。

        nginx从功能上分为如下四类:

**Core(核心模块):**构建nginx基础服务、管理其他模块。**Handlers(处理器模块):**此类模块直接处理请求,主要负责处理客户端请求并产生待响应内容。**Filters (过滤器模块):**此类模块主要对其他处理器模块输出的内容进行修改。**Upstraem (反代理类模块):**此类模块是实现反向代理的功能。
**load-balancer(负载均衡模块)😗*实现特定的算法,从服务器中选择一个合适的服务器进行相应请求

各模块之间的http处理流程:
1)客户端发送HTTP请求
2) Nginx从配置文件选择一个合适的模块 , (如果有)负载均衡模块就根据相应的算法选择一个合适的服务器
3)处理模块对客户端的请求进行处理,并把输出缓冲放到第一个过滤模块上
4) 第一个过滤模块处理后输出给第二个过滤模块,依此类推
5) 最后把响应发给客户端。
  • 核心模块:包括 HTTP 模块、事件模块、解析器模块等。实现 Nginx 的基本功能,如事件处理、内存管理、配置解析等。

    • Nginx 的 worker 进程分为核心模块和功能性模块。

    • 核心模块主要负责维持一个运行循环(run-loop),在其中执行网络请求处理的不同阶段的模块功能,如网络读写、存储读写、内容传输、外出过滤,以及将请求发往上游服务器等。

      • HTTP 模块处理 HTTP 请求和响应,包括 HTTP 头部解析、HTTP 请求方法解析、URI 解析等。

      • 事件模块负责处理底层的事件通知机制,如 Epoll、Kqueue 等。

      • 解析器模块负责解析 Nginx 配置文件。

    • Nginx 的代码采用了模块化设计,这使得我们可以根据需要选择和修改功能模块,然后编译成具有特定功能的服务器。

  • 标准 HTTP 模块:提供 HTTP 服务的功能,如静态文件服务、反向代理、负载均衡等。

  • 第三方模块:由社区或开发者提供,扩展 Nginx 的功能,如 Lua 模块、Redis 模块等。

# 配置示例:启用和配置 HTTP 模块
http {server {listen 80;server_name example.com;location / {root /var/www/html;index index.html index.htm;}location /proxy {proxy_pass http://backend_server;}}
}
1.2.2 事件驱动模型

        Nginx 使用异步、非阻塞事件驱动模型,能够高效地处理并发连接。基于异步及非阻塞的事件驱动模型是Nginx 实现高并发、高性能的关键。

        事件驱动模型基于 epoll(Linux)、kqueue(FreeBSD)等高效的 I/O 多路复用机制,实现事件的高效分发和处理。        

        这种模型使得 Nginx 能够高效地处理大量并发请求,而不会因为阻塞等待而降低性能。

  • 异步非阻塞:所有 I/O 操作都通过事件通知机制完成,不会阻塞进程。

    • Nginx 采用了事件驱动的模型,主要利用了操作系统提供的异步 I/O 机制。

    • 当有新的连接建立或者数据可读写时,Nginx 不会阻塞等待,而是通过事件通知机制处理这些事件,从而提高了处理效率。

  • 高效的事件分发:通过 epoll、kqueue 等机制,Nginx 能够快速分发和处理大量并发连接的事件。

// 示例:基于 epoll 的事件循环
for (;;) {int n = epoll_wait(epoll_fd, events, MAX_EVENTS, -1);for (int i = 0; i < n; i++) {if (events[i].events & EPOLLIN) {// 处理读事件} else if (events[i].events & EPOLLOUT) {// 处理写事件}}
}
1.2.3 Master-Worker 进程模型

        Nginx 采用 Master-Worker 进程模型,确保高并发处理能力和高可靠性。Master 进程负责管理 Worker 进程,处理信号和管理共享资源。Worker 进程处理实际的请求,互不干扰,提高了并发处理能力和稳定性。

  • Master 进程:启动、停止 Worker 进程,处理信号(如重新加载配置),管理共享资源(如缓存)。

  • Worker 进程:处理客户端请求,每个 Worker 进程独立处理不同的连接,避免相互影响。

# 配置示例:设置 Worker 进程数量
worker_processes auto;events {worker_connections 1024;
}
1.2.4 请求处理流程

        Nginx 的请求处理流程高度优化,能够高效地处理 HTTP 请求。主要流程包括接收请求、解析请求、选择处理模块、生成响应和发送响应。

  • 接收请求:通过事件驱动模型接收客户端请求。

  • 解析请求:解析 HTTP 请求头,生成请求上下文。

  • 选择处理模块:根据配置选择相应的模块处理请求,如静态文件服务、反向代理等。

  • 生成响应:调用处理模块生成响应数据。

  • 发送响应:通过事件驱动模型发送响应给客户端。

# 配置示例:静态文件服务和反向代理
http {server {listen 80;server_name example.com;location / {root /var/www/html;index index.html index.htm;}location /proxy {proxy_pass http://backend_server;}}
}

1.3 Nginx配置文件结构

...              #全局块events {         #events块...
}http      #http块
{...   #http全局块server        #server块{ ...       #server全局块location [PATTERN]   #location块{...}location [PATTERN] {...}}server{...}...     #http全局块
}

        1、全局块:配置影响nginx全局的指令。一般有运行nginx服务器的用户组,nginx进程pid存放路径,日志存放路径,配置文件引入,允许生成worker process数等。

        2、events块:配置影响nginx服务器或与用户的网络连接。有每个进程的最大连接数,选取哪种事件驱动模型处理连接请求,是否允许同时接受多个网路连接,开启多个网络连接序列化等。

        3、http块:可以嵌套多个server,配置代理,缓存,日志定义等绝大多数功能和第三方模块的配置。如文件引入,mime-type定义,日志自定义,是否使用sendfile传输文件,连接超时时间,单连接请求数等。

        4、server块:配置虚拟主机的相关参数,一个http中可以有多个server。

        5、location块:配置请求的路由,以及各种页面的处理情况。

示例:

########### 每个指令必须有分号结束。#################
#user administrator administrators;  #配置用户或者组,默认为nobody nobody。
#worker_processes 2;  #允许生成的进程数,默认为1
#pid /nginx/pid/nginx.pid;   #指定nginx进程运行文件存放地址
error_log log/error.log debug;  #制定日志路径,级别。这个设置可以放入全局块,http块,server块,级别以此为:debug|info|notice|warn|error|crit|alert|emerg
events {accept_mutex on;   #设置网路连接序列化,防止惊群现象发生,默认为onmulti_accept on;  #设置一个进程是否同时接受多个网络连接,默认为off#use epoll;      #事件驱动模型,select|poll|kqueue|epoll|resig|/dev/poll|eventportworker_connections  1024;    #最大连接数,默认为512
}
http {include       mime.types;   #文件扩展名与文件类型映射表default_type  application/octet-stream; #默认文件类型,默认为text/plain#access_log off; #取消服务日志    log_format myFormat '$remote_addr–$remote_user [$time_local] $request $status $body_bytes_sent $http_referer $http_user_agent $http_x_forwarded_for'; #自定义格式access_log log/access.log myFormat;  #combined为日志格式的默认值sendfile on;   #允许sendfile方式传输文件,默认为off,可以在http块,server块,location块。sendfile_max_chunk 100k;  #每个进程每次调用传输数量不能大于设定的值,默认为0,即不设上限。keepalive_timeout 65;  #连接超时时间,默认为75s,可以在http,server,location块。upstream mysvr {   server 127.0.0.1:7878;server 192.168.10.121:3333 backup;  #热备}error_page 404 https://www.baidu.com; #错误页server {keepalive_requests 120; #单连接请求上限次数。listen       4545;   #监听端口server_name  127.0.0.1;   #监听地址       location  ~*^.+$ {       #请求的url过滤,正则匹配,~为区分大小写,~*为不区分大小写。#root path;  #根目录#index vv.txt;  #设置默认页proxy_pass  http://mysvr;  #请求转向mysvr 定义的服务器列表deny 127.0.0.1;  #拒绝的ipallow 172.18.5.54; #允许的ip           } }
}需要注意的有以下几点:1、1.$remote_addr 与$http_x_forwarded_for 用以记录客户端的ip地址; 2.$remote_user :用来记录客户端用户名称; 3.$time_local : 用来记录访问时间与时区;4.$request : 用来记录请求的url与http协议;5.$status : 用来记录请求状态;成功是200, 6.$body_bytes_s ent :记录发送给客户端文件主体内容大小;7.$http_referer :用来记录从那个页面链接访问过来的; 8.$http_user_agent :记录客户端浏览器的相关信息;2、惊群现象:一个网路连接到来,多个睡眠的进程被同事叫醒,但只有一个进程能获得链接,这样会影响系统性能。3、每个指令必须有分号结束。
1.3.1、localtion 路由匹配规则

        什么是location? : nginx根据用户请求的URI来匹配对应的location模块,匹配到哪个location,请求将被哪个location块中的配置项所处理。

        location配置语法:location [修饰符] pattern {…}

常见匹配规则如下:

修饰符作用
无修饰符的前缀匹配,匹配前缀是 你配置的(比如说你配的是 /aaa) 的url
=精确匹配
~正则表达式模式匹配,区分大小写
~*正则表达式模式匹配,不区分大小写
^~^~类型的前缀匹配,类似于无修饰符前缀匹配,不同的是,如果匹配到了,那么就停止后续匹配
/通用匹配,任何请求都会匹配到(只要你域名对,所有请求通吃!)
1.3.2、前缀匹配(无修饰符)

首先我提前创建了prefix_match.html文件,之后改一下nginx.conf文件(给前缀是 /prefixmatch 的请求返回 /etc/nginx/locatest/prefix_match.html 这个文件) ,如下:

image.png

然后在宿主机hosts中配置域名 172.30.128.65 http://www.locatest.com 映射后,观察到nginx服务器返回内容如下:

image.png

curl http://www.locatest.com/prefixmatch     ✅ 301
curl http://www.locatest.com/prefixmatch?    ✅ 301
curl http://www.locatest.com/PREFIXMATCH     ❌ 404
curl http://www.locatest.com/prefixmatch/    ✅ 200
curl http://www.locatest.com/prefixmatchmmm  ❌ 404
curl http://www.locatest.com/prefixmatch/mmm ❌ 404
curl http://www.locatest.com/aaa/prefixmatch/❌ 404

可以看到 域名/prefixmatch 和域名/prefixmatch? 返回了301 ,原因在于prefixmatch映射的 /etc/nginx/locatest/ 是个目录,而不是个文件所以nginx提示我们301,这个我们不用管没关系,总之我们知道:域名/prefixmatch域名/prefixmatch? 和域名/prefixmatch/ 这三个url通过我们配置的 无修饰符前缀匹配规则 都能匹配上就行了。

ps:为了方便,我们下边的几个location规则演示不再跳转静态文件了,而是直接return一句话。

1.3.3、精确匹配( = )

为了演示精确匹配,我们再给nginx.conf文件增加一个location配置,如下标红处:

image.png

实际效果如下:

image.png

http://www.locatest.com/exactmatch      ✅ 200
http://www.locatest.com/exactmatch?    ✅ 200
http://www.locatest.com/exactmatch/     ❌ 404
http://www.locatest.com/exactmatchmmmm  ❌ 404
http://www.locatest.com/EXACTMATCH      ❌ 404

可以看出来精确匹配就是精确匹配,差一个字也不行!

1.3.4、前缀匹配( ^~ )

我们上边说了不带任何修饰符的前缀匹配(5.1小节),这里我们看下 修饰符是 ^~的 前缀匹配和不带修饰符的前缀匹配有啥区别,先在ngnx.conf文件增加个location并配好如下:

image.png

curl效果如下:

image.png

curl http://www.locatest.com/exactprefixmatch     ✅ 200
curl http://www.locatest.com/exactprefixmatch/    ✅ 200
curl http://www.locatest.com/exactprefixmatch?    ✅ 200
curl http://www.locatest.com/exactprefixmatchmmm  ✅ 200
curl http://www.locatest.com/exactprefixmatch/mmm ✅ 200
curl http://www.locatest.com/aaa/exactprefixmatch ❌ 404
curl http://www.locatest.com/EXACTPREFIXMATCH     ❌ 404

可以看到带修饰符(^~)的前缀匹配 像:域名/exactprefixmatchmmm 和域名/exactprefixmatch/mmm 是可以匹配上的,而不带修饰符的前缀匹配这两个类型的url是匹配不上的直接返回了404 ,其他的和不带修饰符的前缀匹配似乎都差不多。

1.3.5、正则匹配(~ 区分大小写)

ps:正则表达式的匹配,需要你对正则语法比较熟悉,熟悉语法后写匹配规则也就得心应手了。

添加个location并配置,如下:( ^表示开头,$表示结尾)

image.png

实际效果如下:

image.png

curl http://www.locatest.com/regexmatch      ✅ 200
curl http://www.locatest.com/regexmatch/     ❌ 404
curl http://www.locatest.com/regexmatch?     ✅ 200
curl http://www.locatest.com/regexmatchmmm   ❌ 404
curl http://www.locatest.com/regexmatch/mmm  ❌ 404
curl http://www.locatest.com/REGEXMATCH      ❌ 404
curl http://www.locatest.com/aaa/regexmatch  ❌ 404
curl http://www.locatest.com/bbbregexmatch   ❌ 404

可以看到~修饰的正则是区分大小写的。接下来我们看下 不区分大小写的匹配。

1.3.6、正则匹配(~* 不区分大小写)

改下location 在修饰符~后加个

image.png

看下实际效果:

image.png

可以看到这次 curl http://www.locatest.com/REGEXMATCH 是可以匹配上的,说明 ~ 确实是不区分大小写的。

1.3.7、通用匹配( / )

通用匹配使用一个 / 表示,可以匹配所有请求,一般nginx配置文件最后都会有一个通用匹配规则,当其他匹配规则均失效时,请求会被路由给通用匹配规则处理,如果没有配置通用匹配,并且其他所有匹配规则均失效时,nginx会返回404错误。

image.png

通用匹配实际效果:

image.png

可以看到通用匹配很好理解,只要你域名写对了,那么所有的url都会被匹配上,来者不拒的感觉。

1.3.8、关于location 匹配优先级

上边我们说了6种location匹配规则,那么如果存在多个到底走哪个location呢?这就的说说location的匹配优先级了。先来看下nginx官网和stackoverflow上的资料如下:

image.png

image.png

综上资料我们对location匹配优先级的总结如下: 1. 优先走精确匹配,精确匹配命中时,直接走对应的location,停止之后的匹配动作。 2. 无修饰符类型的前缀匹配和 ^~ 类型的前缀匹配命中时,收集命中的匹配,对比出最长的那一条并存起来(最长指的是与请求url匹配度最高的那个location)。 3. 如果步骤2中最长的那一条匹配是^~类型的前缀匹配,直接走此条匹配对应的location并停止后续匹配动作;如果步骤2最长的那一条匹配不是^~类型的前缀匹配(也就是无修饰符的前缀匹配),则继续往下匹配 5. 按location的声明顺序,执行正则匹配,当找到第一个命中的正则location时,停止后续匹配。 6. 都没匹配到,走通用匹配( / )(如果有配置的话),如果没配置通用匹配的话,上边也都没匹配上,到这里就是404了。

如果非要给修饰符排个序的话就是酱样子: = > ^~ > 正则 > 无修饰符的前缀匹配 > /

ok关于location就到这里,location是一个很重要的点,学好这个才知道nginx到底是咋匹配url的。

2. Nginx反向代理与负载均衡

        Nginx 作为高性能的代理服务器,其代理原理是其设计的核心之一。无论是针对 HTTP 还是其他协议(如 FastCGI、Memcache、Redis 等)的网络请求或响应,Nginx 都采用了代理机制来实现数据的转发和处理。

        Nginx 的代理原理主要基于以下几个关键点:

        接收请求:当 Nginx 接收到客户端的请求时,根据配置文件中的代理设置,确定是否需要进行代理转发。如果需要代理转发,则根据配置选择合适的代理方式。

        建立连接:Nginx 会与目标服务器建立连接,可以是与远程服务器建立 TCP 连接,也可以是与本地应用程序之间建立的 Unix Socket 连接,取决于代理目标的具体情况。

        数据传输:一旦连接建立成功,Nginx 会将客户端的请求数据转发给目标服务器,并且在接收到目标服务器的响应后,再将响应数据返回给客户端。这个过程可以是全双工的,意味着 Nginx 可以同时接收客户端请求和目标服务器响应,然后进行相应的转发和处理。

        代理缓存:为了进一步提高性能,Nginx 还支持代理缓存功能。它可以将经常请求的数据缓存在本地,避免每次请求都要向后端服务器发起请求,从而减少响应时间和网络负载。

        负载均衡:对于需要代理转发的请求,Nginx 还支持负载均衡功能,可以根据一定的策略将请求分发到多个后端服务器上,以实现负载均衡和高可用性。

2.1 反向代理基础

        反向代理服务器在客户端和服务器之间充当中介,接收客户端的请求并将其转发给后端服务器,然后将后端服务器的响应返回给客户端。Nginx 作为反向代理服务器的优势在于其高并发处理能力、灵活的配置和丰富的功能。

2.1.1 反向代理的优势
  • 隐藏后端服务器:反向代理隐藏了后端服务器的真实 IP 和端口,提升了安全性。

  • 负载均衡:反向代理可以将请求分发到多台后端服务器,实现负载均衡。

  • 缓存:反向代理服务器可以缓存后端服务器的响应,减少后端服务器的压力,提高响应速度。

  • SSL 终止:反向代理服务器可以处理 SSL/TLS 加密,减轻后端服务器的负担。

2.1.2 反向代理配置示例
http {upstream backend {server backend1.example.com;server backend2.example.com;}server {listen 80;server_name example.com;location / {proxy_pass http://backend;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto $scheme;}}
}下面是一个整体的参考:nginx 配置反向代理转发proxy_pass#=======================================location 带/结尾=======================================
# 请求url http://127.0.0.1:8080/proxy/index.html
location /proxy/ {proxy_pass http://127.0.0.1:8080/;
}
# 代理地址以 "/" 结尾,代理转发的url地址为:http://127.0.0.1:8080/index.htmllocation /proxy/ {proxy_pass http://127.0.0.1:8080;
}
# 代理地址不以 "/" 结尾,代理转发的url地址为:http://127.0.0.1:8080/proxy/index.htmllocation /proxy/ {proxy_pass http://127.0.0.1:8080/tomcat/;
}
# 代理地址以 "tomcat/" 结尾,代理转发的url地址为:http://127.0.0.1:8080/tomat/index.htmllocation /proxy/ {proxy_pass http://127.0.0.1:8080/tomcat;
}
# 代理地址以 "tomcat" 代理转发的url地址为:http://127.0.0.1:8080/proxytomcat/index.html#=======================================location 不带/结尾=======================================
location /proxy {proxy_pass http://127.0.0.1:8080/tomcat;
}
# 代理地址以 "tomcat" 代理转发的url地址为:http://127.0.0.1:8080/tomcat/index.htmllocation /proxy {proxy_pass http://127.0.0.1:8080/;
}
# 代理地址以 "/" 代理转发的url地址为:http://127.0.0.1:8080//index.htmllocation /proxy {proxy_pass http://127.0.0.1:8080;
}
# 代理地址不以 "/" 代理转发的url地址为:http://127.0.0.1:8080/proxy/index.html#=======================================alias与root=======================================
location /test/ {alias /www/abc/;
}
# 使用alias,当访问/test/时,会到/www/abc/目录下找文件location /test/ {root /www/abc;
}
# 使用root,当访问/test/时,会到/www/abc/test/目录下找文件(如果没有test目录会报403)#================================多层nginx代理@Websocket服务=======================================
location /secure/socket {add_header backendIP $upstream_addr;add_header backendCode $upstream_status;proxy_redirect off;proxy_connect_timeout 6000;proxy_read_timeout 6000; proxy_send_timeout 6000;proxy_set_header Host 192.168.9.101:8087;proxy_pass http://localhost:8080/websocket/web;proxy_http_version 1.1;proxy_set_header Upgrade $http_upgrade;proxy_set_header Connection "upgrade"; proxy_set_header token $arg_username; 
}
#================================多层nginx代理@Java服务=======================================
#主机127.0.0.1下的nginx配置,port=8081
location /local/app/ {proxy_pass http://10.9.103.36:8081/;
}
#主机10.9.103.36下的nginx配置,port=8081
location /chat/ {proxy_pass http://10.186.253.117:8081/;
}
#================================多层nginx代理@HTML资源=======================================
#主机10.9.103.35下的nginx配置,port=8083
location ^~ /html/chat/ {#符号^~:一旦匹配到,就不继续匹配(静态资源匹配)proxy_pass http://10.9.103.36:8081/;
}#主机10.9.103.36下的nginx配置,port=8081(下图为html资源目录结构)
location /mystatic {root html;index index.html index.htm;
}

2.2 负载均衡策略

        Nginx 支持多种负载均衡策略,能够根据不同的需求选择合适的策略将请求分发到后端服务器。

名称说明
轮询默认方式
weight权重方式
ip_hash依据ip分配方式
least conn依据最少连接方式
url hash依据url分配方式
fair依据响应时间方式
2.2.1 轮询 (Round Robin)

        轮询是 Nginx 的默认负载均衡策略,将请求依次分发到每台后端服务器。该策略简单高效,适用于后端服务器性能均衡的情况。

upstream backend {server backend1.example.com;server backend2.example.com;
}
2.2.2 最少连接 (Least Connections)

        最少连接策略将请求分发到当前活动连接数最少的服务器,适用于后端服务器性能不均衡的情况。

upstream backend {least_conn;server backend1.example.com;server backend2.example.com;
}
2.2.3 IP 哈希 (IP Hash)

        IP 哈希策略根据客户端 IP 计算哈希值,将同一客户端的请求分发到同一台服务器,适用于需要会话保持的场景。

upstream backend {ip_hash;server backend1.example.com;server backend2.example.com;
}
2.2.4 权重 (Weight)

        权重策略为每台服务器设置权重,权重越高,服务器接收到的请求越多,适用于后端服务器性能不均衡且需要手动调整分配比例的情况。

upstream backend {server backend1.example.com weight=3;server backend2.example.com weight=1;
}

2.3 配置实例

        下面提供几个反向代理和负载均衡的实际配置示例,以帮助理解和应用这些概念。

2.3.1 基本反向代理配置
server {listen 80;server_name example.com;location / {proxy_pass http://backend1.example.com;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto $scheme;}
}
2.3.2 动静分离配置

        动静分离是指将动态请求和静态请求分别处理,以提高效率。Nginx 可以将静态文件请求直接由 Nginx 处理,而将动态请求转发给后端服务器。

server {listen 80;server_name example.com;location / {proxy_pass http://backend1.example.com;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto $scheme;}location /static/ {root /var/www/html;expires 30d;}
}
2.3.3 负载均衡配置
upstream backend {server backend1.example.com;server backend2.example.com;
}server {listen 80;server_name example.com;location / {proxy_pass http://backend;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto $scheme;}
}

2.4 健康检查

        Nginx 还可以对后端服务器进行健康检查,确保请求不会分发到不可用的服务器。通过配置 ngx_http_upstream_module 模块,可以实现简单的健康检查功能。

upstream backend {server backend1.example.com;server backend2.example.com;server backend3.example.com down;
}server {listen 80;server_name example.com;location / {proxy_pass http://backend;}
}

        在此配置中,backend3.example.com 被标记为 down,Nginx 将不会将请求分发到这台服务器。更高级的健康检查可以通过第三方模块如 ngx_http_upstream_check_module 实现。

2.5 高级反向代理配置

2.5.1 缓存配置

        Nginx 可以作为缓存服务器,通过缓存后端服务器的响应,减少后端服务器的负担,提升响应速度。

proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m use_temp_path=off;server {listen 80;server_name example.com;location / {proxy_cache my_cache;proxy_pass http://backend;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto $scheme;}
}
2.5.2 SSL 终止

        Nginx 可以处理 SSL/TLS 加密,解密客户端请求后将其转发给后端服务器,减轻后端服务器的加密负担。

server {listen 443 ssl;server_name example.com;ssl_certificate /etc/nginx/ssl/nginx.crt;ssl_certificate_key /etc/nginx/ssl/nginx.key;location / {proxy_pass http://backend;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto $scheme;}
}

2.6 HTTPS配置


#user  nobody;
worker_processes  1;#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;#pid        logs/nginx.pid;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"';#access_log  logs/access.log  main;sendfile        on;#tcp_nopush     on;#keepalive_timeout  0;keepalive_timeout  65;#gzip  on;server {listen       443 ssl;server_name  mt.hello.com;#ssl          on;ssl_certificate     ../ssl/nj.crt;ssl_certificate_key ../ssl/nj.key;ssl_session_cache shared:SSL:1m;ssl_session_timeout 5m;ssl_ciphers HIGH:!aNULL:!MD5;ssl_prefer_server_ciphers on;location /chat/ {proxy_pass http://jd.hello.com:8089;}}server {listen 80;#填写绑定证书的域名server_name mt.hello.com;#强制将http的URL重写成httpsrewrite ^(.*) https://$server_name$1 permanent; }server {listen       8081;server_name  mt.hello.com;location /chat/ {proxy_pass http://jd.hello.com:8089;}location /proxy/nginx/ {if ($host = 'mt.hello.com') {rewrite ^(.*)$ http://jd.hello.com/$1 permanent;}proxy_pass http://jd.hello.com:8089/;}location /proxy/ {if ($host = 'mt.hello.com') {rewrite ^(.*)$ http://www.baidu.com permanent;}proxy_pass http://jd.hello.com:8089/;}location /error/ {if ($host = 'jd.hello.com') {return 404;}proxy_pass http://jd.hello.com:8089/;}error_page 404 /404.html;error_page 500 502 503 504 /50x.html;location =/50x.html{root html;}location =/404.html{root html;}location /mystatic {root html;index index.html index.htm;}}}

3. Nginx性能优化

        Nginx 以其高性能和高并发处理能力著称,但在实际应用中,合理的性能优化策略仍能显著提升其性能。本文将详细探讨 Nginx 的性能优化方法,包括配置优化、系统优化、缓存机制和高并发优化。

3.1 配置优化

        Nginx 的配置对其性能有着至关重要的影响。合理的配置可以减少资源消耗,提高处理效率。

3.1.1 Worker 进程配置

        Nginx 的 worker_processes 参数决定了处理请求的工作进程数量。一般建议将其设置为等于服务器的 CPU 核心数,以充分利用多核 CPU 的并行处理能力。

        worker_cpu_affinity:将Nginx⼯作进程绑定到指定的CPU核⼼,默认Nginx是不进⾏进程绑定的。

# worker_processes auto;  #auto 表示自动检测 CPU 核心数,并设置相应数量的工作进程。# 找到以下两行,修改为合适的值
StartServers       8     # 初始启动的进程数
MaxRequestWorkers  150   # 最大的并发请求处理数user  nginx nginx;                 # 启动Nginx⼯作进程的⽤⼾和组
worker_processes  [number | auto]; # 启动Nginx⼯作进程的数量
worker_cpu_affinity 00000001 00000010 00000100 00001000;
# 将Nginx⼯作进程绑定到指定的CPU核⼼,默认Nginx是不进⾏进程绑定的,
# 绑定并不是意味着当前nginx进程独 占以⼀核⼼CPU,但是可以保证此进程不会运⾏在其他核⼼上,
# 这就极⼤减少了nginx的⼯作进程在不同的cpu核 ⼼上的来回跳转,减少了CPU对进程的资源分配与回收以及内存管理等,
#因此可以有效的提升nginx服务器的性 能。 此处CPU有四颗核心。也可写成:
#worker_cpu_affinity 0001 0010 0100 1000;#cpu的亲和能偶使nginx对于不同的work工作进程绑定到不同的cpu上面去。就能够减少在work间不#断切换cpu,把进程通常不会在处理器之间频繁迁移,进程迁移的频率小,来减少性能损耗。
#每个 worker 的线程可以把一个 cpu 的性能发挥到极致。所以 worker 数和服务器的 cpu 数相#等是最为适宜的。设少了会浪费 cpu,设多了会造成 cpu 频繁切换上下文带来的损耗
3.1.2 Worker 连接数配置

  worker_connections 参数决定了每个工作进程可以处理的最大连接数。为了提高并发处理能力,建议将其设置为尽可能大的值。

events {worker_connections 1024;
}

        这个配置表示每个工作进程最多可以处理 1024 个并发连接。

3.1.3 缓存配置

        Nginx 提供多种缓存机制,可以缓存后端服务器的响应,减少后端服务器的压力,提高响应速度。常用的缓存机制包括 FastCGI 缓存和代理缓存。

proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m use_temp_path=off;server {listen 80;server_name example.com;location / {proxy_cache my_cache;proxy_pass http://backend;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto $scheme;}
}

        这个配置创建了一个缓存区域 my_cache,并在反向代理时启用了缓存。

3.2 系统优化

        除了 Nginx 的配置优化,对操作系统的优化也能显著提高 Nginx 的性能。

3.2.1 文件描述符限制

        Nginx 处理大量并发连接时,需要打开大量的文件描述符。默认的文件描述符限制可能不足,需通过修改系统配置提高限制。

# 临时修改
ulimit -n 65535# 永久修改,编辑 /etc/security/limits.conf
* soft nofile 65535
* hard nofile 65535
3.2.2 TCP 连接优化

        调整 TCP 连接参数,可以减少网络延迟,提高并发处理能力。

# 调整内核参数,编辑 /etc/sysctl.conf
net.core.somaxconn = 65535
net.core.netdev_max_backlog = 65535
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.ip_local_port_range = 1024 65535
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 30# 应用配置
sysctl -p

3.3 缓存机制

        缓存是提升 Nginx 性能的重要手段。通过缓存机制,Nginx 可以将后端服务器的响应存储在本地,减少后端服务器的负载。

3.3.1 FastCGI 缓存

        FastCGI 缓存用于缓存 FastCGI 应用程序的响应,例如 PHP。

fastcgi_cache_path /var/cache/nginx levels=1:2 keys_zone=fastcgi_cache:10m inactive=60m;
fastcgi_cache_key "$scheme$request_method$host$request_uri";server {location ~ \.php$ {fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;fastcgi_index index.php;include fastcgi_params;fastcgi_cache fastcgi_cache;fastcgi_cache_valid 200 60m;fastcgi_cache_use_stale error timeout invalid_header updating;}
}
3.3.2 代理缓存

        代理缓存用于缓存反向代理的响应,减少后端服务器的负载。

proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m use_temp_path=off;server {location / {proxy_cache my_cache;proxy_pass http://backend;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto $scheme;}
}

3.4 高并发优化

        Nginx 在处理高并发连接时,通过异步非阻塞的事件驱动模型,能够高效地处理大量并发连接。以下是一些针对高并发场景的优化策略。

3.4.1 启用 keepalive

   keepalive 可以保持客户端和服务器之间的连接,提高连接重用率,减少连接建立和释放的开销。

upstream backend {server backend1.example.com;server backend2.example.com;keepalive 32;
}server {location / {proxy_pass http://backend;proxy_http_version 1.1;proxy_set_header Connection "";}
}
3.4.2 调整缓冲区大小

        调整 Nginx 的缓冲区大小,可以提高大文件传输的效率,减少内存碎片。

http {server {client_body_buffer_size 16K;client_header_buffer_size 1k;large_client_header_buffers 4 16k;output_buffers 1 32k;postpone_output 1460;}
}
3.4.3 启用 Gzip 压缩

        启用 Gzip 压缩,可以减少传输的数据量,提高响应速度。

http {gzip on;gzip_types text/plain application/xml;gzip_min_length 1000;gzip_comp_level 5;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/369532.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2024年7月6日 十二生肖 今日运势

小运播报&#xff1a;2024年7月6日&#xff0c;星期六&#xff0c;农历六月初一 &#xff08;甲辰年庚午月辛未日&#xff09;&#xff0c;法定节假日。 红榜生肖&#xff1a;猪、马、兔 需要注意&#xff1a;狗、鼠、牛 喜神方位&#xff1a;西南方 财神方位&#xff1a;正…

C# 类型转换之显式和隐式

文章目录 1、显式类型转换2. 隐式类型转换3. 示例4. 类型转换的注意事项5. 类型转换的应用示例总结 在C#编程中&#xff0c;类型转换是一个核心概念&#xff0c;它允许我们在程序中处理不同类型的数据。类型转换可以分为两大类&#xff1a;显式类型转换&#xff08;Explicit Ca…

AR视频技术与EasyDSS流媒体视频管理平台:打造沉浸式视频体验

随着增强现实&#xff08;AR&#xff09;技术的飞速发展&#xff0c;其在各个领域的应用日益广泛。这项技术通过实时计算摄影机影像的位置及角度&#xff0c;将虚拟信息叠加到真实世界中&#xff0c;为用户带来超越现实的感官体验。AR视频技术不仅极大地丰富了我们的视觉体验&a…

c++重定向输出和输出(竞赛讲解)

1.命令行重定向 在命令行中指定输出文件 指令 .\重定向学习.exe > 1.txt 效果 命令行输入和输出 指令 .\重定向学习.exe < 2.txt > 1.txt 效果 代码 #include<bits/stdc++.h> using namespace std; int n; int main(){cin>>n;for(int i=0;i<n;i…

C++ 类和对象 构造函数

一 类的6个默认成员函数&#xff1a; 如果一个类中什么成员都没有&#xff0c;简称为空类。 例&#xff1a; #include <iostream> class Empty {// 空类&#xff0c;什么成员都没有 }; 空类中真的什么都没有吗&#xff1f;并不是&#xff0c;任何类在什么都不写时&a…

如何使用 SwiftUI 构建 visionOS 应用

文章目录 前言WindowsVolumes沉浸式空间结论 前言 Apple Vision Pro 即将推出&#xff0c;现在是看看 SwiftUI API 的完美时机&#xff0c;这使我们能够将我们的应用程序适应 visionOS 提供的沉浸式世界。苹果表示&#xff0c;构建应用程序的最佳方式是使用 Swift 和 SwiftUI。…

鸿翼ECM统一AI检索应用全景,为企业打造全方位搜索服务

随着企业的发展和信息化进程的加快&#xff0c;海量数据已沉淀至企业各类系统&#xff0c;系统间信息孤立、信息利用率低、数据价值无法发挥成为制约企业发展的重要因素。如何对散落在企业各系统中的数据、内容进行统一管理和高效利用&#xff0c;实现高效精准的信息检索&#…

谷粒商城学习-07-虚拟机网络设置

文章目录 一&#xff0c;找到配置文件Vagrantfile二&#xff0c;查询虚拟机网卡地址1&#xff0c;查看虚拟机网络配置2&#xff0c;查看宿主机网络配置 三&#xff0c;修改配置文件下的IP配置四&#xff0c;重新启动虚拟机即可生效五&#xff0c;Vagrantfile 的作用1&#xff0…

Qt中使用MySQL数据库详解,好用的模块类封装

本文将详细介绍如何在Qt应用程序中集成MySQL数据库&#xff0c;并封装实现好用的mysql数据库操作类。包括环境准备、连接数据库、执行查询及异常处理等关键步骤&#xff0c;同时包含mysql驱动的编译。分享给有需要的小伙伴&#xff0c;喜欢的可以点击收藏。 目录 环境准备 项…

Pinia:Vue 2 和 Vue 3 中更好用的状态管理框架

前言 还在用Vuex? 在Vue应用程序的开发过程中&#xff0c;高效且易于维护的状态管理一直是开发者关注的核心问题之一。随着Vue 3的发布&#xff0c;状态管理领域迎来了一位新星——Pinia&#xff0c;它不仅为Vue 3量身打造&#xff0c;同时也向下兼容Vue 2&#xff0c;以其简…

《C语言》认识数据类型和理解变量

&#x1f339;个人主页&#x1f339;&#xff1a;喜欢草莓熊的bear &#x1f339;专栏&#x1f339;&#xff1a;C语言基础 目录 前言 一、数据类型的介绍 1.1 字符型 1.2 整形 1.3 浮点型 1.4 布尔类型 1.5 各种数据类型的长度 1.5.1 sizeof操作符 1.5.2 数据类型长度…

【博士每天一篇文献-算法】Adult neurogenesis acts as a neural regularizer

阅读时间&#xff1a;2023-12-20 1 介绍 年份&#xff1a;2022 作者&#xff1a;Lina M. Tran&#xff0c;Adam Santoro&#xff0c;谷歌DeepMind 期刊&#xff1a; Proceedings of the National Academy of Sciences 引用量&#xff1a;13 代码&#xff1a;https://github.c…

class类和style内联样式的绑定

这里的绑定其实就是v-bind的绑定&#xff0c;如代码所示&#xff0c;div后面的引号就是v-bind绑定&#xff0c;然后大括号将整个对象括起来&#xff0c;对象内先是属性&#xff0c;属性后接的是变量&#xff0c;这个变量是定义在script中的&#xff0c;后通过这个变量&#xff…

《昇思25天学习打卡营第10天|使用静态图加速》

文章目录 今日所学&#xff1a;一、背景介绍1. 动态图模式2. 静态图模式 三、静态图模式的使用场景四、静态图模式开启方式1. 基于装饰器的开启方式2. 基于context的开启方式 总结&#xff1a; 今日所学&#xff1a; 在上一集中&#xff0c;我学习了保存与加载的方法&#xff…

【网络安全】修改Host文件实现域名解析

场景 开发一个网站或者服务&#xff0c;需要在本地测试时&#xff0c;可以将线上的域名指向本地开发环境的IP地址。从而模拟真实环境中的域名访问&#xff0c;方便调试和开发。 步骤 1、以管理员身份打开命令提示符 2、编辑hosts文件&#xff1a; 输入以下命令打开hosts文…

六西格玛绿带培训如何告别“走过场”?落地生根

近年来&#xff0c;六西格玛绿带培训已经成为了众多企业提升管理水平和员工技能的重要途径。然而&#xff0c;不少企业在实施六西格玛绿带培训时&#xff0c;往往陷入形式主义的泥潭&#xff0c;导致培训效果大打折扣。那么&#xff0c;如何避免六西格玛绿带培训变成“走过场”…

联合概率密度函数

目录 1. 什么是概率密度由联合概率密度求概率参考链接 1. 什么是概率密度 概率密度到底在表达什么&#xff1f; 外卖在20-40分钟内送达的概率 随机变量落在[20,40]之间的概率。下图中&#xff0c;对总面积做规范化处理&#xff0c;令总面积1&#xff0c; f ( x ) f(x) f(x)则成…

交互未来入选“北京市通用人工智能产业创新伙伴计划”模型伙伴

在“开启数智新时代&#xff0c;共享数字新未来”的宏大主题下&#xff0c;2024全球数字经济大会于近日盛大开幕&#xff0c;汇聚全球智慧&#xff0c;共谋数字经济新篇章。大会首日&#xff0c;备受瞩目的人工智能专题论坛率先拉开帷幕&#xff0c;以“应用即未来——大模型赋…

基于MCU平台的HMI开发的性能优化与实战(下)

继上篇《基于MCU平台的HMI开发的性能优化与实战&#xff08;上&#xff09;》深入探讨了提升MCU平台HMI开发效率和应用性能的策略后&#xff0c;本文将专注于NXP i.MX RT1170 MCU平台的仪表盘开发实践。我们将重点介绍Qt for MCUs的优化技巧&#xff0c;展示如何通过实际案例应…

【SpringBoot】SpringBoot使用mail实现登录邮箱验证

&#x1f4dd;个人主页&#xff1a;哈__ 期待您的关注 目录 一、前期准备 1 开启邮箱服务 2 SpringBoot导入依赖 3 创建application.yml配置文件 4 创建数据库文件 5 配置redis服务 二、验证邮件发送功能 三、注册功能实现邮箱验证 1 创建User实体类 2 创建UserPa…