异步 I/O 与线程池

2016-08-20 23:47:15 +08:00
 mason961125

貌似 nginx 早期一直使用的是多进程+异步 I/O 的模式,后来(据说,个人未求证,只是在某技术博客里看到)使用了线程池技术。

但是,既然已经使用了异步 I/O ,线程池还有存在的必要吗?如果有,为什么?

2748 次点击
所在节点    C
18 条回复
denghongcai
2016-08-20 23:54:58 +08:00
http://www.infoq.com/cn/articles/thread-pools-boost-performance-9x

性能提升也是在特定场景下,具体情况具体分析
fcicq
2016-08-20 23:59:08 +08:00
FreeBSD 不需要楼上所说的这个优化, 这个优化仅限 Linux 才有意义.
wevsty
2016-08-21 00:55:40 +08:00
异步 I/O 最大只能使用单核心,对于多核心的处理器来说并不能达到最大处理能力。多进程或者多线程可以使用多个处理器核心。既然要使用多进程或者多线程,那么进程池或者线程池就是有必要的。
czz19891012
2016-08-21 01:18:33 +08:00
你这个是 concurrency 的问题吧. 其实多线程, 你说的异步 IO(其实是 IO 多路复用) 都是实现 concurrency 的两个方式
比如像 redis 单线程基于 epoll 这种模型, node.js 这种模型都可以归结为 Event-base Concurrency, 那么这种模型和 multi-thread 对比有什么区别呢?

从这个角度来看 multi-thread 是 kernel 来决定下一个要调度处理的 thread 是哪一个, 线程数据多了无论是资源还是调度都会有点问题

event-base 是所有的事件都放在一个 thread 上, 然后由这个 thread 来决定下一个要执行的 event 是谁?

因为 multi-thread 会考虑到每一个 thread 的优先级等等, 而且如果 thread 数目过多那么肯定会影响到具体的调度. 对比 event-base, 切换线程需要切换上下文, 因此肯定会有性能的损耗. 而在 event-base 里面, 所有的 event 的优先级都是一样的, 然后在处理 event 的 handler 里面决定先处理哪一个 event. 但是同样有一个问题就是如果这个 event-base 里面 event 比较多, 那么性能肯定也会下来.而且 event-base 的另一个缺点就是没办法使用到多线程

所以一般都是采用多线程 + 事件的方式来写网络编程了现在.
nginx 是, lighttpd 是, 我们开源的 pika( https://github.com/Qihoo360/pika )也是

我们还实现了这种模型的库 https://github.com/Qihoo360/pink
UnisandK
2016-08-21 01:33:39 +08:00
不知道你要的是不是这个,转

不要让内核做所有繁重的工作。将数据包处理,内存管理和线程调度等从内核中移出来,放到应用程序里,使其处理得更加高效。让 Linux 内核处理控制面,应用程序处理数据面。

这样,系统在处理上千万的并发连接时, 200 个时钟周期用于数据包处理, 1400 个时钟周期用于程序逻辑。由于内存访问要使用 300 个时钟周期,使用减少代码和减少 cache 丢失的方法进行设计也是关键所在。

内核中两个基本问题:
1 ) 连接数 = 线程数 / 进程数。一个数据包进来,内核要遍历所有 10,000 个进程找到处理这个数据包的进程。
2 ) 连接数 = select 数 / poll 数。同样的可扩展问题,每一个数据包都要遍历 sockets 列表。

解决方法:为内核打上补丁,使其查找时间为常数。
1 ) 现在无论线程数量多少,线程的切换时间是常数。
2 ) 使用 epoll()/IOCompeltionPort 可扩展的系统调用能够在常数时间查找 socket 。
线程调度仍不能够扩展,所以服务器使用 epoll 的异步编程模型,在 Node 和 Nginx 中都体现了。即使一台较慢的服务器,增加连接数时性能不会急剧下降。
FrankHB
2016-08-21 04:14:54 +08:00
@UnisandK 转也留个出处吧……虽然不难找。

倒是巧合,刚在看 dpdk 的代码。

不过这个说到底也是根据场景优化的了。而且大概年代的关系看样子挖掘的还不够,比如提到 cache 也没管 cache allocation 什么的新型黑科技……
UnisandK
2016-08-21 09:58:46 +08:00
@FrankHB 直接记在笔记软件里的,偷懒没再去专门找出处
hitmanx
2016-08-21 12:55:47 +08:00
你是想问异步 io vs 多线程,还是随用随创建线程 vs 线程池?
kingoldlucky
2016-08-21 13:19:36 +08:00
异步也需要多线程的支持的 所以需要线程池
SlipStupig
2016-08-21 16:19:23 +08:00
@kingoldlucky JS 表示为什么同样是异步,我却没有多线程
tinyproxy
2016-08-21 16:45:12 +08:00
@SlipStupig 我想你说的应该是 nodejs 吧, nodejs 的事件驱动用的是 libuv ,贴个链接好了 https://github.com/libuv/libuv/blob/b12624c13693c4d29ca84b3556eadc9e9c0936a4/src/unix/fsevents.c#L46

文件异步 IO 一般两种实现方式,最简单的就是线程池,另一种方式请移步 stackoverflow ,我只记得跟系统有关,具体怎么做的忘了。
qiukun
2016-08-21 17:02:32 +08:00
@fcicq 结果这楼没人理你(
kingoldlucky
2016-08-21 17:18:20 +08:00
@SlipStupig 只不过把多线程这块交给浏览器去做了而已
owt5008137
2016-08-21 17:31:27 +08:00
@denghongcai 贴的那篇文章已经解释得相当好了。其实这里用线程池也就是扮演一个简单通用的减少阻塞的方案。否则的话针对特定系统,用特定的方法也是可以的。最不济多开几个进程嘛。不过进程数太多会有一定的内存浪费和 CPU 浪费就是了。
fcicq
2016-08-21 17:37:51 +08:00
@qiukun 没关系. Solaris 系理论也不需要. 只会用 Linux 的人太多.
pubby
2016-08-21 18:42:38 +08:00
@fcicq FreeBSD 还是不错的, zfs 上开 jail 也各种方便。就是基金会有点穷,今年已经去捐了两次了 -_-
fcicq
2016-08-21 19:20:53 +08:00
@pubby 但是 jail 和 zones 差太远了, 而且 ZFS 的主场当然是 Solaris ... 但是 joyent 被三星收购之后情况也看不清了.
henglinli
2016-08-22 08:52:21 +08:00
1024cores.net 有讲怎么并行并发等设计的

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/300708

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX