Nginx高并发实现原理学习

目前,互联网已经得到了广泛的普及与应用,个人电脑和移动设备的发展,使得即时信息与娱乐服务变的更加方便精巧,基础用户的不断增加使得应用访问量变得巨大。为了提供安全可靠的服务,服务器端正在面临着越来越大的压力。传统的服务器多线程业务逻辑设计在大量用户访问时支撑并发连接的能力有限,不利于构建高性能服务器架构。Nginx 作为当下的高并发连接的负载均衡服务器因其极强的性能得到广泛的使用。本文主要对高并发Nginx进行详细的介绍,重点说明使用Nginx实现Web系统的高并发的原理。

一、Web系统高并发性

(一)高并发概念

高并发在外行人眼里似乎很高大上,但其实并不难理解,它指的就是我们通过各种设计使得系统能够在同一时间并行处理很多请求。一般来说高并发是一个结果导向的东西,现实中的例子也不少。常见的高并发场景有:双11时淘宝等系统处理大量购物者的购物请求、选课时的学校选课系统、春节时12306网站处理大量的购票请求、微博出现各种惊人热搜等,高并发的概念并不是突然出现的,而是随着业务的发展而产生的需求。高并发的业务场景出现了,随之而来的就是要支持这个高并发业务场景的架构——技术要为业务服务,业务倒逼技术发展,高并发是随着业务发展的。

(二)高并发指标

接下来分析高并发的指标。高并发并不意味着仅仅只追求高性能。从宏观的角度来看,高并发系统有三个基本的设计目标,分别是高性能、高可用以及高可扩展性,而这三方面并不是孤立存在的,它们彼此之间是可以相互支撑的。

  1. 高性能:性能主要体现了系统的并行处理能力,在有限的硬件投入下,提高性能就意味着能节省成本。衡量软件性能包括了响应时间、TPS、服务器资源利用率等客观指标,也可以是用户的主观感受(从程序员、业务用户、终端用户/客户不同的视角,可能会得出不同的结论)。
  2. .高可用性:可用即表示一般情况下系统可以正常服务的时间,指系统具有较高的无故障运行能力,可用性 = 平均故障时间 / 系统总运行时间。一个全年无故障,能够正常服务;而另一个过不久就出线上事故、宕机,那么用户肯定会选择前者,另外,如果系统可用性过低,也一定会大大拖累业务。
  3. 高扩展:表示的是系统处理的扩展能力。在流量高峰时能否在短时间内完成扩容,更平稳地承接峰值流量,比如双11、微博各种惊人热搜等流量巨大时的扩展能力。面对突发流量,不可能临时改造架构,最快的方式就是增加机器来线性提高系统的处理能力。从高并发系统的整体架构角度来看,扩展的目标不仅仅是把服务设计成无状态就行了,因为当流量增加 10 倍,业务服务可以快速扩容 10 倍,但是数据库可能就成为了新的瓶颈。我们需要站在整体架构的角度,而不仅仅是业务服务器的角度来考虑系统的扩展性,所以说,数据库、缓存、依赖的第三方、负载均衡、交换机带宽等等都是系统扩展时需要考虑的因素。我们要知道系统并发到了某一个量级之后,哪一个因素会成为我们的瓶颈点,从而针对性地进行扩展[1]。

(三)高并发架构实现的方法

高并发的解决方案包括以下几种:

  • · 流量优化: 防盗链处理(把一些恶意的请求拒之门外) ·

  • 前端优化:减少HTTP请求、添加异步请求、启用浏览器的缓存和文件压缩、CDN加速、建立独立的图片服务器; ·

  • 服务端优化:页面静态化处理、并发处理、队列处理; · .

  • 数据库优化:数据库的缓存、分库分表、分区操作、读写分离、负载均衡;

  • Web服务器优化:负载均衡。[3]

以上案例总而言之在方法论上主要有两种:垂直扩展(Scale Up)与水平扩展(Scale Out)
垂直维度主要是针对单台计算机,通过升级软、硬件能力实现性能提升;水平维度则主要针对集群系统,利用合理的任务分配与任务分解实现性能的提升。垂直维度可包括以下措施:

  • 提升单机的硬件性能:通过增加内存、 CPU核数、存储容量、或者将磁盘 升级成SSD等堆硬件的方式来提升。
  • ·提升单机的软件性能:使用缓存减少IO次数,使用并发或者异步的方式增加吞吐量。

水平维度可包括以下措施:

  • ·做好分层架构:这是横向扩展的前提,因为高并发系统往往业务复杂,通过分层处理可以简化复杂问题,更容易做到水平扩展。
  • ·各层进行水平扩展:无状态水平扩容,有状态做分片路由。

