文档章节

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

水果糖的小铺子
 水果糖的小铺子
发布于 03/27 13:53
字数 2721
阅读 91
收藏 1

大道至简, 返璞归真.

前言

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

  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的可用性, 作者决定将mysql与redis进行初步封装.

封装包括大家常用的功能, 连接池、面向对象操作、无需手动管理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工作方式(中/英注释结合易于理解一些专属词汇).


回答之前的问题:

Q. 性能怎么样?

A. 性能还不错, 但是具体数值请自行测试.

Q. 是否容易上手?

A. 学习lua 一小时入门 -> cf 一小时入门

Q. 开这个项目的初衷是什么?

A. 其实在前面已经回答过了.

Q. 开发目标在哪?

A. Wiki 里有TODO

Q. 如何反馈问题?

A. Wiki 里有Q & A

Q. 对比行业内的lua开源项目有何优势?

A. CF对比其它lua开发项目更深入改变用户使用习惯! 简化框架上手难度, 将框架都黑盒子透明化. 无需学习复杂的设计模式与理念.

Q. CF的开发理念是什么?

A. CF项目的目标不是竞争, 而是明白明白简单为美. 当你习惯了它, 也许你就会上瘾.


使用示例

精彩截图

部署面板

状态面板

pod日志

希望

也许你正在使用其它开发框架, 但是这不妨碍你对cf的督促.

也许你正在试用它, 这不妨碍你与作者沟通你的想法.

也许你正在吐槽它的缺点,请来issue尽情吐槽.

文档与地址

项目文档

项目地址

© 著作权归作者所有

水果糖的小铺子
粉丝 23
博文 153
码字总数 73315
作品 1
广州
程序员
私信 提问
轻量级 lua 网络开发框架 - core_framework

core_framework 是一个基于 libev 的轻量级 lua 网络开发框架。 cf使用lua脚本语言进行服务端业务逻辑开发, 在其内部实现了多种网络协议与第三方库用来帮助使用者进行项目原型的快速开发. c...

水果糖
03/27
1K
1
cf 0.3.1发布, 持续更新与优化 Lua Web 应用框架

core_framework 是一个基于 libev 的轻量级 lua 网络开发框架。cf 使用 lua 脚本语言进行服务端业务逻辑开发, 在其内部实现了多种网络协议与第三方库用来帮助使用者进行项目原型的快速开发。...

水果糖的小铺子
07/01
693
0
core_framework 0.4 发布,提供 windows 平台支持

更新日志 修复的字段错误的问题. 修复在平台的莫名其妙段错误. 修复了默认不使用的问题. 优化函数的实现方法, 使用更加简单的函数实现. 优化了对各种后端选择的优先级判断. 优化一大部分 C ...

水果糖的小铺子
07/15
1K
0
Lua Web快速开发指南(1) - 初识cf框架

cf是什么? cf全称为: CoreFramework. 一个基于Reactor事件驱动与协程的lua高性能网络框架, 目前主要面向HTTP Application开发. cf内部主要实现了包括HTTP与HTTP Over Websoket协议的Server,...

水果糖的小铺子
06/14
137
0
cf 0.2.1 发布,设计了一个 logo 与一些 bug fix

一个基于libev的轻量级lua网络开发框架 —— 也许这就是你想要的美. 0.2.1 更新: 为cf设计了一个漂亮的小logo; 修复xml2lua潜在的重入问题, 并且进行了文件路径调整与wiki说明. 优化xml2lua...

水果糖
04/25
756
1

没有更多内容

加载失败,请刷新页面

加载更多

搭建高可用MongoDB集群(分片)

搭建高可用MongoDB集群(分片) MongoDB基础请参考:https://blog.51cto.com/kaliarch/2044423 MongoDB(replica set)请参考:https://blog.51cto.com/kaliarch/2044618 一、概述 1.1 背景 ......

linjin200
22分钟前
5
0
CDH6.0.1集成tez-0.9.1计算引擎

参考文章: https://www.jianshu.com/p/9fb9f32e1f0f https://www.baidu.com/link?url=OgpwasnZi7H1dySN2T111sseEWDBaCCTC3DFV61G7756YbrkJCA8Y3UFaueyqnfN&wd=&eqid=daeb8b3500049cf3000000......

Sheav
24分钟前
4
0
Vue内置指令的使用

v-model(数据绑定) v-model常用于表单数据的双向绑定,它本质上是一个语法糖。它主要的有两种应用: 在文本框、多行文本、input的下拉框、单选按钮、复选框中的应用 <div id="app"> ...

凌兮洛
25分钟前
5
0
外部来源应用检查-烦死了,终于找到解决设置了

Android 连接usb调试应用的时候: 华为关闭方法:1、设置-安全-更多安全设置,关掉外部来源应用检查。2、设置-系统-开发人员选项-关闭“监控ADB安装应用” 不知道OPPO 怎么关闭的?...

QGlaunch
26分钟前
4
0
6个K8s日志系统建设中的典型问题,你遇到过几个?

作者 | 元乙 阿里云日志服务数据采集客户端负责人,目前采集客户端 logtail 在集团百万规模部署,每天采集上万应用数 PB 数据,经历多次双 11、双 12 考验。 导读:随着 K8s 不断更新迭代,使...

阿里云官方博客
28分钟前
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部