Nginx高效的原因

导读

研发同学们对应用过载就扩容这个动作已是非常的熟悉,但大家有听说过业务流量突增,nginx也随之需要扩容嘛?我相信很少听过,为什么呢?主要是nginx高效工作起作用,那接下来我们来讲讲我们nginx为何高效。

一. Nginx 为何神物

Nginx 是一种异步框架的web服务器,它可以用作反向代理、负载均衡器和 HTTP 缓存或邮件服务器。Nginx 是免费且开源的,根据类 BSD 许可证的条款发布,意味任何人都可以下载甚至修改源码。Nginx 软件由伊戈尔·赛索耶夫创建并于 2004 年首次公开发布。2011 年成立同名公司以提供支持,现大部分互联网公司都在使用。早期我们公司使用的是 tengine+tengine-cgi+php-fpm 的架构来提供服务,后来公司统一使用dubbo后,我们架构升级为 TGW(tengine集群)+tengine+java-cgi , 同时,我们的 Tengine+lua (nginx衍生版本) 还具备有 WAF防火墙,流量管控,流量调度,统一日志和实时监控等的定制化开发模块。

二.Nginx 为何高效

一个高性能web服务器典型特点是处理速度快且消耗资源少.尤其在上万连接同时在线的时候.若要做到处理速度快,并发模型的设计尤其关键.服务器并发量取决于两个因素:一是服务器连接的进程数量, 二是每个进程可同时处理的并发请求数量,因而web服务器并发模型由两部分构成,服务的提供方式和连接处理机制, 这两种别具一格的方式使得Nginx在同类型的web服务器中表现优秀。

1. 服务提供方式

一般Web服务器并发处理请求有以下三种方式:多进程方式、多线程方式、异步方式。

多进程 需要内存复制等额外开销,客户端较多时候,服务器性能会降低,典型应用如Apache的prefork模块;

多线程 使用进程中多个线程提供服务,多线程开销较小,典型应用如Apache的worker模块;

异步 则采用非阻塞的方式与每个客户通信,服务器用一个进程进行轮询,典型应用如Nginx的work process进程;

其中效率最高是异步,最稳定是多进程、占用资源少是多线程。

类型优点缺点
多进程方式                     稳定性高:由于采用独立进程处理独立请求,而进程之间是独立的,单个进程问题不会影响其他进程,因此稳定性最好 资源占用率高:当请求过大时,需要大量的进程处理请求,进程生成、切换开销很大,而且进程间资源是独立的,造成内存重复利用。
多线程方式 开销较小:线程间部分数据是共享的,且线程生成与线程间的切换所需资源开销比进程间切换小得多 线程切换过快可能造成线程抖动,且线程过多会造成服务器不稳定。
异步方式 性能最好:一个进程或线程处理多个请求,不需要额外开销,性能最好,资源占用最低。 某个进程或线程出错,可能导致大量请求无法处理,甚至导致整个服务宕机。

    Nginx基于事件模型(异步方式)提供服务,更适合每秒连接数和请求数同时非线性增长的情况。即使负载增加了,内存和CPU使用事件数量始终保持可预期。Nginx使用普通的硬件就能在一个服务器上处理数万的并发连接。这就是Nginx高性能的第一个原因。

2.连接处理机制

谈到连接处理机制,关键是LINUX的I/O模型,同步阻塞io,同步非阻塞io,异步阻塞io(io复用),异步非阻塞io(信号驱动或者异步io)

阻塞和非阻塞:

那什么是阻塞和非阻塞呢,这里用点菜传菜举例来说明阻塞和非阻塞:



第一种:就在出菜窗口等待,直到厨师炒完菜后将菜送到窗口,然后服务员再将菜送到用户手中;
第二种:等一会再到窗口来问厨师,某个菜好了没?如果没有先处理其他事情,等会再去问一次;

 

第一种为阻塞方式,第二种为非阻塞的。从上面看,明显第二种非阻塞的效率更高;

同步和异步:

那什么是同步和异步呢,这里用传菜来举例下同步和异步 :


同步:客户点菜,服务员直接跟厨师打交道,菜出来没出来,服务员直接指导,但只有当厨师将菜送到服务员手上,这个过程才算正常完成,这就是同步的事件。
异步:同样是点菜,有些餐馆有专门的传菜人员,当厨师炒好菜后,传菜员将菜送到传菜窗口,并通知服务员,这就变成异步的了。

 

