skynet分析

更新时间:2023-07-19 05:46:17 阅读: 评论:0

目录结构分析
1. skynet-src:基础框架核心【c】,编译生成skynet主程序
2. rvice-src:模块实现【c】,rvice_* 编译成 crvice/*.so
3. lualib-src:库【c】,lua-* 编译成 luaclib/*.so,库里有luaopen_*,注册被lua调用的函数
4. lualib:库【lua】
5. rvice:模块实现【lua】,各种功能模块主要开发部分
依托关系图
skynet 框架做什么
skynet 维护全局消息队列 global_mq 和服务消息队列 mq,每个服务(多数是lua vm)有自己的私有消息队列挂在全局消息队列
工作线程会从全局的 globe_mq 中取 mq 来处理(通过消息队列中保存的 handle 找到对应的服务实例 ctx,执行 ctx 的回调函数)
总结:skynet 维护消息队列,支持投递分发,启动工作线程弹出消息处理
从启动流程开始解析
模块管理【模块包含 *_create *_init *_relea】,用来生成管理实例
模块生成实例 skynet_context_new()
每个实例生成的关键点:生成服务实例ctx,注册handle到框架,生成私有服务队列挂载到全局队列,绑定回调函数接受消息驱动妻悍家福
lua 服务的沙盒管理
launch的消息会由框架分派到 launcher.lua 【.launcher 在 bootstrap.lua 中已经绑定完成】
根据协议会调用 command.LAUNCH --> skynet.launch(snlua, name)
skynet_rver.c cmd_launch 最终还是调用 skynet_context_new(),跟上面提到的服务实例化流程一
snlua模块帮助lua服务做了以下基础事情:生成独立lua_state,生成ctx服务实例,生成私有消息服务队列
lua 服务的启动和回调设计
所有 lua 服务都是 snlua 模块生成的,就会调用 snlua_init 初始化元宵节习俗有哪些
snlua_init初始化的时候第一个消息驱动服务【rvice_snlua.c】_launch --> _init --> 【loader.lua】执行*.lua
*.lua 服务实现,必须调用 skynet.start() start会注册dispatch_message为当前lua服务回调函数
skynet_dispatch_message 根据prototype 调用不同的 dispatch
至此 lua 服务也参与到框架中
动漫头像冷酷
lua 服务的消息交互
每个skynet服务都是处理消息和发送消息,大部分消息工作在请求回应模式 call,消息ssion由发起方生成(框架自动关系),回应方回应时带回,0表示不需要回应
享受生活作文每个服务都有32位数字地址,高8位表明所属节点,skynet.lf() 获得服务自己的地址,skynet.harbor()获得服务所属节点
可以给服务起名,用ister(name)注册别名,skynet.name(name,address)为某个地址命名
消息分发和回应
dispatch()注册具体协议(需要先注册消息类别),对应的处理函数表,CMD{}
register_protocol() 注册消息类别,多数处理"lua"类型的消息已经默认注册只需要dispatch,自定义新类别需要同时定义pack,unpack进行消息编码解码
pack 把lua消息打包成 c指针和长度,unpack 把c指针和长度解析成lua对象
<() 接受c指针和长度,将消息附上当前ssion以及skynet.PTYPE_RESPONSE发回给消息的source,一般可以(skynet.pack(...)),框架中也有pack(...)
如果回应的消息需要先挂起等将来条件满足再回应,可以调用 spon(skynet.pack)
消息推送和远程调用
skynet.nd(address, typename, ...) 把类型为typename的消息发送给address,它会先经过事先注册的pack函数打包
skynet.call(address, typename, ... )内部生成一个唯一ssion,向address提起请求并阻塞当前 coroutine 等待回应,回应会返回ssion来查找对应 coroutine,unpack解包
skynet.call 仅仅阻塞当前 coroutine ,服务内的状态在调用前和返回处理时很可能被改变
skynet.rawcall(address, typename, msg, size)不经过打包直接发送,回应也不经过解包
skynet 数据共享(datacenter, sharedata)
master节点会开启一个服务 datacenter,类似一个全网共享的树结构注册表
datacenter.t(key1,key2,...,value)设置value,key层级支持多层
<(key1,key2,...)取得value,key层级支持多层
datacenter.wait(key1,key2,...)取得value,区别是如果当前没有值会等待
上述接口都会阻塞当前 coroutine,会网络通信,哪怕请求的是本节点共享的数据
-----------------------------
sharedata 共享本节点数据(new, update, query, delete)
skynet 服务地址的管理 rvice_mgr.lua
当节点中的服务是单例的需求,skynet.uniquervice() 可以获取某个模块的单例服务实例(没有找到实例的话会调用 wrvice() 创建)
支持全网单例,请求的时候第一个参数bool会表示是否全网单例,全网单例会从 master 节点的 rvice_mgr 请求
相比上面的数据中心共享,这个模块只提供服务地址的共享,而且本地节点会有缓存,减少数据通信
skynet 怎么实现分布式
skynet 中有 harbor 模块用来投递远程消息,同一个skynet中的所有服务地址高8位都是相同的,远程消息都会被投递到 harbor 中转
根据配置文件启动 cmaster 和 cslave,这两个服务是管理命名,连接处理的上层
cmaster 服务启动之后,监听端口等待 slave 启动发送握手消息
cslave 服务启动之后,会根据配置的 master 地址进行握手
1. slave 连接 master 发送握手消息教养笔记小班
2. master 通知现有 slave_node 连接新加入的 slave,同时通知 slave 现有N个 slave_node,把 slave 加入到 slave_node 队列
3. slave 启动 monitor_master 协程监听 master 的通知,(比如新加入slave的连接通知)
4. 等待现有的N个 slave_node 连接,管理建立的连接到 slaves,然后关闭socket监听
harbor 服务实例是负责中转远程消息的真正执行者,上面 slave 之间的连接是 harbor 实际进行
cslave 处理来自 harbor.lua 的 lua 协议(在全网查找服务名字,任何服务需要注册全局名字),处理来自 harbor.so 模块的 text 协议(查询全局名字,断开harbor),处理来自 master 的连接广播
遐组词组harbor.so 处理(PTYPE_HARBOR 消息来自 cslave 命名,连接),处理(PTYPE_SYSTEM 消息发
送到远程)
skynet 组播广播
multicastd 模块生成实例 snlua multicastd,每个节点都只有一个单例,会在数据中心注册,专门负责组播频道管理
multicastd 管理着 channel 某频道订阅者列表,channel_remote 某频道远程订阅者列表
节点内可生成多个订阅者,订阅者可以订阅本地或者远程频道,订阅远程频道的时候,multicastd 会像远程节点的 multicastd 订阅(加到对方的 channel_remote)
文明旅游倡议书new() 创建频道,返回频道id
new(conf) 根据提供的参数加入频道,消息收到后的回调
subscribe() 订阅频道,接收广播消息的前提
publish() 发布消息,如果有远程订阅者,会广播消息内容到远程的 multicastd,再由它广播给同节点下的订阅者,会触发订阅者的回调
同节点内广播消息指针,跨节点广播消息内容,跨节点依赖,跨节点通过数据中心查找频道信息
snax 框架
lua层实现了一个比skynet层更简单使用的框架,启动的服务是 snlua snax xxx
snax 框架约定了预置的几个接口,init,exit,hotfix。还提供了 accept(接受不回应) 和 respon(接受并且回应) 两类接口
调用 和 对应调用服务定义里的 accept 函数和 respon 函数
时间和线程
skynet 服务中单位时间是 0.01秒
skynet.starttime() 服务节点启动的utc时间,秒
skynet.time() 当前utc时间,秒
skynet.sleep(ti) 当前 coroutine  挂起 ti 单位时间,会向框架注册定时器,触发定时器后会通过 skynet.wakeup 唤醒
skynet.yield() 等价 skynet.sleep(0)
skynet.timeout(ti, func) 注册定时器在 ti 单位时间后调用 func,不会阻塞当前 coroutine,func 会在新的 coroutine 被执行
skynet.fork(func) 立即启动一个新的 coroutine 来执行 func
skynet.wait() 挂起当前 coroutine 等候 skynet.wakeup属猪

本文发布于:2023-07-19 05:46:17,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/82/1104487.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:消息   服务   节点   生成   实例
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图