业务集群通常能设计成无状态的,而数据库和缓存往往是有状态的,因此需要设计分区键做好存储分片,当然也可以通过主从同步、读写分离的方案提升读性能。[2]

用一个比喻,你想要一个人打十个人,这时候就得想办法了。第一个办法就是努力锻炼自己,然后全副武装,这就是垂直扩展;第二个办法,你一看对面人多,你叫10多个兄弟,然后你们二十个打他们十个,这就是水平扩展;此外还有第三个不常用的办法,你找个门把住,每次就放一个大汉进来,打倒一个再放下一个,这个就是削峰限流的做法。
从上面举的例子容易看出,垂直维度方案比较适合业务阶段早期和成本可接受的阶段,该方案是提升性能最简单直接的方式,但是受成本与硬件能力天花板的限制。而水平维度方案所带来的好处一般在业务发展的后期才能体现出来,但是没有垂直方案的天花板问题。一旦达到一定的业务阶段,水平维度是技术发展的必由之路。

本文主要从理论层面研究水平维度上利用Nginx在web服务器上来实现一定的高并发的原理。

二、Nginx实现高并发

Nginx是一款是由程序设计师Igor Sysoev所开发的高性能的 Web和 反向代理服务器,也是一个 IMAP/POP3/SMTP 代理服务器,以其高性能,稳定性,丰富的功能,简单的配置和低资源消耗而闻名。很多高知名度的网站都使用 Nginx,比如:Netflix,GitHub, SoundCloud, MaxCDN 等。[4]在高连接并发的情况下,Nginx是Apache服务器不错的替代品。Nginx的内存占用少,启动极快,高并发能力强,在互联网项目中广泛应用。官方测试Nginx能够支撑5万并发链接,并且CPU、内存等资源消耗却非常低,运行非常稳定。
Nginx的主要着眼点就是其高性能以及对物理计算资源的高密度利用,因此其采用了不同的架构模型。受启发于多种操作系统设计中基于“事件”的高级 处理机制,Nginx采用了模块化、事件驱动、异步、单线程及非阻塞的架构,并大量采用了多路复用及事件通知机制。在Nginx中,连接请求由为数不多的几个仅包含一个线程的进程worker以高效的回环(run-loop)机制进行处理,而每个worker可以并行处理数千个的并发连接及请求。[5]

(一) Nginx实现高并发的整体架构

Nginx 启动时,会生成两种类型的进程,一个是主进程 (master),一个或多个工作进程(worker),因此,Nginx 启动以后,查看操作系统的进程列表,我们就能看到至少有两个Nginx进程。master进程并不处理网络请求,主要负责调度和监控工作进程,接收外部的操作(信号),服务器实际处理网络请求及响应的是工作进程,在类 unix 系统上,Nginx可以配置多个工作进程,而每个工作进程都可以同时处理数以千计的网络请求,而工作进程包括核心和功能性模块,核心模块负责维持一个运行循环,执行网络请求处理的不同阶段的模块功能,也使得我们可以根据需要对功能模块进行适当的选择和修改,编译成具有特定功能的服务器。

(二) Nginx实现高并发的模块化设计

高度模块化的设计是 Nginx 的架构基础。1.核心模块:Nginx 服务器正常运行必不可少的模块,提供错误日志记录、配置文件解析、事件驱动机制、进程管理等核心功能。2.标准 HTTP 模块提供 HTTP 协议解析相关的功能。3.可选HTTP模块主要用于 扩展 标准的 HTTP 功能,让 Nginx 能处理一些特殊的服务。4.邮件服务模块主要用于支持 Nginx 的 邮件服务。5.第三方模块是为了扩展 Nginx 服务器应用,完成开发者自定义功能。Nginx服务器被分解为多个模块 ,每个模块就是一个功能模块 ,只负责自身的功能,模块之间严格遵循 “高内聚,低耦合”的原则,这有利于高并发的实现。[6]

(三) Nginx实现高并发的请求方式处理

Nginx结合多进程机制和异步机制中的异步非阻塞方式。
服务器每当收到一个客户端时,就有服务器主进程生成一个子进程出来和客户端建立连接进行交互,直到连接断开,该子进程就结束了。使用多进程的好处是各个进程之间相互独立,不需要加锁,减少了使用锁对性能造成影响,同时降低编程的复杂度,降低开发成本。其次,采用独立的进程,如果一个进程发生异常退出时,其它进程正常工作, master进程则很快启动新的工作进程,确保服务不会中断,从而将风险降到最低。
每个工作进程使用异步非阻塞方式,可以处理多个客户端请求。当某个工作进程接收到客户端的请求以后,调用 IO 进行处理,如果不能立即得到结果,就去处理其他请求(非阻塞),而客户端在此期间也无需等待响应,可以去处理其他事情(异步)当IO返回时,就会通知此工作进程,该进程得到通知,暂时挂起当前处理的事务去响应客户端请求。Nginx 的异步非阻塞工作方式正把当中的等待时间利用起来了。在需要等待的时候,这些进程就空闲出来待命了,因此表现为少数几个进程就解决了大量的并发问题。

