协程解决了什么问题
先做个测试,比较简单业务场景下,协程网络库server 和 原生epoll的差异。直接看结论,过程不用看 。
测试epoll
ab -n 1000 -c 10 http://0.0.0.0:8888/
测试nyco_server
ab -n 1000 -c 10 http://0.0.0.0:4000/
进入nyco项目先make一下,得到静态库libnyco.a,跑下面就能正常编译了sample中代码了
gcc -o nty_http_server ./sample/nty_http_server.c -I./core -L. -lntyco -lpthread -ldl
gcc -o nty_http_server ./sample/nty_http_server.c -lntyco -lpthread -ldl
测试nyco_server
Server Software:
Server Hostname: 0.0.0.0
Server Port: 4000Document Path: /
Document Length: 1 bytesConcurrency Level: 10
Time taken for tests: 0.105 seconds
Complete requests: 1000
Failed requests: 0
Total transferred: 84000 bytes
HTML transferred: 1000 bytes
Requests per second: 9511.67 [#/sec] (mean)
Time per request: 1.051 [ms] (mean)
Time per request: 0.105 [ms] (mean, across all concurrent requests)
Transfer rate: 780.25 [Kbytes/sec] receivedConnection Times (ms)min mean[+/-sd] median max
Connect: 0 0 0.2 0 2
Processing: 0 0 0.3 0 3
Waiting: 0 0 0.3 0 2
Total: 0 1 0.4 1 3Percentage of the requests served within a certain time (ms)50% 166% 175% 180% 190% 195% 198% 299% 3100% 3 (longest request)
测试epoll
Server Software:
Server Hostname: 0.0.0.0
Server Port: 8888Document Path: /
Document Length: 1 bytesConcurrency Level: 10
Time taken for tests: 0.097 seconds
Complete requests: 1000
Failed requests: 0
Total transferred: 89000 bytes
HTML transferred: 1000 bytes
Requests per second: 10313.11 [#/sec] (mean)
Time per request: 0.970 [ms] (mean)
Time per request: 0.097 [ms] (mean, across all concurrent requests)
Transfer rate: 896.35 [Kbytes/sec] receivedConnection Times (ms)min mean[+/-sd] median max
Connect: 0 0 0.1 0 1
Processing: 0 1 0.2 1 2
Waiting: 0 0 0.2 0 2
Total: 0 1 0.2 1 2Percentage of the requests served within a certain time (ms)50% 166% 175% 180% 190% 195% 198% 299% 2
结论:
可以看到在轻量任务下,协程性能不如epoll
测试中ab默认是短连接的,就是ab发一条数据然后等server回复一个字节,双方关闭。
那么在这个简单场景下我们为什么要使用协程?好处只不过是异步改同步了,原生epoll相比协程,少了协程的创建、就绪/阻塞/定时队列的切换(总之就是少跑了很多用户函数),整体的流程是一样的。一样都要跑epollwait等着连接就绪、读写就绪。
什么时候用协程?
我们用协程是希望来在单核下中把串行的请求改为并行,协程真正的使用应该是在分布式系统中连接下游微服务和客户端的服务器,而不是纯服务端,这种场景将出现大量等待下游微服务返回的场景,这时候切到其他协程去处理,等就绪了再切回来。
为什么这个场景不用多线程?
多线程编程难度大(套不了协程的逻辑),虽然也可以用futrue来做并发,但是逻辑没有协程清晰和灵活,而且用了多线程就需要考虑线程安全,就得加锁,再者线程开销比协程大。
多线程适合做成线程池来做cpu密集型或者io密集型的任务,总之就是把多核给利用起来,线程池更好管理,分发任务->多核处理->汇总任务结果的逻辑更好实现。
协程更适合用多进程,因为协程的调度器是独立的,共享就要加锁,为什么要共享?而且多进程更简单,fork就完事了,多个服务器跑不同端口就行了,一个挂了也不影响,共享数据走共享内存。
为什么要做协程的性能测试?
原生epoll的性能是很高的,协程网络库本质=epoll+额外的逻辑,你得测你性能下降没有太厉害。