【深入理解Nginx】Nginx设计中的性能优化点

Nginx设计中的性能优化点

目录

Nginx设计中的性能优化点

1、和nginx有关的内核性能调优

2、Nginx为访问第三方服务做的优化

3、内存池技术

4、事件

5、进程模型


1、和nginx有关的内核性能调优

2、Nginx为访问第三方服务做的优化

Nginx请求执行过程分析:

server模块:是http模块中的一个子模块,用来定义一个虚拟访问主机,也就是一个虚拟服务器的配置信息

location模块:用于进行访问路由的配置,主要用于配置路由信息在路由访问配置中关联到反向代理、负载均衡等各项功能。

upstream模块:主要负责负载均衡的配置,通过默认的轮询调度方式来分发请求到后端服务器。 

server模块通过hash表搜索

支持通配符的hash表,为了处理带有通配符的域名字符串的匹配,实现了支持通配符的hash表nginx中的通配符有两种形式:一种是通配符在前面的,例如*.test.com:可以省略*号,写成.test.com;还有一种通配符在后面的例如 www.test.*,这样域名不能省略 *号,注意:nginx不能同时包含在前面和在后的通配符例如 *.test.*。

将key字符串以 . 为分隔符拆分成多个key字段,将所有key字符串的第一个key字段去重后存到一个基本hash表中,再将所有有相同的第一个key字段的字符串去掉第一个key字段后分别递归处理。 

location模块通过二叉树搜索

location块通过二叉树搜索,因为是静态的,不会变,所以不用红黑树,用的完全平衡二叉树。 

upstream

(1)客户端到nginx,nginx再到服务器端,网速是极不对称的,反向代理的一个重要功能就是,提供大内存和磁盘文件缓存包,按照一定策略,接受完一定大小的包后,再由nginx发给客户端或服务器端。这样减少了服务器端需要维持的连接和缓存的占用时间;

(2)与服务器端:1)建立tcp连接三次握手是异步的,发送syn后epoll注册事件监听,设置回调函数;2)向上游发送请求或者接受下游请求,请求大小未知,所以发送请求的方法需要被epoll调度多次后才能发/收完请求的全部内容;3)包头大小有一个合理范围,而包体不一定,并且nginx不关心包体内容,因此nginx将包体头部全部用内存缓存,包体则根据情况而定,透传请求:nginx将客户端的请求包体全部接受完后才会发送给服务器端;4)透传响应:不实现反向代理、转发响应时上游网速优先,若下游网速快于上游网速,或者相差不大,不需要nginx开辟大块内存或磁盘文件来缓存上游响应、转发响应时下游网速优先,开辟内存和磁盘缓存响应。 

3、内存池技术

     Nginx为每一个层级都会创建一个内存池,进行内存管理,比如一个模板,tcp连接,http请求等,在对应的生命周期结束的时候会摧毁整个内存池,把分配的内存一次性归还给操作系统。在分配的内存上,nginx有小块内存和大块内存的概念,小块内存nginx在分配的时候会尝试在当前的内存池节点中分配,而大块内存会调用系统函数malloc向操作系统申请。在释放内存的时候,nginx没有专门提供对释放小块内存的函数,小块内存会在ngx_destory_pool和ngx_reset_pool的时候一并释放。区分小块内存和大块内存的原因有两个:1)针对大块内存,如果它的生命周期远远短于所属的内存池,那么单独提供一个释放函数是十分有意义的;2)大块内存与小块内存的界限是一页内存,大于一页内存在物理上不一定是连续的,所以如果分配的内存大于一页的话,从内存池中使用,和向操作系统重新申请效率差不多是等价的。

        还能够对外部资源进行管理,能够记录日志。

  • 用于减少系统调用次数;
  • 开发者申请一个内存池后可以任意从中申请内存,最后用完销毁内存池即可。nginx是一个web服务器,每一个请求的生命周期很短,也决定了每个内存池的生命周期很短,因此不会累计过多没有销毁的内存池。而在开发模块时,直接使用ngx_poll_t即可,模块结束后自动释放;
  • 申请大内存和小内存的不同处理:当nginx判断申请内存大的时候,直接从堆上申请内存,挂到一个大内存链表上,大内存的生命周期可能远远小于请求的生命周期的情况,nginx提供了方法提前释放而不用等到内存池销毁,小块内存nginx会一次申请比较大的一块,后面复用;
  • 内存对齐,碎片整理。

4、事件

(1)网络事件:epoll

(2)定时事件:红黑树实现,按照每个任务的时间来排序,每次取最左边的节点时间和当前时间判断即可,调用ngx_event_expire_timers方法触发所有超时事件

(3)磁盘事件:nginx的读操作作用的是linux内核实现,只有在内核进程完成了磁盘操作,内核才会通知nginx进程。好处是一方面可以让ngix更充分占用CPU,另一方面当有大量读磁盘的事件堆积到内核的时候,内核可以通过“电梯算法”降低随机读磁盘的成本。

5、进程模型

(1)master_worker:nginx启动时master进程进行初始化读取配置文件后fork出worker进程来监听处理网络事件,因为是fork出来的,所以和master监听的是同一个端口,accept事件到来时会有争取。

1)master进程不负责网络事件的监听和处理,主要负责启动服务,平滑升级,更换日志文件,热更新配置等,管理worker等功能。通过信号来管理worker进程;

2)worker进程监听和处理网络事件,一个worker挂了时master会快速拉起一个新的worker;

3)一个优化,nginx通常线程数和核心数相当,可以配置进程绑定CPU,减少进程在CPU间的跃迁,高效利用CPU cache。

(2)惊群问题:nginx会fork多个子进程监听同一个端口,子进程在accept建立新连接时会争抢,进程数量多时会有性能下降,开accept_mutex锁(默认打开)解决。nginx通过一个进程间同步锁accept_mutex,保证同一时刻只能由一个worker在监听web端口,释放锁通过定时器事件来实现。

(3)进程间负载均衡问题:多个worker抢一个事件时,会有一个成功,但如果这个worker本来就已经堆积了大量事件,另外有空间进程或者任务少的进程抢不到事件,子进程就会出现了负载不均衡。开accept_mutex锁解决,每个worker有个变量ngx_accept_disabled,初始为负值,绝对值为配置的总连接数的7/8,每次使用一个连接就加1,这个值为正时触发负载均衡,此时accept事件时此worker不会去抢accept_mutex,而是将ngx_accept_disabled减一。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

烊萌

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值