(四) Nginx实现高并发的进程处理模型

Nginx 在启动后,会有一个主进程和多个相互独立的工作进程,主进程负责接收来自外界的信号,向各工作进程发送信号,每个进程都有可能来处理这个连接。主进程能监控工作进程的运行状态,当工作进程由于异常情况退出后,会自动启动新的工作进程。每进来一个请求,会有一个工作进程去处理。但不是全程的处理,处理到可能发生阻塞的地方,比如向上游(后端)服务器转发请求,并等待请求返回。那么,这个处理的工作不会这么傻等着,他会在发送完请求后,注册一个事件:“如果upstream返回了,告诉我一声,我再接着干”。于是他就休息去了。此时,如果再有请求进来,他就可以很快再按这种方式处理。而一旦上游服务器返回了,就会触发这个事件,工作才会来接手,这个请求才会接着往下走。
由于web server的工作性质决定了每个请求的大部份生命都是在网络传输中,实际上花费在server机器上的时间片不多,这就是为什么几个进程就解决了高并发。每个工作进程都是独立的进程,不共享资源,不需要加锁。采用独立的进程,可以让互相之间不会影响,一个进程退出后,其它进程还在工作,服务不会中断,主进程则很快重新启动新的工作进程。而且 Nginx为了更好的利用多核特性,提供CPU亲缘性的绑定选项,我们可以将某一个进程绑定在某一个核上,这样就不会因为进程的切换 带来 Cache 的失效对于每个请求,有且只有一个工作进程对其处理。[9]

(五) Nginx实现高并发的反向代理与负载均衡

反向代理方式是指以代理服务器来接收internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给Internet上请求连接的客户端,此时代理服务器对外就表现为一个反向代理服务器。反向代理隐藏了真实的服务端,当我们请求 www.baidu.com 的时候,就像拨打 10086 一样,背后可能有成千上万台服务器为我们服务,但具体是哪一台,你不知道,也不需要知道,你只需要知道反向代理服务器是谁就好了,www.baidu.com 就是我们的反向代理服务器,反向代理服务器会帮我们把请求转发到真实的服务器那里去。Nginx 就是性能非常好的反向代理服务器,用来做负载均衡。
而什么是负载均衡呢?随着请求数的快速增长,单服务器已经无法承担大量用户的并发访问,这个时候,就需要建立服务器集群,来让多台服务器协同工作,提高整体项目的吞吐量和QPS。假设一台设备资源占有率已经饱和,而另一台服务器却只有零星几个请求处理,这显然是不合理的。我们期望多台服务器需要平均承担客户端发来的请求,使每台机器都充分利用。这时,我们就需要用到一种技术,叫做负载均衡。负载均衡是多台服务器组合为一个集群,其中每台机器可以单独运行,服务器之间地位相同,通过负载均衡技术,将客户端发来的请求平均分配到每台服务器中,使得项目的负载能够均衡的分布,每台服务器的资源使用量也基本相同。通过负载均衡技术,使得项目巨额访问量从单台服务器均匀的分摊到每台服务器上。[10][12]
Nginx对外表现为服务器, 当接受到客户端的HTTP请求时, 并不产生响应, 但也不同于Squid等其他服务器直接转发, 而是会将用户发来的请求缓存一份, 然后再通过负载均衡算法将完整的请求缓存从它的上游集群服务器中选择合适的进行转发, 而上游服务器处理请求生成的响应会直接转发给Nginx, 此时Nginx会边接受边将响应转发给客户, 而不是完整地缓存到响应再一并转发。这正是Nginx作为反向代理服务器的优势所在。[15]
Nginx负载均衡主要有三种策略。

  • 轮循(默认):Nginx根据请求次数,将每个请求均匀分配到每台服务器
  • 最少连接:将请求分配给连接数最少的服务器。Nginx会统计哪些服务器的连接数最少。
  • ·IP Hash:绑定处理请求的服务器。第一次请求时,根据该客户端的IP算出一个HASH值,将请求分配到集群中的某一台服务器上。后面该客户端的所有请求,都将通过HASH算法,找到之前处理这台客户端请求的服务器,然后将请求交给它来处理。[16][18]

负载均衡对实现高并发有很大作用。
一是转发功能按照一定的算法,将客户端请求转发到不同应用服务器上,减轻单个服务器压力,提高系统并发量。
二是故障移除:通过心跳检测的方式,判断应用服务器当前是否可以正常工作,如果服务器期宕掉,自动将请求发送到其他应用服务器。
第三,恢复添加:如检测到发生故障的应用服务器恢复工作,自动将其添加到处理用户请求队伍中。

