Nginx基础教程(87)Nginx多线程机制之pthread系统调用:Nginx多线程机制解密:用线程池让性能飙升9倍的秘密

如果你以为Nginx只是单线程的异步大师,那你就错过了它真正强大的武器库。

从Nginx的“敌人”说起:阻塞操作

大家都知道,Nginx采用了异步、事件驱动的方法来处理连接。这种处理方式无需为每个请求创建额外的专用进程或线程,而是在一个工作进程中处理多个连接和请求。

为此,NGINX工作在非阻塞的socket模式下,并使用了epoll和kqueue这样有效的方法。

这种架构的优势显而易见:满负载进程的数量很少(通常每核CPU只有一个)而且恒定,任务切换只消耗很少的内存,而且不会浪费CPU周期。NGINX可以非常好地处理百万级规模的并发请求。

但异步、事件驱动方法仍然存在问题。这个问题的名字叫阻塞(blocking)。很多第三方模块使用了阻塞调用,然而用户(有时甚至是模块的开发者)并不知道阻塞的缺点。阻塞操作可以毁掉NGINX的性能,我们必须不惜一切代价避免使用阻塞。

即使在当前官方的NGINX代码中,依然无法在全部场景中避免使用阻塞。想象一下,当Nginx需要读取一个没有缓存在内存中的文件时,它不得不从磁盘读取。从磁盘(特别是旋转式的磁盘)读取是很慢的。而当队列中等待的其他请求可能不需要访问磁盘时,它们也得被迫等待。

这就像商店的营业员要接待一排长队:队伍中的第一位顾客想要的商品在仓库中,营业员跑去仓库取货,整个队伍就得等待数小时。结果是延迟增加并且系统资源没有得到充分利用。

一个阻塞操作足以显著地延缓所有接下来的操作

线程池:Nginx的救星

为了解决这个问题,在NGINX 1.7.11中引入了线程池机制。那么,线程池到底是什么呢?

继续我们之前的比喻,现在那个营业员变聪明了,他雇用了一个配货服务团队。当任何人要买的东西在仓库时,他不再亲自去仓库,只需要将订单丢给配货服务。配货服务将处理订单,同时营业员可以继续为其他顾客服务。

对NGINX而言,线程池执行的就是配货服务的功能。它由一个任务队列和一组处理这个队列的线程组成。当工作进程需要执行一个潜在的长操作时,工作进程不再自己执行这个操作,而是将任务放到线程池队列中,任何空闲的线程都可以从队列中获取并执行这个任务。

工作进程将阻塞操作卸给线程池。

这样一来,只有访问文件的请求需要等待,而磁盘不再延误其他事件的处理。

目前,卸载到线程池中执行的两个基本操作是大多数操作系统中的read()系统调用和Linux中的sendfile()。在未来的版本中,如果有明显的优势,可能会卸载其他操作到线程池中。

pthread系统调用:线程池的基石

要理解Nginx的线程池实现,我们首先需要了解pthread系统调用的基础知识。

线程基础

线程是任务执行的基本单位,而进程则是线程执行的资源容器。线程共享相同的地址空间,共享相同的代码、数据区和堆区域。它们还共享相同的操作系统资源(如打开的文件)——一个线程读取文件会推进所有线程的文件偏移量。

每个线程有自己的执行状态:自己的用户栈、PC(程序计数器)、SP(栈指针)和寄存器。

关键的pthread函数

Nginx线程池的实现依赖于几个关键的pthread函数:

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

值引力

持续创作,多谢支持!

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

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

打赏作者

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

抵扣说明:

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

余额充值