对于同步的事件,你只能以阻塞的方式去做。而对于异步的事件,阻塞和非阻塞都是可以的,

传统的服务器采用的就是同步阻塞的多进程模型,而Nginx服务器使用多进程机制能够保证不增长对系统资源的压力,同时使用异步非阻塞方式减少了工作进程在I/O调用上的阻塞延迟,保证了不降低对请求的处理能力,这就是高效原因之一。

I/O多路复用:

select 和 poll 一般所有的操作系统都会支持,但是每次等待都要设置需要等待的套接口,并且内部的实现不够高效,很难支持监听高并发量的套接口集。不同的操作系统使用了不同的高级轮询技术来支持高性能的监听,一般这些方式都不是可移植的,比如freebsd上实现了 kqueue,solaris实现了/dev/poll,linux实现了epoll等。我们使用的 Centos 6.x 系统的epoll库。这也就是Nginx高性能的第二大原因。

4. Tengine 丰富插件

Tengine 是 nginx衍生版本,性能和稳定性已经在大型的网站如淘宝网,天猫商城等得到了很好的体验,其一个重要特点就是非常多的丰富插件,以下就来介绍下我们乐信使用了哪些 Tengine 插件模块:

- --with-http_concat_module ## 用于合并多个文件在一个响应报文中
- --with-http_flv_module ## 供服务端伪流媒体支持
- --with-http_stub_status_module ## nginx 性能监控
- --with-http_gzip_static_module ## gzip 支持各类数据压缩传输,降低网络
- --with-http_sysguard_module ## 过载保护模块
- --with-http_lua_module ## lua 模块
- --with-http_v2_module ## http2支持
- --add-module=../nginx_upstream_check_module-master ## upstream 健康检测和自动剔除模块
- --add-module=../nginx-upsync-module-1.8.x ## 实现配置动态更新等等;

 

正是以上tengine丰富的插件,给我们的业务带来了强稳定性,高并发性能噢;

5. tengine 其它特性

除了以上,内部有大量可见的细节优化,采用多进程单线程的工作方式,并且利用cpu和进程的亲缘性将进程和特定cpu绑定(tengine默认支持),避免了进程上下文切换的开销,从而减少了cpu占用。另外它实现了高效的内存池,将内存占用降到最低等,这个依靠于nginx.cong 主配置进行优化等等;

三. tengine 扩展 lua

ngx_lua 模块是 nginx 第三方模块,它能将lua语言嵌入到nginx配置中,从而使用lua 极大增强了nginx的能力,nginx以高并发而知名,lua脚本轻便,两者的搭配堪称完美。

我们使用的 tengine+lua 大致可以分为2类作用,第一类是核心接入服务器,第二类是业务承载服务器,可能在我们这里都统称在一个大集群里面:

核心接入服务器:
1.如动态负载均衡(后续我们需要做的,因为我们业务需更高级别隔离);
2.根据请求特征将流量分配到不同分组不同set或者机房,我们叫它流量调度(已具备);
3.防DDOS攻击限流:可以将请求日志推送到实时计算集群,然后将需要限流的IP推送到核心Nginx进行限流(我们利用TGW防DDOS攻击);
4.缓存服务,使用Nginx Proxy Cache实现内容页面的缓存等等;
业务承载服务器:
1.缓存,直接把图片等资源链接存储在redis,通过lua+nginx+redis 进行第一层请求返回(如tab页缓存);
2.AB测试/灰度发布:比如要上一个新的接口,可以通过在业务Nginx通过Lua写复杂的业务规则实现不同的人看到不同的版本。(已具备);
3.服务质量监控:我们可以记录请求响应时间、缓存响应时间、反向代理服务响应时间等达到实时监控,另外记录非200状态码错误来了监控服务可用率(已具备)等功能;

四. 总结

  1. nginx 它是一个高性能web服务器,它能同时提供上万的连接请求,而且速度快,占用资源少,部署在普通服务器就ok;

  2. nginx 高效是因为异步且采用非阻塞的方式与每个客户通信,通过使用了操作系统IO复用方式(select和poll、epoll)达到高性能;

  3. tengine 丰富的插件可提供我们插拔式选择使用,并且在主配置文件也具有大量的优化性能参数,如内存池,cpu亲缘性绑定等等;

  4. lua_ngx 现在在我们业务方面实践,比如有waf防火墙,流量调度,流量管控,页面缓存,质量监控,统一日志等多个模块应用业务上。

原文地址:https://www.cnblogs.com/wzlbigdata/p/13963071.html