core_framework —— 基于libev的轻量级lua网络开发框架
大道至简,返璞归真. 前言在发表这篇博文的前夕,还有一些小伙伴在提问一些以下相关的问题:
等等,以上问题会在本文中一一介绍. CF的起因首先来聊聊情怀这个东西! 相信每一个行业内的从业者都或多或少有过一个梦,这个梦叫做: "我到时候要开发一个XXX"!其实作者当初也是一样. 每当半夜(凌晨)在加班、看文档、调试的时候,总会搜索到一些几年前或十几年前的框架或入门demo。例如: tinyhttp,链接的源码是一些同学fork的镜像站。 每次看到这些内容或多或少都会激起心中那一丝丝快熄灭的热情,也许这就是最后对技术的渴望? 就是在动手创建项目之前还反复问过自己是否要做? 能坚持下去么?也许被喷都是一种奢望? 在心里一一回答了这些问题后,在2018年末创建了本项目. 说句实话! 一个网络开发框架最难的不是实现某个功能,而是从零开始一步一步添砖加瓦的造轮子! 作为一个网络开发框架,最重要的两个功能肯定是需要的! 定时器库、事件驱动库. 如何抉择?选项有2个: libev / libuv . libev 成熟稳定、轻量级、unix like支持、容易嵌入; libuv 比libev更加优秀,增加了许多功能(线程池、信号、同步、锁等等),封装更加完善,并且增加了windows支持; 从cf框架开发之初选型来看,libuv绝对是目前最优解. 但是作者偏偏选择了libev. 也从此开始,艰辛的底层开发之路就此展开. 首先,作者不让使用者C/C++进行实际业务开发! 这样做会让使用者有较高的开发成本与学习成本,而选择一门较好的脚本语言就显得尤为重要. 作者对Lua还算是稍微熟悉一点,所以就选了Lua作为业务脚本语言。至于Lua语言的优势这里就不说了,网上大把文章夸它的. 现在既然脚本语言已经选定,那么就开始写代码吧!Let‘s Lua. CF的编写之路1. 网络层首先,我们来看一段C封装给Lua调用的API代码: LUAMOD_API int luaopen_tcp(lua_State *L){ luaL_checkversion(L); /* 添加SSL支持 */ SSL_library_init(); SSL_load_error_strings(); // CRYPTO_set_mem_functions(xmalloc,xrealloc,xfree); // OpenSSL_add_ssl_algorithms(); /* 添加SSL支持 */ luaL_newmetatable(L,"__TCP__"); lua_pushstring (L,"__index"); lua_pushvalue(L,-2); lua_rawset(L,-3); lua_pushliteral(L,"__mode"); lua_pushliteral(L,"kv"); lua_rawset(L,-3); luaL_Reg tcp_libs[] = { {"read",tcp_read},{"write",tcp_write},{"ssl_read",tcp_sslread},{"ssl_write",tcp_sslwrite},{"stop",tcp_stop},{"start",tcp_start},{"close",tcp_close},{"listen",tcp_listen},{"connect",tcp_connect},{"ssl_connect",tcp_sslconnect},{"new",tcp_new},{"new_ssl",ssl_new},{"free_ssl",ssl_free},{"new_server_fd",new_server_fd},{"new_client_fd",new_client_fd},{NULL,NULL} }; luaL_setfuncs(L,tcp_libs,0); luaL_newlib(L,tcp_libs); return 1; } 以上是TCP实现的C代码的片段,有兴趣阅读源码的小伙伴请点击这里; 众所周知Lua没有原生的Socket. 那么就需要框架编写者自己抽象底层逻辑重新实现一套API. 简单的封装Lua C库谁都会,而且也算不上是什么难事. 但是我们的目的是将底层同步阻塞Socket hook为非阻塞,这时候难点就来了! 大家都知道libev是基于react模型的事件驱动网络库,所有注册事件后的业务逻辑都是以回调的形式触发. 那不就变成node-lua代码了吗?(笑) 这时候,作者想了个点子来解决这个问题! 执行流程如下:
简单来说就是将C层次的异步回调逻辑封装为Lua层的同步非阻塞,保证不因为IO问题阻塞线程. 下面提供一段socket同步非阻塞的伪代码,经供参考: function TCP:recv(bytes) local current_co = co_self() self.read_co = read_ev(function() -- do action -- stop timer_ev -- wakeup(current_co) 恢复执行权 end) self.timer_co = self.timer_ev(function() -- do action -- stop read_ev -- wakeup(current_co) 恢复执行权 end) tcp_start(io,EV_READ,self.read_co) timer_start(timer,3秒超时,self.timer_co) return co_yield() -- 让出执行权 end 一个Lua版的Socket EV_READ伪代码大致的处理流程如上,想看实际处理逻辑请看这里。 同理,Socket write/connect/listen等等API直接照抄就行(UDP也大同小异). (其实这里有个小插曲就是SSL SOCKET的坑,但是由于篇幅问题就不说了.) 细心的小伙伴可能发现代码同时注册了Socket与Timer事件,Socket非阻塞操作不能解决read与connect超时的问题. 所以cf框架干脆就封装彻底一点. 至此,Socket算是已经算是基本hook与封装完成了. 接下来就可以开始写应用层协议了. 2. 应用层协议现在Socket终于能正常使用了,那么面临的新问题就又来了。 libev没有自带异步dns dns都还需要使用者自己封装,这个坑真是填的无比难受! 好在网络上有前辈实现了Lua版的异步dns,作者稍微看明白之后就借用了过来封装内部使用. 这样cf也算是有了深度定制的异步dns库了吧!(虽然并不完善,但是足够使用) 一个网络库是否流行,基本上就得看生态. 那么协议层的轮子又得造起来:
其中一些协议为各位前辈那边借过来适配后定制的,简单的协议则是直接花1-2小时直接手写出来的。 3. 封装与易用性为了不让API那么封闭与提升cf的可用性,作者决定将mysql与redis进行初步封装. 封装包括大家常用的功能,连接池、面向对象操作、无需手动管理session生命周期等等. 简化编程思想包袱来提升开发效率. 至于内部Socket更是让框架来解决释放问题确保文件描述数量限制的情况下也是可以正常使用. (其实是不喜欢依赖gc被动close fd与free内存) CF是啥?如果你耐心看完了第一部分介绍,那么你就应该对cf有了一个大概的了解. cf全称为: CoreFramework,是一个基于libev的Lua网络开发框架. 在其内部实现了多种网络协议与第三方库用来帮助使用者进行项目原型的快速开发. cf 在httpd使用上尊崇前、后端分离的解决方案,仅实现了基本的view路由并且不支持rest风格的API路由. 虽然这样可能会引来宇多人的诟病. cf 的httpd内嵌websocket支持,方便使用者在复用端口的同时也可以享受长连接编写的乐趣. 更多的介绍,请大家项目地址的Wiki CF能做什么?
CF使用到的技术栈?传输层: TCP/UDP 会话层: SSL Client支持 协议层: dns/webocket/http/mqtt/redis/mysql/smtp 工具库: Timer/TASK 第三方库: Libev、openssl/libressl、lua-5.3、jemalloc/tcmalloc(可选) CF如何安装?cf 目前支持绝大部分Unix like操作系统,作者是在Mac上进行开发,所以Mac支持是必须的. cf测试的Linux为Centos,所以基本上基于Linux内核的操作系统编译后的运行也没什么问题(export 增加/usr/local/lib) 同时,作者还贴心的为大家做了一个简单Dockerfile. 文件在项目根目录下,大家下载直接使用即可。 当然,如果你不想制作Dockerfile,也可以使用Docker命令直接拉去作者制作好放在docker hub的镜像. 使用详情与使用方法请参考Docker安装和编译安装 CF 如何运行呢?测试运行
后台运行
退出
文档在哪?作者为大家贴心的写了一篇详细到不能再详细的文档,以此来获取大家的点赞与关注. 作者还为喜欢阅读源码的同学准备了充足的中文注释与英文注释,结合起来方便大家快速了解CF工作方式(中/英注释结合易于理解一些专属词汇). 回答之前的问题:Q. 性能怎么样?
Q. 是否容易上手?
Q. 开这个项目的初衷是什么?
Q. 开发目标在哪?
Q. 如何反馈问题?
Q. 对比行业内的lua开源项目有何优势?
Q. CF的开发理念是什么?
使用示例
精彩截图希望也许你正在使用其它开发框架,但是这不妨碍你对cf的督促. 也许你正在试用它,这不妨碍你与作者沟通你的想法. 也许你正在吐槽它的缺点,请来issue尽情吐槽. 文档与地址项目文档 项目地址 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |