skynet源码分析:服务

skynet是为多人在线游戏打造的轻量级服务端框架,使用c+lua实现。使用这套框架的一个好处就是,基本只需要lua,很少用到c做开发,一定程度上提高了开发效率。

skynet的例子是怎么调用的

服务器: 
simpledb.lua: skynet.register “SIMPLEDB” 向skynet里注册一个服务 
agent.lua: skynet.call(“SIMPLEDB”, “text”, text) 调用相应的服务 
main.lua: skynet.newservice(“simpledb”) 启动一个服务
以上函数都在\lualib\skynet.lua 文件内

以下是几个写服务时经常要用到的函数。

newservice(name, ...) 启动一个名为 name 的新服务。
uniqueservice(name, ...) 启动一个唯一服务,如果服务该服务已经启动,则返回已启动的服务地址。
queryservice(name) 查询一个由 uniqueservice 启动的唯一服务的地址,若该服务尚未启动则等待。
localname(name) 返回同一进程内,用 register 注册的具名服务的地址。

newservice可以在一个进程里启动多个服务,这适用于无状态的服务。
uniqueservice则是类似于设计模式中的单件(singleton),这适用于需要唯一性的服务。举个例子,比如写日志,只想写一份。或者是全局共享的数据。

消息机制

SKYNET设计综述讲到模块被称为服务。“服务间可以自由发送消息。每个模块可以向 Skynet 框架注册一个 callback 函数,用来接收发给它的消息。”还提到“把一个符合规范的 C 模块,从动态库(so 文件)中启动起来,绑定一个永不重复(即使模块退出)的数字 id 做为其 handle 。Skynet 提供了名字服务,还可以给特定的服务起一个易读的名字,而不是用 id 来指代它。id 和运行时态相关,无法保证每次启动服务,都有一致的 id ,但名字可以。”今天要分析的两个文件skynet_handle.c和skynet_handle.h就是实现名字服务的。

skynet_handle.c实际上就做了两个核心的事情,一是给服务分配一个handle,二是把handle和name关联起来。

把handle和name关联起来比较容易懂,实际上使用一个数组,关联的时候使用二分查找到数组里查名字,如果名字不存在,就插入一个元素,然后把名字和handle关联起来。插入元素的时候,如果数组空间不足了,就扩容为原来的2倍。

而给服务分配handle稍复杂一些,实际上也是使用一个slot数组,数组下标使用的是一个hash,数组元素指向服务的上下文。这个hash的算法是比较简单粗暴的,就是看从handle_indx开始累计到slot_size,看中间有没有空闲的下标(也就是下标指向为null的),如果遍历完了还是没有,就把slot扩大一倍,还是没有就再扩大一倍,直到找到空位为止,或者是slot长度超出限制为止。

取到了handle以后呢,还要将harbor id附到handle的高8位。

参考:

skynet源码分析(3)--消息名字和ID之handle

skynet教程(3)--服务的别名

原文地址:https://www.cnblogs.com/losophy/p/9203060.html

时间: 2024-10-08 17:33:19

skynet源码分析:服务的相关文章

SOFA 源码分析 —— 服务引用过程

前言 在前面的 SOFA 源码分析 -- 服务发布过程 文章中,我们分析了 SOFA 的服务发布过程,一个完整的 RPC 除了发布服务,当然还需要引用服务. So,今天就一起来看看 SOFA 是如何引用服务的.实际上,基础逻辑和我们之前用 Netty 写的 RPC 小 demo 类似.有兴趣可以看看这个 demo-- 自己用 Netty 实现一个简单的 RPC. 示例代码 ConsumerConfig<HelloService> consumerConfig = new ConsumerCon

netty 5 alph1源码分析(服务端创建过程)

参照<Netty系列之Netty 服务端创建>,研究了netty的服务端创建过程.至于netty的优势,可以参照网络其他文章.<Netty系列之Netty 服务端创建>是 李林锋撰写的netty源码分析的一篇好文,绝对是技术干货.但抛开技术来说,也存在一些瑕疵. 缺点如下 代码衔接不连贯,上下不连贯. 代码片段是截图,对阅读代理不便(可能和阅读习惯有关) 本篇主要内容,参照<Netty系列之Netty 服务端创建>,梳理出自己喜欢的阅读风格. 1.整体逻辑图 整体将服务

