当前位置: 首页 > news >正文

Nginx底层架构(非常清晰)

目录

前言:

场景带入:

HTTP服务器是什么?

反向代理是什么?

模块化网关能力:

1.配置能力:

2.单线程:

3.多worker进程

4.共享内存:

5.proxy cache

6.master进程

最后:


前言:

在互联网流量呈指数级增长的今天,如何用有限的资源支撑百万级并发请求,是每个后端开发者必须面对的挑战。作为全球最受欢迎的高性能Web服务器之一,Nginx以不足2MB的内存占用轻松处理万级连接,其设计哲学堪称分布式系统的典范。
本文将深入Nginx的多进程架构事件驱动模型,揭开其“用最少的资源做最多的事情”的奥秘。从惊群效应的优雅规避,到SO_REUSEPORT的现代负载均衡策略,我们将通过源码级视角,解析Nginx如何在操作系统内核与用户态代码之间编织出一张高效网络。无论你是想优化现有服务,还是探索服务器编程的艺术,这趟旅程都将为你打开一扇新世界的大门。

场景带入:

      你是一个程序员,你在本地写了一个html文件,将他拖入到浏览器,就可以通过浏览器渲染出相应的数据。

    但这只是本地的,自己写的数据,我们在浏览器上访问到的数据和页面,都是通过,远端服务器传送到我们的客户端的。那二者之间是如何进行数据传输的呢?没有什么是加一层中间层不能解决的。如果有,那就再加一层,这次我们要加的中间层是nginx。

HTTP服务器是什么?

我们想要在远端服务器上拿到数据,就让远端服务器创建一个进程,并且让他对外提供HTTP服务,也就是提供一个URL。当用户在客户端输入这个URL时,比如(www.baidu.com),那客户端会对远端服务器发送一个HTTP请求,当远端服务器收到这个请求时,就会响应相应的数据。浏览器进行解析与展示,这就完成了一次普通的网页访问。

反向代理是什么?

一个完整的产品,它不止有前端页面,他还有后端服务。

前端需要时刻对后端请求最新数据。

此时,流量小的时候,压力并不大,后端服务还能轻松完成任务,不过流量一旦大起来,前端页面对后端的请求就会变多,那此时我们只能增多后端服务的数量,来完成对这些请求的处理,但是问题来了,后端服务多了,每个后端服务都有对应的IP与端口,前端就不知道该访问哪个服务了。还是那句话,没有什么是加一层中间层不能解决的。中间加一个进程,对外提供一个域名,当这些前端请求打过来的时候,这个进程就负责把这些请求均匀的转发给每个服务,让每个服务都能处理请求,这就是负载均衡。像这种屏蔽掉背后具体有哪些服务器的代理方式,我们就叫他反向代理

有了它,我们就可以对外只提供一个URL的域名。我们就可以根据需要,随时扩缩后端服务的数量

那我们这个反向代理就可以加在我们之前提到的远端服务器的那个进程上,这样不仅可以为前端提供HTTP服务,还可以将请求分给后端服务器。

模块化网关能力:

既然它是一个中间层,且会有大量的流量穿过它,那他高低也算个网关了。

那么我们就可以在他上面加入一些通用网关的功能,比如: 

1.日志:我们就可以记录每次调用的结果,方便后续排查问题;

2.压缩:我们就可以对输入输出内容进行压缩,减少网络带宽消耗;

3.限流与封禁:主要是对某个模块进行限流和封禁;

4.修改内容:修改输入输出的内容;

5.自定义:自己根据需要开发新的功能;

还可以添加新的协议如:HTTP,HTTP2,TCP,UDP,Websocket。 

1.配置能力:

前面提到那么多种能力,用户肯定不会全部用上,所以需要有个地方来让人选择用那些能力,于我们可以加个配置文件,也就是Nginx.conf,然后,用户在配置文件上选择自己想要的功能。

2.单线程:

这个网关需要有这个多的前端请求打过来,如果每个请求都要开一个单独的进程,那么开销会很大,那么只需要将这些请求的线程都塞到一个单线程里头去,就能避免并发问题和线程开销。

3.多worker进程

但单个网关进程要单线程处理这么多的网络流量,即使处理的再快,当有海量数据时,依然压力会很大。那么我们此时就将一个网关进程变成多个网管进程,我们叫他Worker进程,每个进程之间互不干扰。让多个进程监听一个端口,一有流量进来,我们就分给每个进程,将进程数量设置成和操作系统CPU核数一致,那每个进程都能够得到一个核,那这里就能让效率最大化。

