- 论坛徽章:
- 4
|
本帖最后由 linux_c_py_php 于 2013-04-17 13:34 编辑
lua_frame.tar.gz
(11.86 KB, 下载次数: 159)
项目说明:
以c编写基于epoll的单线程网络服务端,嵌入lua以便支持脚本编写请求处理逻辑,并且完美的支持了yield。
工作原理为:
一,c服务端框架:
1) 一个session对应一个coroutine,所有session共享同一个main thread。coroutine的引用计数在main thread的一个table中维持, 即fd->coroutine的映射。
2)负责网络I/O,负责request的解析并将其加入到所属session的request-queue尾部。根据session(连接,会话)的request-queue是否为空并处于coroutine yield的状态(wait_req标记位)决定是否需要调用lua_resume唤醒lua处理request-queue。
3)每个session都有独立的定时器检查coroutine状态,如果coroutine因为语法等任何错误而死亡,能够及时的探测并踢除session的连接。
二,lua扩展框架中:
1)用户编写main.lua,填写业务回调callback函数, 之后调用start_consume即进入了请求处理循环。
2)start_consume将检查request queue来获取一个request,如果没有request则yield挂起等待c框架唤醒,否则将request传给用户callback进行处理。
3)并提供给了用户一些lua api进行编程, 现在只提供了一个发送报文的接口, 后续会给出定时器, 连接/读/写 等异步编程接口.
不便之处:
1,由于c服务端只有一个main thread(全局lua_State),每个session都是在main thread创建的coroutine thread上执行的,所以是通过设置coroutine.resume(callback)
中的callback的_ENV(第一个upvalue)实现每个coroutine都拥有独立的session全局变量。结果就是,在实现lua module的时候,由于require继承全局环境而非callback的环境, 导致在开发时不得不将session变量从main.lua(只有main.lua的_ENV里可见session)向下传递。(@_@,但愿你看代码的时候能够体会)
其他说明:
为了体现lua给c带来了什么好处, 我开发了一个lua api叫做block_alarm,其作用是阻塞N毫秒之后执行回调函数,这对于lua开发者来说是看似阻塞的,但对于c服务端框架来说是完全异步的,并不会阻塞其他连接的处理。
使用示例:- sapi = require('sapi')
- require('os')
- function cb(sess, req)
- first = "curtime=" .. tostring(os.time()) .. " req=" .. req
- sapi.write_response(sess, first)
- function alarm_cb(arg)
- second = "curtime=" .. tostring(os.time()) .. " res=" .. req
- sapi.write_response(sess, second)
- end
- sapi.block_alarm(sess, 4000, alarm_cb, req)
- end
- sapi.start_consume(session, cb)
复制代码 sapi是我提供的基础lua module,用于和c服务端进行交互,一共就3个接口,大家看一下:- module('sapi', package.seeall) --session api
- local capi = require('capi')
- --get a request from session->reqs if not empty,
- --otherwise it will do yield.
- --you have to notice that we are already in coroutine here
- function get_req(session)
- req = capi._get_req(session)
- while req == nil do
- coroutine.yield()
- req = capi._get_req(session)
- end
- return req
- end
- function write_response(session, content)
- return capi._write_response(session, content)
- end
- function block_alarm(session, timeout, callback, arg)
- capi._block_alarm(session, timeout)
- coroutine.yield()
- callback(arg)
- end
- function start_consume(session, cb)
- while true do
- req = get_req(session)
- cb(session, req)
- end
- end
复制代码 欢迎lua志同道合的朋友一起研究lua,并给该项目的设计思路中错误或者不足的地方给予指正。 |
|