观看视频
2018-08-23 22:00:00 分享会之后的答疑。
源代码地址:pool#workshop
一个网友在分享会之后的个人理解:对是独占资源对象的复用,提升了最后的 qps,独占式方法 TestChanPool()
函数中使用了从资源池获取 worker 对象,执行完毕后再放回资源池,如果获取不到则阻塞等待,因此,100 000 请求,每个请求占用 10ms,可用 worker 对象 50 个,则最后 100 000*10/50 =20s
,视频中测试结果也显示 21s 符合预期。而 TestWorkshop()
函数中使用回调函数对 worker 进行加锁,每个线程使用的那一刻是 worker 对象是被独占的,而后续的 do{sleep(10ms)}
是并发执行的,并且根据每个 worker 同时执行的 do 的任务数,进行负载均衡,所以最后测试性能 QPS 能够有 20 倍的提升。
workshop 中每个协程只在获得 worker 的那一刻是互斥的,且不会从池子中移除,通过状态统计达到资源的负载均衡。在业务上真正使用资源时其实是无锁状态,所以能被其他协程同时使用,进而吞吐量提升。业务逻辑耗时越长,相比独占式资源池的吞吐量优势越显著。本机测试 50 个资源 10ms 时可提升 20 倍。
为什么不使用轮询使用资源,代码实现会更简单?
实际场景中每次业务逻辑耗时不相同,轮询并不能保证真的负载均衡。尤其是当突发异常时,可能导致负载失衡。
为什么长连接异步通信不使用一条连接而是连接池?
说到长连接异步通信,为什么不使用一条连接而是连接池,其实涉及到多条连接抢占带宽和 TCP 丢包后速率下降的问题。这对于下载场景(迅雷就是这么做的)和使用共享云主机的场景比较有用。
具体可以看这篇文章:为什么多 TCP 连接比单TCP连接传输快
以前在做加速的一项就是多线程下载,开启多个 tcp 连接,同时下载,比只有一个连接下载快多了。
workshop 的使用场景
使用 workshop 的前提就是该资源可以被同时使用,比如长连接的异步IO通信。
对于长连接异步通信时,如果使用了独占式连接池只会起到反效果,让它和同步通信没差别,还不如不用池子。workshop 就是适用于这个场景的。
长连接:同步和异步方式。
同步方式下客户端所有请求共用同一连接,在获得连接后要对连接加锁,在读写结束后才解锁释放连接,性能低下,基本很少采用,唯一优点是实现极其简单。
异步方式下所有请求都带有消息ID,因此可以批量发送请求,异步接收回复,所有请求和回复的消息都共享同一连接,信道得到最大化利用,因此吞吐量最大。
这个时候接收端的处理能力也要求比较高,一般都是独立的一个(或者多个)收包线程(或者进程)防止内核缓冲区被填满影响网络吞吐量。缺点是实现复杂,需要异步状态机,需要增加负载均衡和连接健康度检测机制,等等。
workshop 就是实现了上述多条异步连接间的负载均衡,健康检测等。