教育培训 > nginx为什么性能这么优越?

nginx为什么性能这么优越?

2020-08-19 16:24阅读(73)

nginx为什么性能这么优越?:所谓没有对比就没有伤害!在nginx横空出世之前,Apache服务器一直占据web服务器的垄断地位,所以就用对比的方式来:-nginx,优越,性

1

所谓没有对比就没有伤害!

在nginx横空出世之前,Apache服务器一直占据web服务器的垄断地位,所以就用对比的方式来解释nginx那么强!

两者性能差别的主要原因在于网络IO模型选择不同,apache使用了select,而nginx使用了epoll模型!

举个例子:一个万人村里面选村长,有两种方式:

①,让每个人在纸条上写下自己的名字,然后前村长去收集纸条(一个线程去遍历),然后得到村长推荐候选人的名单(需要处理的连接),这就相当于select模型,去轮询每一个连接,并对需要进行处理的连接进行处理!

②,每个人都可以毛遂自荐(每个连接都有可能活跃),想要竞选的在旁边站成一排(事件触发,放入队列中),然后就在这几个人中选择(几个待处理的任务),相当于只要对少量的事件进行处理!

一个是从上万人中循环得到几个进行处理,一个是几个自己站出来直接处理,这种效率相差不是一般的大吧?

nginx是基于epoll模型开发的,而epoll是基于JAVA NIO的同步非阻塞开发,在高并发情况下能支持更多的连接!

nginx是事件驱动的,一个主进程跟多个工作进程组成的工作模式,主线程负责循环分配事件,多个工作线程负责事件的处理!

我们通常使用nginx做什么呢?

nginx作为高性能的http服务器和反向代理服务器,通常用做负载均衡组件,负责接受大量的连接然后基于一定的规则(轮询,权重等)分发连接给不同的应用服务器进行处理!

而且负载均衡配置十分简单,只需要在安装好nginx之后,通过修改配置文件nginx.conf,将不同的连接分发到不同的服务器上(通过配置server),配置十分简单!

一般来说,企业中使用nginx作为负载均衡组件的场景还是很多的,同时为了避免单点故障带来的不稳定性,通常会使用keepalive搭建高可用的集群方案!

nginx搭建比较简单,大家自己可以多玩一玩!更多的技术分享,敬请关注。。。

2

看到下面回答中“nginx是基于epoll模型开发的,而epoll是基于JAVA NIO的同步非阻塞开发“,忍不住想这回答还真是无畏啊,错的离谱,竟还有那么多点赞。应该说Epoll机制仅仅是nginx在Linux上实现事件驱动的一种技术而已,说nginx基于epoll开发那就错了,说nginx基于java nio开发就更不知所云了。

当我们说性能优越的时候,我们在说什么呢?首先让我们看看有哪些衡量性能的性能指标吧。

性能指标一般包括响应时间、吞吐量、并发用户数等。

响应时间指功能完成的时间,和客观环境、数据量级、主观感受等都有关系。客观环境中硬件包括服务器配置、客户端机器配置等,软件包括数据库部署方式、客户端使用的浏览器等,另外还有网络环境。

吞吐量是给定时间内系统可处理的事务/请求的数量等,例如网络传输的数据流量。这个指标对于互联网软件更为关键,目前我们尚未进行定量分析和测试。

并发用户数用来衡量系统的同步协调能力,我们更关注多个用户同时操作同一功能或数据时,对系统性能的影响。

总的来说,nginx的性能是指其低延迟、高吞吐、高并发能力。

下面我们就从架构设计的角度,来分析nginx是如何做到低延迟、高吞吐、高并发能力的。

Nginx采用一个Master管理进程,多个worker工作进程的设计方式。如下图所示,Master进程管理了完全相同的worker进程,一个cache manager进程和cache loader进程。

这种多进程的架构可以充分利用多核系统的并发处理能力。同时,多个worker进程间可以实现负载均衡,一个请求到来时更容易被分配到负载较轻的worker进程中处理。这将降低请求的延迟,也提高了网络处理的性能。

Nginx进程内部采用了非阻塞方式的事件驱动架构模式,这也是Nginx不同于传统Web服务器的地方。传统的Web服务器而言,采用的所谓事件驱动往往局限于TCP建立连接、关闭事件上,一个连接建立以后,在关闭之前的所有操作都不再是事件驱动,这时会退化成按序执行每个操作的批处理模式,这样每个请求在连接建立之后都将始终占用系统资源,直到关闭才会释放。

nginx的异步事件驱动实际上是请求的多阶段异步处理的过程。nginx实际把请求处理流程划分为了11个阶段,这样划分的原因是将请求的执行逻辑细分,各阶段按照处理时机定义了清晰的执行语义,开发者可以很容易分辨自己需要开发的模块应该定义在什么阶段。

nginx做为一个异步高效的事件驱动型web服务器,在linux平台中当系统支持epoll时nginx默认采用epoll来高效的处理事件。Epoll实际上是 poll 的一种改进,它可以处理大批量的句柄。而 poll 又是select 的一种改进。在select 中对所打开的文件描述符个数有一定的限制,该限制由 FD_SETSIZE 设置(一般为 1024 或 2048), 而且内核中的 select 的实现是采用轮询来处理描文件描述符集,因此效率低。当文件描述符集中的某个描述符处于可读、可写或异常状态时,select 采用内存拷贝方法通知用户空间。因此, 在select 模型中文件描述符个数受限且效率低的问题就很明显。为了解决select 对文件描述符个数的限制,采用了 poll 模型,但是 poll 依然不能解决 select 的效率问题。所以,最终epoll 模型重新对poll 模型进行改进 。

epoll 的优点如下所示:

  • 处理大批量文件句柄:一个进程可以处理大批量的文件句柄,可处理文件描述符的个数远大于 2048;

  • 高效率:内核实现中 epoll 是根据每个描述符上面的回调函数实现的,并且只有处于活动状态的套接字才会主动调用该回调函数,其他不活动的套接字并不会去调用,因此,epoll 不必扫描整个文件描述符集,只需要扫描处于活动状态的文件描述符。所有大大减低了效率。
  • 加快内核与用户的消息传递:epoll 是通过内核与用户空间mmap 同一块内存实现内核与用户之间消息的传递。
  • 内核微调:可以根据运行时所需内存动态调整内存大小。


Nginx的高性能有赖于其高效内存管理,下面我们看看其内存池设计。

Nginx 使用内存池对内存进行管理,把内存分配归结为大内存分配和小内存分配。若申请的内存大小比同页的内存池最大值 max 还大,则是大内存分配,否则为小内存分配。

  1. 大块内存的分配请求不会直接在内存池上分配内存来满足请求,而是直接向系统申请一块内存(就像直接使用 malloc 分配内存一样),然后将这块内存挂到内存池头部的 large 字段下。
  2. 小块内存分配,则是从已有的内存池数据区中分配出一部分内存。

这样设计的好处就是减少了内存碎片,提升了内存分配的效率。

总结一下,nginx优越的性能得益于其多进程、异步事件处理的架构,得益于其高效的内存管理。


本回答的内容参考了nginx官网上的内容,截图也来自于https://www.nginx.com/blog/inside-nginx-how-we-designed-for-performance-scale/

3

这个问题要从本质来看,NGINX本质上是不实现业务的,不是容器,而是一个看门+转发的服务器,这个定位决定了NGINX可以做得高效,如果不是NGINX,也会有另一个服务器来实现得这么高效。

1.NGINX

采用了的构架极其简单,采用了多进程,每个进程的核心业务其实是单线程的,在执行上,代码逻辑可以极其简化。同时也可以把多核机器的性能发挥出来。

2.采用了EPOLL的这个异步IO模型,在面对大并发时,系统在处理网络事件上,占用的CPU极低,为高性能提供了可能。

3.在内存使用上,NGINX不像传统的写法,在池里面分配,然后再释放,而是为每个连接生成一个临时池,这个池上的申请小块内存不进锁,同时这个池上的内存也不释放,而是在完成请求后,这个池一次性释放。

4

我做过深入测试,windows下面最强者是iis,linux下最强者是nginx,nginx在win下性能很差,还不如apache

5





想必大家一定听说过 Nginx,若没听说过它,那么一定听过它的\"同行\"Apache 吧!


Nginx 的产生


Nginx 同 Apache 一样都是一种 Web 服务器。基于 REST 架构风格,以统一资源描述符(Uniform Resources Identifier)URI 或者统一资源定位符(Uniform Resources Locator)URL 作为沟通依据,通过 HTTP 协议提供各种网络服务。



然而,这些服务器在设计之初受到当时环境的局限,例如当时的用户规模,网络带宽,产品特点等局限并且各自的定位和发展都不尽相同。这也使得各个 Web 服务器有着各自鲜明的特点。


Apache 的发展时期很长,而且是毫无争议的世界第一大服务器。它有着很多优点:稳定、开源、跨平台等等。



它出现的时间太长了,它兴起的年代,互联网产业远远比不上现在。所以它被设计为一个重量级的。



