core_framework —— 基于libev的轻量级lua网络开发框架

栏目: C · 发布时间: 5年前

内容简介:在发表这篇博文的前夕, 还有一些小伙伴在提问一些以下相关的问题:等等, 以上问题会在本文中一一介绍.首先来聊聊情怀这个东西! 相信每一个行业内的从业者都或多或少有过一个梦, 这个梦叫做: "我到时候要开发一个XXX"!其实作者当初也是一样.

在发表这篇博文的前夕, 还有一些小伙伴在提问一些以下相关的问题:

  1. 性能怎么样?

  2. 是否容易上手?

  3. 开发目标在哪?

  4. 如何反馈问题?

  5. 对比行业内的 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代码了吗?(笑)

这时候, 作者想了个点子来解决这个问题! 执行流程如下:

  1. 每次需要做一些同步操作的时候, 就调用C API注册回调事件.
  1. 为当前注册的所有事件创建一个Lua协程保存上下文并让出当前协程执行权.
  1. 等到注册事件被触发后, 调用C API恢复协程继续执行.

简单来说就是将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. httpdhttpc
  2. mail
  3. mysql
  4. redis
  5. mqtt
  6. websocket

其中一些协议为各位前辈那边借过来适配后定制的, 简单的协议则是直接花1-2小时直接手写出来的。

3. 封装与易用性

为了不让API那么封闭与提升cf的可用性, 作者决定将 mysqlredis 进行初步封装.

封装包括大家常用的功能, 连接池、面向对象操作、无需手动管理session生命周期等等. 简化编程思想包袱来提升开发效率.

至于内部Socket更是让框架来解决释放问题确保文件描述数量限制的情况下也是可以正常使用. (其实是不喜欢依赖gc被动close fd与free内存)

CF是啥?

如果你耐心看完了第一部分介绍, 那么你就应该对cf有了一个大概的了解.

cf全称为: CoreFramework, 是一个基于libev的Lua网络开发框架. 在其内部实现了多种网络协议与第三方库用来帮助使用者进行项目原型的快速开发.

cf 在httpd使用上尊崇前、后端分离的解决方案, 仅实现了基本的view路由并且不支持rest风格的API路由. 虽然这样可能会引来宇多人的诟病.

cf 的httpd内嵌websocket支持, 方便使用者在复用端口的同时也可以享受长连接编写的乐趣.

更多的介绍, 请大家项目地址的 Wiki

CF能做什么?

  • 基于容器技术的微服务场景(swarm/kubernetes); —— 推荐

  • 游戏服务器的前端代理层; —— 推荐

  • 内存/CPU资源较为紧缺的云服务器; —— 推荐

  • 对性能要求较高的无状态集群; —— 推荐

  • 海量长连接(websocket)Agent集群; —— 推荐

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的镜像. candymi/cfweb

使用详情与使用方法请参考 Docker安装编译安装

CF 如何运行呢?

测试运行

bash#: ./cfadmin

后台运行

bash#: ./cfadmin

退出

killall cfadmin

ctrl + c

文档在哪?

作者为大家贴心的写了一篇详细到不能再详细的 文档 , 以此来获取大家的点赞与关注.

作者还为喜欢阅读源码的同学准备了充足的中文注释与英文注释, 结合起来方便大家快速了解CF工作方式(中/英注释结合易于理解一些专属词汇).


以上所述就是小编给大家介绍的《core_framework —— 基于libev的轻量级lua网络开发框架》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

互联网+供应链金融创新

互联网+供应链金融创新

宝象金融研究院、零壹研究院 / 电子工业出版社 / 2016-6 / 65.00

供应链金融是一种带有模式创新的金融服务,它真正渗透到了产业运行的全过程。然而,如何探索这种模式的规律?特别是在"互联网+”时代,不同的产业主体如何更好地利用供应链金融促进产业的发展,成为了众多企业关注的话题。零壹财经攥写的《互联网+供应链金融创新》正是立足于这一点,全面总结反映了中国各行各业,以及不同的经营主体如何在立足产业运营的基础上,通过供应链金融来促进产业的发展具有很好的借鉴意义,其丰富的案......一起来看看 《互联网+供应链金融创新》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

随机密码生成器
随机密码生成器

多种字符组合密码

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码