免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 11914 | 回复: 7
打印 上一主题 下一主题

[C++] 写了个lua+多线程+libevent的东西,求意见 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2014-01-08 19:56 |只看该作者 |倒序浏览
地址:  https://github.com/ackroyd-xt/lua_libevent_multiThread_server

最近学lua和libevent,然后看了两个写了server的帖子
http://bbs.chinaunix.net/thread-3776236-1-1.html  
还有一个忘了地址了,是写了个lua+libevent 的单线程server (说是多线程但只是coroutine,实际上只是单线程)

于是跟风写了个自己的。。但是有些疑问,希望能解答。。
不经常上chinaunix,希望能直接发到邮箱谢谢。。

基本想法是:
      1. 线程池 (之前自己写过一个,主线程负责任务分配,子线程接收任务,没有任务就使用 pthread_cond_wait阻塞等待任务
      2. 主线程应用libevent负责epoll,任何连接有事件了就组装一个任务分发给空闲线程 (实际上只是分发一个描述符下去)
      3.  每个描述符对应一个lua_State,由lua保存这个连接的状态(之前用lua_newthread但是多线程操作会coredump)
      4.  子线程接到任务后resume  对应的lua_State, lua跑脚本,跑到yield处 返回到子线程,子线程认为任务完成陷入pthread_cond_wait
      5.   lua_state在程序启动时建立,只有在出错时才删除重建。当连接正常断开时lua脚本回到开头的位置继续接受请求,避免多次申请lua_state
      6.  lua在yield之前设置标识,子线程在lua yield返回后根据标识向主线程申请注册对应的事件(通过管道完成,向管道写一个fd,主线程检查全局数组conn的下标为fd的元素,根据该元素的标识注册对应的事件)。(之前是子线程直接注册事件,但是libevent好像没有多线程所以core掉了,现在是全部交给主线程来注册)

想到的优点:
      1. 因为是多线程,所以和单线程的实现相比,就算服务端阻塞也没问题(例如数据库查询)(也就是增加了吞吐量?)
      2. 因为用了lua,服务端逻辑可以写的比较复杂(和客户端的交互可以有很多次,可以加上超时之类的东西,而且都是非阻塞的;可以把 读写的注册和yield包装起来,这样lua脚本可以写的像阻塞的但实际都是非阻塞的) 。 如果是简单的多线程实现,就是一个连接占用一个线程,无法应付少量活跃连接、大量不活跃连接的情况; 而这个实现由于有coroutine且本身有多线程,实际需要的线程数量=实际活跃的连接数,所以可以支撑更多的连接(吞吐量

性能上,在具体场景可能略低于更有针对性的实现(例如简单服务器场景的单线程libevent实现, 复杂服务器场景的 简单多线程实现)。个人觉得就是个适用性较广、性能还不差的一个东西。

目前的缺点和问题:
      1.  为了支持复杂的客户端和服务端交互的逻辑(而且要非阻塞),server业务逻辑必须用lua写,或者用 C写但是要用continue-program-style (试过一个例子,就是每次yield时注册下次调用的continue函数,感觉写起来比较麻烦)。如果用lua写,可能就需要很厚的胶水层(稍微复杂点的东西都要放到C里包装起来给到lua调用) ----------这个感觉是最大的问题,不管写什么都要用lua包装下,虽然可以直接用C写但 cps风格很麻烦,每次yield之后的操作都要放到下一个函数里实现。想写个包装的东西把yield和continue函数包装起来,但没想到什么办法
     2.  个人感觉 性能+实现复杂度 比不上更具有针对性的、更简单的实现,不管怎么写感觉还是比不过libevent。 相比简单多线程的实现,例如要查询数据库的场景,简单多线程是把线程切换(等待客户端回复等阻塞socket操作导致线程阻塞)的工作交给cpu,这个实现是自己实现了这部分工作换来更大吞吐量,但是这个感觉意义不大。。。

征求意见,1. 怎么让胶水层不那么厚,至少不要每次写server都要手动加厚胶水层        2. 怎么进一步提升性能,在服务较简单以至于可以直接使用单线程libevent实现、服务端操作不会阻塞的情况下,有无让性能超过单线程libevent的可能?  或者涉及数据库操作时,相比直接使用简单多线程实现, 性能相比又怎样?

      

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
2 [报告]
发表于 2014-01-08 21:51 |只看该作者
本帖最后由 群雄逐鹿中原 于 2014-01-08 21:54 编辑

建议参考下luvit。

如果把 udt 加上和 luajit 加上,就完美了。

论坛徽章:
4
水瓶座
日期:2013-09-06 12:27:30摩羯座
日期:2013-09-28 14:07:46处女座
日期:2013-10-24 14:25:01酉鸡
日期:2014-04-07 11:54:15
3 [报告]
发表于 2014-01-09 09:51 |只看该作者
楼主的思路和当年的我一样有问题,对coroutine实践还是缺乏点经验,可以看看我当时的学习成果的设计思路。

http://bbs.chinaunix.net/thread-4076795-1-1.html

论坛徽章:
11
未羊
日期:2013-12-16 12:45:4615-16赛季CBA联赛之青岛
日期:2016-04-11 19:17:4715-16赛季CBA联赛之广夏
日期:2016-04-06 16:34:012015亚冠之卡尔希纳萨夫
日期:2015-11-10 10:04:522015亚冠之大阪钢巴
日期:2015-07-30 18:29:402015亚冠之城南
日期:2015-06-15 17:56:392015亚冠之卡尔希纳萨夫
日期:2015-05-15 15:19:272015亚冠之山东鲁能
日期:2015-05-14 12:38:13金牛座
日期:2014-12-04 15:34:06子鼠
日期:2014-10-16 13:40:4715-16赛季CBA联赛之八一
日期:2016-07-22 09:41:40
4 [报告]
发表于 2014-01-09 10:28 |只看该作者
因为用了lua,服务端逻辑可以写的比较复杂


这是什么意思, 难道不用 lua 就不能写的比较复杂?

论坛徽章:
0
5 [报告]
发表于 2014-01-09 18:26 |只看该作者
回复 3# linux_c_py_php

好像之前看的单线程lua server就是你这个?但是好像是在另一个帖子。。。我之前确实有看过一个lua_frame的东西,好像就是你这个
但是你的实际上是单线程(coroutine的线程而非真实线程),我的是多线程的实现。

但是你的帖子和回复里都没看到有说问题在哪里,能直接明说吗?谢谢~
   

论坛徽章:
0
6 [报告]
发表于 2014-01-09 18:35 |只看该作者
回复 4# zylthinking


  只是说用lua很方便。例如  客户端发报文---服务端校验并回复---客户端发报文---服务端进行数据库处理并回复  这种交互,如果不使用lua的话,我能想到的是:
1. 写成多线程的,每个线程处理一个请求(或者常驻线程轮流处理请求),但这样就不是非阻塞的,线程会被阻塞的连接占用
2. 写成多线程的,每个线程轮流处理请求,并向主线程申请注册libevent事件然后等待(但这样这个线程仍被该连接占用)
3. 写成单线程的,每一个交互步骤都要写一个callback,在执行完一个callback后再注册下一个callback,这种方式写起来会很麻烦;而且如果还要加上更多的if -else分支的话就很麻烦了。其实就是把lua的栈管理由人工来做了

论坛徽章:
15
射手座
日期:2014-11-29 19:22:4915-16赛季CBA联赛之青岛
日期:2017-11-17 13:20:09黑曼巴
日期:2017-07-13 19:13:4715-16赛季CBA联赛之四川
日期:2017-02-07 21:08:572015年亚冠纪念徽章
日期:2015-11-06 12:31:58每日论坛发贴之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-07-12 22:20:002015亚冠之浦和红钻
日期:2015-07-08 10:10:132015亚冠之大阪钢巴
日期:2015-06-29 11:21:122015亚冠之广州恒大
日期:2015-05-22 21:55:412015年亚洲杯之伊朗
日期:2015-04-10 16:28:25
7 [报告]
发表于 2014-01-27 16:46 |只看该作者
本帖最后由 yulihua49 于 2014-01-27 16:48 编辑
fakepersona 发表于 2014-01-09 18:35
回复 4# zylthinking


4.linux_c_py_php的方法就很好。用epoll内置的L/F模型。具体做法可以改进。
直接用epoll何必要linevent?

论坛徽章:
0
8 [报告]
发表于 2014-02-10 15:50 |只看该作者
回复 7# yulihua49


    用的AIX没有epoll。。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP