skynet网络多线程处理讨论

311 views
Skip to first unread message

Tao Ge

unread,
Jul 26, 2016, 5:13:02 AM7/26/16
to skynet-users
最近因为项目线上问题以及群内讨论建议为skyent的网络增加多线程处理
在此讨论设计方案,各抒己见

Tao Ge

unread,
Jul 26, 2016, 5:21:47 AM7/26/16
to skynet-users
我的个人想法是开一个线程池来处理socket的读写,epoll的线程用于处理各种socket类型消息,然后将可读写的socket放入一个队列中,线程池从队列中取出socket进行读写操作


在 2016年7月26日星期二 UTC+8下午5:13:02,Tao Ge写道:
最近因为项目线上问题以及群内讨论建议为skyent的网络增加多线程处理
在此讨论设计方案,各抒己见

hua zhang

unread,
Jul 26, 2016, 6:24:01 AM7/26/16
to skynet...@googlegroups.com
事情的起因是这样的,我希望用skynet做webserver来承载大量的web请求,并把请求发送到后端或者从后端取数据。 后端的瓶颈不是问题,不管是memcached,或者redis,或者kafka。 这是一个轻cpu运算,重吞吐量的应用场景。
于是我测试了skynet作为http echo server的能力, echo server比较简单
一个service 监听连接,并把请求发送给broker处理
        for i= 1, broker_n do
                broker[i] = assert(skynet.newservice("broker"))
        end    
       
        local address = skynet.getenv "listen"
        skynet.error("Listening "..address)
        local id = assert(socket.listen(address))
        local balance = 1
        socket.start(id , function(id, addr)
                skynet.send(broker[balance], "lua", id, addr)
                balance = balance + 1
                if balance > #broker then
                        balance = 1
                end    
        end)

broker处理http请求,返回ok
local function handle_socket(id)
        local code, url, method, header, body = httpd.read_request(sockethelper.readfunc(id), 8192)

        if code then
                if url == "/echo" then
                        response(id, 200, "ok")
                end
。。。。

通过局域网的另一台机器,对这个服务进行ab压力测试
ab -n 100000 -c 2000 -r http://ip:8888/echo &

无论是调整ab进程数量,或者connection数量, 请求数量大约在2w左右每秒 达到瓶颈

26896 root      20   0  341m 103m 1188 R 87.1  0.2   0:07.90 skynet                                              
26905 root      20   0  341m 103m 1188 S 13.2  0.2   0:01.11 skynet                                              
26908 root      20   0  341m 103m 1188 S 13.2  0.2   0:01.16 skynet                                              
26898 root      20   0  341m 103m 1188 R 12.9  0.2   0:01.24 skynet                                              
26912 root      20   0  341m 103m 1188 S 12.9  0.2   0:01.20 skynet                                              
26900 root      20   0  341m 103m 1188 S 12.6  0.2   0:01.24 skynet                                              
26906 root      20   0  341m 103m 1188 S 12.3  0.2   0:01.02 skynet                                              
26909 root      20   0  341m 103m 1188 S 12.3  0.2   0:01.02 skynet                                              
26910 root      20   0  341m 103m 1188 S 12.3  0.2   0:01.03 skynet                                              
26907 root      20   0  341m 103m 1188 S 11.9  0.2   0:01.17 skynet                                              
26911 root      20   0  341m 103m 1188 S 11.6  0.2   0:00.99 skynet                                              
26899 root      20   0  341m 103m 1188 S 11.3  0.2   0:01.12 skynet                                              
26897 root      20   0  341m 103m 1188 S 10.6  0.2   0:01.05 skynet                                              
26904 root      20   0  341m 103m 1188 S 10.6  0.2   0:00.97 skynet                                              
26901 root      20   0  341m 103m 1188 S 10.3  0.2   0:00.95 skynet                                              
26902 root      20   0  341m 103m 1188 S  9.9  0.2   0:00.94 skynet                                              
26903 root      20   0  341m 103m 1188 R  8.9  0.2   0:00.92 skynet

通过在thread_socket 线程函数里 打印出tid( gettid()) 可以确认第一个占用cpu接近90%的线程是thread_socket

这时候替换服务器为swoole,同样的echo server,每秒大约能处理4w请求, 多的没有测试。

swoole 的做法是:它有多个Reactor线程来真正处理TCP连接,收发数据。swoole的主线程在Accept新的连接后,会将这个连接分配给一个固定的 Reactor线程,并由这个线程负责监听此socket。在socket可读时读取数据,并进行协议解析,将请求投递到Worker进程。在 socket可写时将数据发送给TCP客户端。
分配的计算方式是fd % serv->reactor_num

那么问题来了,作为一个skynet粉希望用skynet做更多的事情,
如果skynet也采用这种方法,比如启动多个thread_socket, accept到新的连接后,通过message queue,把fd传递给某个thread_socket,   这样是否会提升skynet的适用场景,或者有无其他比较好的方案。

2016-07-26 17:13 GMT+08:00 Tao Ge <get...@gmail.com>:
最近因为项目线上问题以及群内讨论建议为skyent的网络增加多线程处理
在此讨论设计方案,各抒己见
--
您收到此邮件是因为您订阅了Google网上论坛上的“skynet-users”群组。
要退订此群组并停止接收此群组的电子邮件,请发送电子邮件到skynet-users...@googlegroups.com
要发帖到此群组,请发送电子邮件至skynet...@googlegroups.com
访问此群组:https://groups.google.com/group/skynet-users
要在网络上查看此讨论,请访问https://groups.google.com/d/msgid/skynet-users/d1979ce1-1b34-426c-b80e-a5e9eddc59d8%40googlegroups.com
要查看更多选项,请访问https://groups.google.com/d/optout