SOFA 源码分析 —— 服务发布过程

前言 SOFA 包含了 RPC 框架,底层通信框架是 bolt ,基于 Netty 4,今天将通过 SOFA-RPC 源码中的例子,看看他是如何发布一个服务的. 示例代码 下面的代码在 com.alipay.sofa.rpc.quickstart.QuickStartServer 类下. ServerConfig serverConfig = new ServerConfig() .setProtocol("bolt") // 设置一个协议,默认bolt .setPort(9696)

Dubbo 源码分析 - 服务导出全过程解析

1.服务导出过程 本篇文章,我们来研究一下 Dubbo 导出服务的过程.Dubbo 服务导出过程始于 Spring 容器发布刷新事件,Dubbo 在接收到事件后,会立即执行服务导出逻辑.整个逻辑大致可分为三个部分,第一是前置工作,主要用于检查参数,组装 URL.第二是导出服务,包含导出服务到本地 (JVM),和导出服务到远程两个过程.第三是向注册中心注册服务,用于服务发现.本篇文章将会对这三个部分代码进行详细的分析,在分析之前,我们先来了解一下服务的导出过程. Dubbo 支持两种服务导出方式,

DroidPlugin源码分析服务与静态广播的处理214r3rff4

上一篇文章分析过DroidPlugin对Activity的处理过程,不得不为对DroidPlugin的工程师们钦佩不已,那么是不是Service可以像Activity的处理过程一样来处理呢?前面讲过每一个代理进程只是预定义了一个Service,如果某一个插件中有多个Service,那岂不是某一个时刻只能有一个Service运行呢?由此可以判定可能Service的处理和Activity不一样. 一方面:平时使用Activity主要是用于展示界面和用户交互,Activity的生命周期可能受用户控制,

DroidPlugin源码分析服务与静态广播的处理

上一篇文章分析过DroidPlugin对Activity的处理过程,不得不为对DroidPlugin的工程师们钦佩不已,那么是不是Service可以像Activity的处理过程一样来处理呢?前面讲过每一个代理进程只是预定义了一个Service,如果某一个插件中有多个Service,那岂不是某一个时刻只能有一个Service运行呢?由此可以判定可能Service的处理和Activity不一样. 一方面:平时使用Activity主要是用于展示界面和用户交互,Activity的生命周期可能受用户控制,

skynet源码分析1:开篇明义

skynet是云风基于actor模型实现的一个服务器框架,核心七千多行c代码,并提供了一个lua binding.写得比较简明,用起来比较爽快,很合我的胃口,再加之决定在公司最近的一个项目上skynet,所以就决定精读一遍源码,将所思所想所得记录于此,以便用起来心安理得. skynet的实现基于如下几条actor行为: 能创建,销毁其它actor,actor间为平级关系. 能发送消息给其它actor,能接收其它actor的消息. actor间的交互只能通过消息传递. 能处理自己的消息. 在sky

skynet源码分析5:lua绑定之地基

前面四篇已经涵盖了skynet的c层核心,剩下的timer,socket模块本身和actor模型没什么关系,且比较独立,最后再看吧.光用skynet的c接口,是很难在这上面写业务逻辑的,所以要找一种更爽快的方式来使用.官方推荐的是lua,利用lua的协程对skynet的消息分发做了封装,使得actor之间的异步消息通信有同步一样的操作感,并且做了一些的扩展模块来方便使用.lua简洁实用的风格我个人也很钟意. 要想做一个lua binding来使用,要有两个必要条件: 根据skynet的模块契约实

skynet源码分析之cluster集群模式

比起slave/harbor集群模式,skynet提供了用的更为广泛的cluster集群模式,参考官方wiki https://github.com/cloudwu/skynet/wiki/Cluster.cluster模式利用socketchannel库(http://www.cnblogs.com/RainRill/p/8892648.html) 与其他skynet进程进行交互,每个请求包带一个唯一的session值,对端回应包附带session值.cluster集群模式tcp通道是单向的,