@wsd1
2017-04-05T20:33:54.000000Z
字数 4110
阅读 1432
ucast
skynet
201704
本文章作为设计指导文档,内含不少特定名词,假设读者理解 ot协议传输层大致逻辑、JSON-RPC的命名空间 这些背景知识,否则看起来可能晦涩难读。
若为使用故,可以仅看图和代码即可。
skynet_uc是skynet ucast的字面组合,ucast使用skynet框架构造物联网系统的服务端部分。传输层面用C撰写,分发层面使用lua撰写。
分发层面不仅支持独立撰写lua业务逻辑,还加入了deepstream的客户端,为业务层提供实时化的能力。
Github项目:
https://github.com/cloudwu/skynet
wiki:
https://github.com/cloudwu/skynet/wiki
云大的心路历程(skynet改了很多,关注作者的思路,从以前版本可以发掘很多好东西,比如JSON支持):
http://blog.codingnow.com/eo/skynet/
Lua5.3的文档:
http://cloudwu.github.io/lua53doc/manual.html#6.4.1
目前的架构中代码关系如下:
1、配置文件 “examples/config.ucast” 指定“ucast.lua”作为引导代码;后者引导其他部件;
2、首先引导 “test/ds.lua”(deepstream客户端);
3、其次引导 “service/ot_router.lua”(上行方法分发器);
4、再次引导 “service/ot-agent/otc.lua”(_otc.xxx RPC provider)
5、“3rd/lua-ot/lua-ot.c” 实现了 “otu_service.c” 和 lua层面的pack、unpack功能;
6、“lualib/ot/ds_util.lua” 和 “lualib/ot/ot_util.lua” 用来提供api调用时的一些辅助功能;
7、“lualib/websocket.lua” 和 “test/ds.lua” 提供了一个deepstream客户端
实现了ds服务器的客户端,通过“lualib/ot/ds_util.lua”为其他业务模块提供ds服务。比如,“ot_router.lua”、“otc.lua”都是通过其和外部沟通的。
这个代码会引导C实现的otu模块(otu_service.c),并且在之后处理otu上行的JSON_RPC;它提供了注册接口接受其他业务代码注册方法空间,上行RPC会转交给其他业务,比如service/ot-agent/otc.lua 就是专门处理 _otc.xxx类型rpc的业务模块。
otc在ucast.lua中被引导,同时也被触发向ot_router安装了自己的命名空间。
其会与ds模块建立联系,listen "event/ot/info/"和"event/ot/devlog/"两个event的订阅;若是有有客户端订阅了某个did的相应事件,就会被记录下来,一旦上行有_otc.info 和 _otc.devlog的请求,就会被emit到ds。
这个是工作量最大的一个部分:向下实现了传输层面对UDP报文的处理和OT协议的实现,向上实现了和skynet lua层面交互接口。 其还应该包括 “3rd/lua-ot/lua-ot.c” ,完整的实现了与业务层面的对接。
ot_router.lua 作为与设备最近的lua层逻辑,负责分发上行ot-rpc的信息,其为ds-client实现了如下接口:
ot_router.lua 向 ds provide了 “rpc_otu_call” 接口。借此可以实现:
1、下行RPC控制设备
其他ds客户端可以make rpc实现下行控制设备,读取设备统计数据这些功能。
设备下行访问示例:
下行访问设备侧 uCast.info 接口。
//该代码演示 其他ds客户端 如何访问到ot_router.lua的RPC服务
var ds_rpc_param = {
D:255, //D字段指示下发设备DID
R:{ //R字段指示是下行请求
method: "uCast.info",
params:{},
//json-rpc id,用于标定请求和回应对应关系
id:234567 //只有需要RPC有返回时才需要该字段
}
}
client.rpc.make("rpc_otu_call", ds_rpc_param, function(err, ret) {
txt.innerText = JSON.stringify(ret, null, 2)
console.log(ret)
})
2、获取传输层设备统计信息
该信息来源于otu_service.c,其负责的传输层面对上下行交互过程中诸多的细节做了统计,"ot_router.lua"提供了访问接口,通过ds服务的 “rpc_otu_call” RPC可以获取该信息。
var ds_stat_param = {
D:255 //D字段指示下发设备DID
// <-- 注意这里,没有 R字段
}
client.rpc.make("rpc_otu_call", ds_stat_param, function(err, ret) {
txt.innerText = JSON.stringify(ret, null, 2)
console.log(ret)
})
/* 结果类如:
{
"online": true, //当前是否在线
"reqCost10": 11, //下行请求回应间隔时间近10次平均
"reqCost100": 10, //下行请求回应间隔时间近100次平均
"dnReq": 2, //下行请求数量
"dnNotify": 0, //下行通知数量
"dnReqFail": 0, //下行请求失败数量
"dnReqOK": 2, //下行请求一次成功数量
"upReq": 2, //上行请求数量
"upReqDrop": 0, //上行请求被抛弃的数量(可能是busy)
"upNotify": 46, //上行通知数量
"upKplv": 29, //上行保活数量
"upSync": 8, //上行同步数量
"lastseen": 1491330240, //最近出现的utc时间(不算sync)
"synDiff16": 0, //最近交互同步时差(绝对值)16次平均
"synDiff128": 0 //最近交互同步时差(绝对值)128次平均
}
*/
otc实现了 _otc命名空间 的业务逻辑,其实现了包括
“_otc.login”、“_otc.info”、“_otc.devlog” 三个上行ot-rpc接口。
“_otc.login” 用于实现设备登录;
“_otc.devlog” 用于设备提交调试日志信息;
“_otc.info” 用于实现设备上行更新信息;
后两个暴露给ds-client,使ds客户端可以方便的订阅设备的调试日志和更新信息。具体如下:
devlog 订阅通道是: “event/ot/devlog/xxx”,xxx表示设备did,示例代码:
client.event.subscribe('event/ot/devlog/255', function(value) {
txt.innerText = JSON.stringify(value)
})
/* 返回值示例:这是推流器发出的log
"000:32:14.424: [Rtmpc] @80241B/s"
*/
相对应的,在嵌入式Addon开发过程中,可以如下调用向云端_otc.devlog发送信息:
api_ot.otc_log("[Rtmpc] @%dB/s.", Bps);
该API可以方便的提交字符串到云端,服务器侧通过订阅“event/ot/devlog/xxx”来获取该字符串。
注意,该过程通过 “_otc.devlog” 上行notify通知实现,没有添加method_id,没有重发逻辑保证抵达,建议作为调试手段使用。
同时请注意不要过于频繁调动该API,否则会被服务端禁止。
info 订阅通道是: “event/ot/info/xxx”,xxx表示设备did,示例代码:
client.event.subscribe('event/ot/info/255', function(value) {
txt.innerText = JSON.stringify(value)
})
/* 返回值示例:
{
"life": 15500,
"mm": {
"max": 3886796,
"used": 3785700,
"total": 9277124
},
"mac": "CA:09:00:0F:14:16",
"netif": {
"localIp": "192.168.1.179",
"mask": "255.255.255.0",
"gw": "192.168.1.1",
"gw_mac": "8C:BE:BE:40:0A:A5"
},
"otu_stat": "20,20,16,4,12,5"
}
*/
上行ot-rpc接口“_otc.info”背景:
设备侧使用该rpc接口更新自己的设备状态,缺省设计是每30分钟或者切换服务器“_otc.login”之后调用该接口。
更加详细可以参考 “ot协议传输层设计”细节。
20170406:
gc之后:
mem
:0000000a 79.54 Kb (snlua ds)
:0000000b 50.33 Kb (snlua ot-router)
:0000000d 46.17 Kb (snlua ot-agent/otc)
:0000000c otu
多次下行call后,内存均增长,不过gc指令可以使其完全恢复原状。因此判断,通过DS下行call设备方法 lua层面路径正常。
推流后设备定时上行devlog,页面订阅后,内存均增长。但gc后恢复原状,判断上行订阅 lua层面路径正常。