它不支持高并发的服务器。在 Apache 上运行数以万计的并发访问,会导致服务器消耗大量内存。



操作系统对其进行进程或线程间的切换也消耗了大量的 CPU 资源,导致 HTTP 请求的平均响应速度降低。



这些都决定了 Apache 不可能成为高性能 Web 服务器,轻量级高并发服务器 Nginx 就应运而生了。



俄罗斯的工程师 Igor Sysoev,他在为 Rambler Media 工作期间,使用 C 语言开发了 Nginx。



Nginx 作为 Web 服务器一直为 Rambler Media 提供出色而又稳定的服务。然后呢,Igor Sysoev 将 Nginx 代码开源,并且赋予自由软件许可证。



由于以下这几点,所以,Nginx 火了:



  • Nginx 使用基于事件驱动架构,使得其可以支持数以百万级别的 TCP 连接。
  • 高度的模块化和自由软件许可证使得第三方模块层出不穷(这是个开源的时代啊)。
  • Nginx 是一个跨平台服务器,可以运行在 Linux、Windows、FreeBSD、Solaris、AIX、Mac OS 等操作系统上。
  • 这些优秀的设计带来的极大的稳定性。




Nginx 的用武之地


Nginx 是一款自由的、开源的、高性能的 HTTP 服务器和反向代理服务器;同时也是一个 IMAP、POP3、SMTP 代理服务器。


Nginx 可以作为一个 HTTP 服务器进行网站的发布处理,另外 Nginx 可以作为反向代理进行负载均衡的实现。



关于代理



说到代理,首先我们要明确一个概念,所谓代理就是一个代表、一个渠道;此时就涉及到两个角色,一个是被代理角色,一个是目标角色。


被代理角色通过这个代理访问目标角色完成一些任务的过程称为代理操作过程;如同生活中的专卖店,客人到 adidas 专卖店买了一双鞋,这个专卖店就是代理,被代理角色就是 adidas 厂家,目标角色就是用户。



正向代理



说反向代理之前,我们先看看正向代理,正向代理也是大家最常接触到的代理模式,我们会从两个方面来说关于正向代理的处理模式,分别从软件方面和生活方面来解释一下什么叫正向代理。


在如今的网络环境下,我们如果由于技术需要要去访问国外的某些网站,此时你会发现位于国外的某网站我们通过浏览器是没有办法访问的。


此时大家可能都会用一个操作 FQ 进行访问,FQ 的方式主要是找到一个可以访问国外网站的代理服务器,我们将请求发送给代理服务器,代理服务器去访问国外的网站,然后将访问到的数据传递给我们!


上述这样的代理模式称为正向代理,正向代理最大的特点是客户端非常明确要访问的服务器地址;服务器只清楚请求来自哪个代理服务器,而不清楚来自哪个具体的客户端;正向代理模式屏蔽或者隐藏了真实客户端信息。彻底理解正向代理和反向代理,这篇看下。


来看个示意图(我把客户端和正向代理框在一块,同属于一个环境,后面我有介绍):

客户端必须设置正向代理服务器,当然前提是要知道正向代理服务器的 IP 地址,还有代理程序的端口。



如下图:

总结来说:正向代理,\"它代理的是客户端\",是一个位于客户端和原始服务器(Origin Server)之间的服务器,为了从原始服务器取得内容,客户端向代理发送一个请求并指定目标(原始服务器)。


然后代理向原始服务器转交请求并将获得的内容返回给客户端。客户端必须要进行一些特别的设置才能使用正向代理。



正向代理的用途:

  • 访问原来无法访问的资源,如 Google。
  • 可以做缓存,加速访问资源。
  • 对客户端访问授权,上网进行认证。
  • 代理可以记录用户访问记录(上网行为管理),对外隐藏用户信息。


反向代理


明白了什么是正向代理,我们继续看关于反向代理的处理方式,举例如我国的某宝网站,每天同时连接到网站的访问人数已经爆表,单个服务器远远不能满足人民日益增长的购买欲望了。


此时就出现了一个大家耳熟能详的名词:分布式部署;也就是通过部署多台服务器来解决访问人数限制的问题。


某宝网站中大部分功能也是直接使用 Nginx 进行反向代理实现的,并且通过封装 Nginx 和其他的组件之后起了个高大上的名字:Tengine。


有兴趣的童鞋可以访问 Tengine 的官网查看具体的信息:

http://tengine.taobao.org/


那么反向代理具体是通过什么样的方式实现的分布式的集群操作呢,我们先看一个示意图(我把服务器和反向代理框在一块,同属于一个环境,后面我有介绍):