问题来了:这么多的work进程监听同一个端口,不会造成端口冲突吗?

在传统的多进程服务器模型中(如Nginx的早期版本),通常由主进程(Master Process)创建并绑定监听套接字(Socket),随后通过fork()派生出多个Worker子进程。此时:

  • 共享文件描述符:所有Worker进程继承同一个监听套接字,而非各自独立创建新套接字。因此,它们实际上共享同一个内核套接字对象,不存在多个套接字绑定同一端口的问题。

  • 内核负载均衡:当新连接到达时,操作系统内核会选择一个处于accept()状态的Worker进程来处理连接。这种方式称为“惊群效应”优化后的负载均衡(现代内核如Linux通过EPOLLEXCLUSIVE等机制避免多个进程被同时唤醒)。

4.共享内存:

前端页面发来的请求都会打到worker进程上,那如果说要限流这样的要计数的功能,每个worker上的计数都不一样,这个时候我们就要创建一个共享内存了,每一个worker进程都共有一个内存,这样就能保证多个进程之间做逻辑,这样就能保证系统数据的一致性。

5.proxy cache

前端发送请求给后端,后端响应结果返回给前端,此时,每次的请求都要重复这一过程,那能不能像redis一样设置中间层,将查询的结果暂存,下次在查询时就能直接拿了。我们只需要准备一些磁盘文件,将查询的数据放在那里就可以了。注意:不能放在共享内存里,内存太贵了

6.master进程

每个worker会分走一部分流量,如果功能更新,所有的worker同时重启,上面的网络连接就会全部断掉。那么我们此时创建一个新的进程,让他读取前面的Nginx.conf文件,让他统一管理各个worker进程,解决谁先连谁后连的问题。

最后:

在数字世界的汪洋中,每一次TCP握手都是浪花,每一个HTTP请求皆是潮汐。Nginx像一位冷静的船长,用事件驱动的罗盘指引着数据洪流的航向。当我们惊叹于它举重若轻的并发处理能力时,或许更应该思考:在摩尔定律逐渐失效的今天,软件架构的智慧是否比硬件堆砌更具生命力?
下次当你看到Nginx的羽毛Logo时,愿你能听见多进程协同工作的交响,看见操作系统内核与现代软件设计的共舞。在技术的星辰大海中,Nginx永远是最可靠的灯塔之一——因为它告诉我们,真正的力量,往往藏匿于简洁之中。

相关文章:

  • redis系列--1.redis是什么
  • qt(vs2010) 手动配置moc生成规则
  • 数据大屏只能撑撑场面?
  • Uniapp:本地存储
  • 卫星电话扬帆智慧海洋,构筑蓝海通信新生态
  • 48V/2kW储能电源纯正弦波逆变器详细设计方案-可量产
  • 【7】深入学习Buffer缓冲区-Nodejs开发入门
  • CS5346 - Annotation in Visualization (可视化中的注释)
  • 【Python爬虫】简单案例介绍3
  • 详细解读 box-sizing: border-box;
  • 大模型——Crawl4AI入门指南
  • 【高性能缓存Redis_中间件】三、redis 精通:性能优化与生产实践
  • 从零开始:前端开发者的SEO优化入门与实战
  • 如何在服务器上搭建mail服务器邮件服务器
  • obsidian写文章的图床设置方法
  • 应用分享:基于 Grounding DINO 的智能膳食助手如何推进健康信息学发展
  • Qt样式表(窗口、按钮之类,有图片和代码详细注释)
  • Windows单机模拟MySQL主从复制
  • Spring MVC 全栈指南:RESTful 架构、核心注解与 JSON 实战解析
  • 什么是Lodash
  • 林诗栋4比1战胜梁靖崑,晋级世界杯男单决赛将和雨果争冠
  • 特朗普就防卫负担施压日本,石破茂:防卫费应由我们自主决定
  • 上海召开全市加强社会治安综合治理中心规范化建设工作推进会
  • 体坛联播|中国U16女足击败墨西哥,王星昊首获世界冠军
  • 三一重工去年净利增逾三成至59.75亿,拟分红超30亿元
  • 北京一季度GDP为12159.9亿元,同比增长5.5%