Tao Ge

unread,
Jul 26, 2016, 9:43:10 PM7/26/16
to skynet-users
根据你的测试结果,你认为造成吞吐量不能提升的原因在哪里呢,或者是否有perf的详细分析报告呢?


在 2016年7月26日星期二 UTC+8下午6:24:01,hua zhang写道:
最近因为项目线上问题以及群内讨论建议为skyent的网络增加多线程处理
在此讨论设计方案,各抒己见
--
您收到此邮件是因为您订阅了Google网上论坛上的“skynet-users”群组。
要退订此群组并停止接收此群组的电子邮件,请发送电子邮件到skynet-users+unsubscribe@googlegroups.com

云风 Cloud Wu

unread,
Jul 26, 2016, 9:59:04 PM7/26/16
to skynet-users
如果纯为跑分的话,建议直接写一个 C 模块,调用系统的 send/write, 而绕过 socket thread 去写 socket 。这样可以把跑分测试中的读写分离。

这个方法在一定程度上也是很实用的(不仅仅为跑分跑的更高), 它的限制只是,你需要小心使用,避免多服务同时对同一个 socket 写数据,导致逻辑上的混乱;反之,如果你业务上有可能会从多个服务向同一个 socket 写的话(目前 skynet 支持,且每个服务的每次写调用都可以保证原子性),使用多线程同样需要考虑这个问题。

skynet 并没有特地为仅仅做 IO 处理去优化,所以不打算为这个让代码变得更复杂。如果你做一个纯转发的网关,显然有很多专门针对性的东西做的更好。
或者对于直接转发,你完全可以在同一台机器上启动多个 skynet 进程;而如果你有一定的业务要处理,优化 IO 也并不会提高业务处理的性能。


Tao Ge <get...@gmail.com>于2016年7月27日周三 上午9:43写道:
--
您收到此邮件是因为您订阅了Google网上论坛上的“skynet-users”群组。
要退订此群组并停止接收此群组的电子邮件,请发送电子邮件到skynet-users...@googlegroups.com
要发帖到此群组,请发送电子邮件至skynet...@googlegroups.com

--
您收到此邮件是因为您订阅了Google网上论坛上的“skynet-users”群组。
要退订此群组并停止接收此群组的电子邮件,请发送电子邮件到skynet-users...@googlegroups.com

要发帖到此群组,请发送电子邮件至skynet...@googlegroups.com
访问此群组:https://groups.google.com/group/skynet-users

云风 Cloud Wu

unread,
Jul 26, 2016, 10:06:40 PM7/26/16
to skynet...@googlegroups.com


hua zhang <cpl...@gmail.com>于2016年7月26日周二 下午6:24写道:
事情的起因是这样的,我希望用skynet做webserver来承载大量的web请求,并把请求发送到后端或者从后端取数据。 后端的瓶颈不是问题,不管是memcached,或者redis,或者kafka。 这是一个轻cpu运算,重吞吐量的应用场景。

skynet 的优势场合其实是: 不要单独做后端,而是把你的后端业务放在 skynet 的同一个进程里来做。整体提高性能。

因为它能帮你解决跨进程数据传递的额外开销,同时又通过多个 lua 沙盒隔离任务,且可以充分利用硬件的多核能力。

另外,它还能减少整个系统的复杂度,例如,skynet 的服务自己可以 cache 状态数据,从而 memcached 这种设施就是多余的了。

若是做个网关转发,我推荐直接用 nginx 。

hua zhang

unread,
Jul 27, 2016, 2:47:35 AM7/27/16
to skynet...@googlegroups.com
好的,多谢了。 另外还想问一下, skynet后面有没有什么路线图?
可以让更多的开发者参与到skynet的开发中。
比如swoole,它在2014年由个人项目变成了组织项目,它把自己定位成移动通信、企业软件、云计算、网络游戏、物联网(IOT)、车联网、智能家居等网络计算的一个方案。 它有一个评审小组,来确认需求,评审,代码发布,项目宣传等事宜。

云风 Cloud Wu

unread,
Jul 27, 2016, 5:41:05 AM7/27/16
to skynet...@googlegroups.com
skynet 用户应该比较厌恶加新的特性,所以现在尽量保持这个版本的稳定,只修 bug 。

hua zhang <cpl...@gmail.com>于2016年7月27日周三 下午2:47写道:
好的,多谢了。 另外还想问一下, skynet后面有没有什么路线图?
可以让更多的开发者参与到skynet的开发中。
比如swoole,它在2014年由个人项目变成了组织项目,它把自己定位成移动通信、企业软件、云计算、网络游戏、物联网(IOT)、车联网、智能家居等网络计算的一个方案。 它有一个评审小组,来确认需求,评审,代码发布,项目宣传等事宜。

--
您收到此邮件是因为您订阅了Google网上论坛上的“skynet-users”群组。
要退订此群组并停止接收此群组的电子邮件,请发送电子邮件到skynet-users...@googlegroups.com
要发帖到此群组,请发送电子邮件至skynet...@googlegroups.com
访问此群组:https://groups.google.com/group/skynet-users
Reply all
Reply to author
Forward
0 new messages