通过上述的图解大家就可以看清楚了,多个客户端给服务器发送的请求,Nginx 服务器接收到之后,按照一定的规则分发给了后端的业务处理服务器进行处理了。超详细 Nginx 极简教程,傻瓜一看也会。


此时请求的来源也就是客户端是明确的,但是请求具体由哪台服务器处理的并不明确了,Nginx 扮演的就是一个反向代理角色。


客户端是无感知代理的存在的,反向代理对外都是透明的,访问者并不知道自己访问的是一个代理。因为客户端不需要任何配置就可以访问。


反向代理,\"它代理的是服务端\",主要用于服务器集群分布式部署的情况下,反向代理隐藏了服务器的信息。


反向代理的作用:

  • 保证内网的安全,通常将反向代理作为公网访问地址,Web 服务器是内网。
  • 负载均衡,通过反向代理服务器来优化网站的负载。


项目场景



通常情况下,我们在实际项目操作时,正向代理和反向代理很有可能会存在同一个应用场景中,正向代理代理客户端的请求去访问目标服务器,目标服务器是一个反向单利服务器,反向代理了多台真实的业务处理服务器。



另外,关注微信公众号:Java技术栈,在后台回复:架构,可以获取我整理的 N 篇最架构教程,都是干货。


具体的拓扑图如下:

截了一张图来说明正向代理和反向代理二者之间的区别,如下图:

图解:

  • 在正向代理中,Proxy 和 Client 同属于一个 LAN(图中方框内),隐藏了客户端信息。
  • 在反向代理中,Proxy 和 Server 同属于一个 LAN(图中方框内),隐藏了服务端信息。


实际上,Proxy 在两种代理中做的事情都是替服务器代为收发请求和响应,不过从结构上看正好左右互换了一下,所以把后出现的那种代理方式称为反向代理了。



负载均衡


我们已经明确了所谓代理服务器的概念,那么接下来,Nginx 扮演了反向代理服务器的角色,它是依据什么样的规则进行请求分发的呢?不用的项目应用场景,分发的规则是否可以控制呢?


这里提到的客户端发送的、Nginx 反向代理服务器接收到的请求数量,就是我们说的负载量。请求数量按照一定的规则进行分发,到不同的服务器处理的规则,就是一种均衡规则。


所以将服务器接收到的请求按照规则分发的过程,称为负载均衡。


负载均衡在实际项目操作过程中,有硬件负载均衡和软件负载均衡两种,硬件负载均衡也称为硬负载,如 F5 负载均衡,相对造价昂贵成本较高。


但是数据的稳定性安全性等等有非常好的保障,如中国移动中国联通这样的公司才会选择硬负载进行操作。


更多的公司考虑到成本原因,会选择使用软件负载均衡,软件负载均衡是利用现有的技术结合主机硬件实现的一种消息队列分发机制。



Nginx 支持的负载均衡调度算法方式如下:



①weight 轮询(默认):接收到的请求按照顺序逐一分配到不同的后端服务器,即使在使用过程中,某一台后端服务器宕机,Nginx 会自动将该服务器剔除出队列,请求受理情况不会受到任何影响。


这种方式下,可以给不同的后端服务器设置一个权重值(weight),用于调整不同的服务器上请求的分配率。


权重数据越大,被分配到请求的几率越大;该权重值,主要是针对实际工作环境中不同的后端服务器硬件配置进行调整的。


②ip_hash:每个请求按照发起客户端的 ip 的 hash 结果进行匹配,这样的算法下一个固定 ip 地址的客户端总会访问到同一个后端服务器,这也在一定程度上解决了集群部署环境下 Session 共享的问题。


③fair:智能调整调度算法,动态的根据后端服务器的请求处理到响应的时间进行均衡分配。


响应时间短处理效率高的服务器分配到请求的概率高,响应时间长处理效率低的服务器分配到的请求少,它是结合了前两者的优点的一种调度算法。


但是需要注意的是 Nginx 默认不支持 fair 算法,如果要使用这种调度算法,请安装 upstream_fair 模块。


④url_hash:按照访问的 URL 的 hash 结果分配请求,每个请求的 URL 会指向后端固定的某个服务器,可以在 Nginx 作为静态服务器的情况下提高缓存效率。


同样要注意 Nginx 默认不支持这种调度算法,要使用的话需要安装 Nginx 的 hash 软件包。



Web 服务器对比



几种常用 Web 服务器对比如下图:

6

部署架构上支持负载均衡

设计上采用进程池概念

网络模块在linux上支持非阻塞epoll模型