Open hanxi opened 3 years ago
看到很多简洁的 web 框架,总想自己造个轮子试试,边写边记录些比较。
既然是造轮子,我当然选自己最熟悉的 Lua 语言了,可是已经有了基于 Openresty 的 lor 框架,所以底层我就又选用了我熟悉的 skynet 了。
明确目标: 基于 skynet 开发一个 web 框架。
为了早点出轮子,且轮子是可玩的,我对功能做了取舍。计划第一个版本只完成下面这些功能:
为什么不实现模板呢?在现在,前后端分离开发的趋势下,模板显得没那么重要了。服务器只需要提供接口就行,模板都转移到了前端。
重定向的功能本来是计划中的,但是觉得不实现它也没什么问题,等需要的时候再补上吧。
第一个版本定为 0.01 ,主要功能就是上面说的。后续版本现在也只是想想而已,比如目前只能在 Linux 下运行,可以尝试迁移到 Mac OS 和 Windows 下运行,因为不是必须的东西,所以就放在 TODO 计划中了。
从使用者的角度来确定框架结构。首先是方便开发部署,所以参考了 lor 的方式,提供脚手架生成工程,工程中包含些操作脚本,比如 start.sh , stop.sh 和 reload.sh 这些。由于选用的底层是 skynet ,所以按照 skynet 推荐的方式开发,以 skynet 为 submodule 。
start.sh
stop.sh
reload.sh
预定的目录结果大概是这样的:
. ├── 3rd ├── conf ├── luaclib ├── lualib ├── Makefile ├── service └── skynet
框架的主要代码都放在 lualib 目录,其他第三方库都放到 3rd 目录。service 是自定义的 skynet 服务目录。
lualib
3rd
service
框架使用 skynet 的特性很少,只用到了 2 种服务,一个主服务 main 和多个 agent 服务,web 开发逻辑都在 agent 服务上执行。
+---------+ +---------+ | agent 1 <----+ client | +-------+ +---------+ +---------+ | main +-----+ +-------+ +---------+ | agent 2 | +---------+
首先就是参考 skynet/examples/simpleweb.lua 示例开启 http 服务。这里的例子把 agent 服务写在了同一个文件,把他拆开为 service/main.lua 和 lualib/wlua/agent.lua 两个文件,稍微改改就跑起来了。
skynet/examples/simpleweb.lua
service/main.lua
lualib/wlua/agent.lua
首先从使用者的角度来设计框架,使用者的目录结构大致是这样的:
. ├── app │ └── main.lua ├── conf │ └── wlua.conf ├── cutlog.sh ├── kill.sh ├── reload.sh ├── start.sh └── stop.sh
可以看出,除了那些 sh 脚本,只有两个文件是主要的。 app/main.lua 就是 agent 服务的入口,也是使用者开发 web 服务器的入口。 conf/wlua.conf 是配置文件,我想要的 app/main.lua 是这样的结构,和 lor 框架的非常类似。
app/main.lua
agent
conf/wlua.conf
local wlua = require "wlua" local app = wlua:new() app:get("/", function (c) c:send("Hello wlua!") end) app:run()
跟 lor 还是有点区别的,这里参考了 gin 框架的样式,回调函数的参数只有 c ,是 context 对象,这个对象包含了此次客户端请求的所有信息和相关的操作。
c
context
app 这个对象也参考了 gin 框架的 engine 对象,代码结构也和 gin 框架类似。lualib 目录结构是这样的:
lualib/ ├── config.lua ├── log.lua ├── middleware │ └── logger.lua ├── r3.lua ├── util │ ├── date.lua │ ├── file.lua │ ├── json.lua │ ├── string.lua │ └── table.lua ├── wlua │ ├── agent.lua │ ├── context.lua │ ├── methods.lua │ ├── request.lua │ ├── response.lua │ └── routergroup.lua └── wlua.lua
wlua.lua 就是上面 app 对象的类的实现。wlua 类主要包含了 router ,router 最初是采用的是很简单的 APItools/router.lua ,只要代码能跑起来随时都能把它替换掉。最后发现了一个性能很强的路由库 c9s/r3 ,参考了 iresty/lua-resty-libr3 的封装,自己封装成 hanxi/lua-r3 。主要接口代码就是上面的 r3.lua 文件,之前封装的时候也写过一篇相关文章记录 https://blog.hanxi.cc/p/49 。
wlua.lua
app
wlua
router
r3.lua
一个客户端请求包含什么呢?主要就者两个:
基本就是请求和回应了,context 把 request 和 response 组合在一起,方便使用者操作。
中间件也参考了 gin 的中间件接口和实现,也实现了一个 logger 中间件来输出 access log 。采用 use 来使用中间件,中间里采用 c:next() 函数来执行后续的 handlers 函数。
use
c:next()
handlers
实现的 http method 就是下面这些,也基本够用了。
local M = { GET = true, POST = true, PUT = true, DELETE = true, PATCH = true, HEAD = true, OPTIONS = true, } return M
统计了下 lualib 目录下的代码,也就 820 行,还是很简洁的,开发过程中的看板可以参考下 https://github.com/hanxi/wlua/projects/1 。
目前除了精简,就只剩下不足了,比如没有实现重定向接口。而且 reload 目前还是有点粗鲁的,只是发个消息退出,如果有挂起的逻辑,会造成逻辑只跑了一半就退出了,还是有优化的余地的。
另外想学 skynet 的话,可以试试我写的这门实战课程 《Skynet 游戏服务器开发实战》 , 地址: https://www.lanqiao.cn/courses/2770 优惠邀请码: 2CZ2UA5u
2CZ2UA5u
看到很多简洁的 web 框架,总想自己造个轮子试试,边写边记录些比较。
参考框架
既然是造轮子,我当然选自己最熟悉的 Lua 语言了,可是已经有了基于 Openresty 的 lor 框架,所以底层我就又选用了我熟悉的 skynet 了。
明确目标: 基于 skynet 开发一个 web 框架。
web 框架都有些什么
主要功能
其他东西
轮子取舍
为了早点出轮子,且轮子是可玩的,我对功能做了取舍。计划第一个版本只完成下面这些功能:
为什么不实现模板呢?在现在,前后端分离开发的趋势下,模板显得没那么重要了。服务器只需要提供接口就行,模板都转移到了前端。
重定向的功能本来是计划中的,但是觉得不实现它也没什么问题,等需要的时候再补上吧。
版本规划
第一个版本定为 0.01 ,主要功能就是上面说的。后续版本现在也只是想想而已,比如目前只能在 Linux 下运行,可以尝试迁移到 Mac OS 和 Windows 下运行,因为不是必须的东西,所以就放在 TODO 计划中了。
开发路线
1. 根据参考的框架,确定框架
从使用者的角度来确定框架结构。首先是方便开发部署,所以参考了 lor 的方式,提供脚手架生成工程,工程中包含些操作脚本,比如
start.sh
,stop.sh
和reload.sh
这些。由于选用的底层是 skynet ,所以按照 skynet 推荐的方式开发,以 skynet 为 submodule 。预定的目录结果大概是这样的:
框架的主要代码都放在
lualib
目录,其他第三方库都放到3rd
目录。service
是自定义的 skynet 服务目录。框架使用 skynet 的特性很少,只用到了 2 种服务,一个主服务 main 和多个 agent 服务,web 开发逻辑都在 agent 服务上执行。
2. 首先让框架跑起来
首先就是参考
skynet/examples/simpleweb.lua
示例开启 http 服务。这里的例子把 agent 服务写在了同一个文件,把他拆开为service/main.lua
和lualib/wlua/agent.lua
两个文件,稍微改改就跑起来了。3. 代码架构设计
首先从使用者的角度来设计框架,使用者的目录结构大致是这样的:
可以看出,除了那些 sh 脚本,只有两个文件是主要的。
app/main.lua
就是agent
服务的入口,也是使用者开发 web 服务器的入口。conf/wlua.conf
是配置文件,我想要的app/main.lua
是这样的结构,和 lor 框架的非常类似。跟 lor 还是有点区别的,这里参考了 gin 框架的样式,回调函数的参数只有
c
,是context
对象,这个对象包含了此次客户端请求的所有信息和相关的操作。app 这个对象也参考了 gin 框架的 engine 对象,代码结构也和 gin 框架类似。
lualib
目录结构是这样的:wlua.lua
就是上面app
对象的类的实现。wlua
类主要包含了router
,router
最初是采用的是很简单的 APItools/router.lua ,只要代码能跑起来随时都能把它替换掉。最后发现了一个性能很强的路由库 c9s/r3 ,参考了 iresty/lua-resty-libr3 的封装,自己封装成 hanxi/lua-r3 。主要接口代码就是上面的r3.lua
文件,之前封装的时候也写过一篇相关文章记录 https://blog.hanxi.cc/p/49 。一个客户端请求包含什么呢?主要就者两个:
基本就是请求和回应了,context 把 request 和 response 组合在一起,方便使用者操作。
中间件也参考了 gin 的中间件接口和实现,也实现了一个 logger 中间件来输出 access log 。采用
use
来使用中间件,中间里采用c:next()
函数来执行后续的handlers
函数。实现的 http method 就是下面这些,也基本够用了。
最后
统计了下 lualib 目录下的代码,也就 820 行,还是很简洁的,开发过程中的看板可以参考下 https://github.com/hanxi/wlua/projects/1 。
目前除了精简,就只剩下不足了,比如没有实现重定向接口。而且 reload 目前还是有点粗鲁的,只是发个消息退出,如果有挂起的逻辑,会造成逻辑只跑了一半就退出了,还是有优化的余地的。
另外想学 skynet 的话,可以试试我写的这门实战课程 《Skynet 游戏服务器开发实战》 , 地址: https://www.lanqiao.cn/courses/2770 优惠邀请码:
2CZ2UA5u
相关链接