通过以上分析可以发现Nginx对比apache服务器的诸多优点。

  • Nginx 更主要是作为反向代理,而非Web服务器使用。
  • Nginx是事件驱动服务器,最适合做的就是这种 I/O 密集型工作,如反向代理。因为进程在一个地方进行计算时,那么这个进程就不能处理其他事件了。
  • Nginx 只需要少量进程配合事件驱动,而不像 Apache 多进程模型那样大量的进程数。
  • Nginx处理静态文件效果也很好,那是因为读写文件和网络通信其实都是 I/O操作,处理过程一样。

三、总结

本文介绍了高并发的各种概念以及指标,接着说明了Nginx实现高并发的一些原理,并且对比apache服务器,就Nginx在实现高并发方面的诸多优点进行了分析说明。
当然本文只是在原理上做了一些分析,在实际中,高并发没有具体的标准,业务场景不一样,执行复杂度不一样,单看并发量也没有意义,必须结合具体场景进行判断。举个例子,访问百度首页通常情况下都是鼠标点击一下就看到结果了,几乎感觉不到等待时间,且百度每秒处理的访问量也非常的大,而如果支付宝扫描二维码支付,通常需要等较久的时间,这就是业务场景上的差距。再比如配置上的不同,用高配物理机得出的数据和最老最低配的虚拟器上的出来的结果是无法比较的。总之,高并发的本质不是多大算高并发的一个数字,而是从架构上、设计上、编码上怎么来保证或者解决由并发引起的问题。高并发的实际要求以及实现远远不止以上说到的内容,Nginx的实现也有更多的方法,往往要根据处理的业务场景和实际的设备以及要求做出灵活应变。

参考文献

[1]冰河 海量数据处理与大数据技术实战 北京大学出版社2020-08-01
[2]李运华《从零开始学架构》 2021-01-23
[3]张开涛 亿级流量网站架构核心技术 电子工业出版社2017年
[4]吴宝花 基于Nginx的服务器集群负载均衡策略研究与优化[D].南昌大学,2020.
[5]吴翰清 《白帽子讲Web安全 》2012年电子工业出版社
[6]杜星. 轻量级Web服务器Nginx的理论与技术研究[D].南京邮电大学,2016.
[7]吴陈. 基于Nginx的服务器集群负载均衡策略的研究与改进[D].华南理工大学,2020.
[8]刘佳祎,崔建明,智春.基于Nginx服务器的动态负载均衡策略[J].桂林理工大学学报,2020,40(02):403-408.
[9]张泽宇. VPPNGX:基于FD.io VPP的高性能Nginx实现[D].上海交通大学,2020.
[10]刘茜. 一种基于Nginx负载均衡软件技术实现方法[A]. 天津市电子学会、天津市仪器仪表学会.第三十三届中国(天津)2019’IT、网络、信息技术、电子、仪器仪表创新学术会议论文集[C].天津市电子学会、天津市仪器仪表学会:天津市电子学会,2019:4.
[11]刘金秀,陈怡华,谷长乐.基于Nginx的高可用Web系统的架构研究与设计[J].现代信息科技,2019,3(11):94-97.
[12]林丽丽.使用高性能Web服务器Nginx实现开源负载均衡[J].大众科技,2010(07):37-38+27.
[13]许诺.大数据下基于Nginx负载均衡的教务系统优化设计[J].信息技术与信息化,2021(06):191-193.
[14]李刚.Nginx负载均衡技术在高校教务系统中的应用[J].辽宁师专学报(自然科学版),2020,22(03):19-22+32.
[15]赵凯.一种基于Nginx反向代理机制的微服务负载均衡方法分析[J].无线互联科技,2020,17(16):140-141.
[16]刘旻昊.Nginx服务器“秘籍”[J].中国传媒科技,2018(04):13-14.
[17]马原龙. Nginx负载均衡技术研究[D].重庆邮电大学,2016.
[18]王艳,陈卫卫.基于Nginx替代Apache在高并发WEB负载均衡系统中的应用[J].电子测试,2015(06):88-92.
[19]Castien René F,Coppieters Michel W,Durge Tom S C,ScholtenPeeters Gwendolyne G M. High concurrent validity between digital and analogue algometers to measure pressure pain thresholds in healthy participants and people with migraine: a cross-sectional study.[J]. The journal of headache and pain,2021,22(1):
[20]Wang Ling. Design and Implementation of Online Exam Platform Based on High-Concurrency Processing Mode[J]. International Journal of Computational and Engineering,2021,6(2):
[21]赵俊哲. 网络流量高并发优化处理研究[D].南京邮电大学,2020.

猜你喜欢

转载自blog.csdn.net/qq_45808700/article/details/128710270