Skynet:特性收集

  基于云风的 blog,收集 skynet 的特性以便将来在代码中一一验证。

  “ ... ” 部分节选自云风的 BLOG。

1. 基于 Erlang-Actor 模式的 C 实现

  “把一个符合规范的 C 模块,从动态库(so 文件)中启动起来,绑定一个永不重复(即使模块退出)的数字 id 做为其 handle 。模块被称为服务(Service),服务间可以自由发送消息。每个模块可以向 Skynet 框架注册一个 callback 函数,用来接收发给它的消息。每个服务都是被一个个消息包驱动,当没有包到来的时候,它们就会处于挂起状态,对 CPU 资源零消耗。如果需要自主逻辑,则可以利用 Skynet 系统提供的 timeout 消息,定期触发。”

  “Skynet 原则上主张所有的服务都在同一个 OS 进程中协作完成。Skynet 只负责把一个数据包从一个服务内发送出去,让同一进程内的另一个服务收到,调用对应的 callback 函数处理。它保证,模块的初始化过程,每个独立的 callback 调用,都是相互线程安全的。”

2. skynet 不予解决的问题

  “Skynet 的消息传递都是单向的,以数据包为单位传递的。并没有定义出类似 TCP 连接的概念。也没有约定 RPC 调用的协议。不规定数据包的编码方式,没有提供一致的复杂数据结构的列集 API 。”

3. 服务间通信的优化

  如果有必要,数据包在处理过程中可以实现零拷贝:“Skynet  并不关心数据包是怎样被打包的。它仅仅是把数据包的指针,以及你声称的数据包长度(并不一定是真实长度)传递出去。由于服务都是在同一个进程内,接收方取得这个指针后,就可以直接处理其引用的数据了。”

  当然,绝大多数应用场景应该有必要采用另外一种方案:“Skynet 推荐的是一种更可靠,性能略低的方案:它约定,每个服务发送出去的包都是复制到用 malloc 分配出来的连续内存。接收方在处理完这个数据块(在处理的 callback 函数调用完毕)后,会默认调用 free 函数释放掉所占的内存。”,这样至少是直接访问内存,而不是用消息通讯的方式。

  服务间通信 session:服务内对其他不同服务回调的区分;type:消息类型;

4. 进程间通信:

  “单个 skynet 进程内的服务数量被 handle 数量限制。handle 也就是每个服务的地址,在接口上看用的是一个 32 位整数。但实际上单个服务中 handle 的最终限制在 24bit 内,也就是 16M 个。高 8 位是保留给集群间通讯用的。我们最终允许 255 个 skynet 节点部署在不同的机器上协作。每个 skynet 节点有不同的 id 。这里被称为 harbor id 。”

  “每个消息包产生的时候,skynet 框架会把自己的 harbor id 编码到源地址的高 8 位。这样,系统内所有的服务模块,都有不同的地址了。从数字地址,可以轻易识别出,这个消息是远程消息,还是本地消息。”

  “所有的消息包在发送时,skynet 识别出这是一个远程消息包时,都会把它转发到 harbor 服务内。harbor 服务会建立 tcp 连接到所有它认识的其它 skynet 节点内的 harbor 服务上。”

  “skynet 目前支持一个全局名字服务,可以把一个消息包发送到特定名字的服务上。这个服务不必存在于当前 skynet 节点中。这样,我们就需要一个机构能够同步这些全局名字。为此,我实现了一个叫做 master 的服务。它的作用就是广播同步所有的全局名字,以及加入进来的 skynet 节点的地址。”

5. 服务间广播:

  广播包引用计数:“skynet 会识别消息的 type 是否为 PTYPE_MULTICAST ,然后有不同的生命期管理策略,并把组播包交给组播服务处理。”

  “组播服务并不解决分熟在不同集群节点上的服务归组的问题。即,每个分组内的成员都必须在同一系统进程内。这可以极大的简化设计。用户可以让不同的服务 handle 归属一个组号。向 skynet 索取这个组号对应的 handle 。向这个组的 handle 发送消息,就等同于向组内所有 handle 发送消息。”

  跨进程分组:“首先,提供了一个简单的,用 C 编写的服务,叫做 tunnel 。它可以把发送给它的消息,无条件的转发到另一个 handle 上。这个转发 handle 可以是在不同 skynet 节点上的。”,“我用 lua 编写了一个全局的分组管理器,协调在不同节点上,创建出相同组名的分组来。然后用 tunnel 服务连接不同节点上的同一分组就够了。”

6. 基础服务的流程控制:

  “skynet 提供了一个叫做 skynet_command 的 C API ,作为基础服务的统一入口。它接收一个字符串参数,返回一个字符串结果。你可以看成是一种文本协议。但 skynet_command 保证在调用过程中,不会切出当前的服务线程,导致状态改变的不可预知性。”

7. 消息调度

  “在 Skynet 启动时,建立了若干工作线程(数量可配置),它们不断的从主消息列队中取出一个次级消息队列来,再从次级队列中取去一条消息,调用对应的服务的 callback 函数进行出来。为了调用公平,一次仅处理一条消息,而不是耗净所有消息(虽然那样的局部效率更高,因为减少了查询服务实体的次数,以及主消息队列进出的次数),这样可以保证没有服务会被饿死。”

  从业务需求出发,核心在于每次业务处理是否会对同一个数据块进行写操作,如何会的话,服务之间就要进行同步协调,那么不如用单个服务轮询的方式好处理。

  我的业务需求是聊天室。公共聊天室的话,启动多个服务,每个服务需要做2件事:1. 收到广播消息后向其他用户广播 - 用户信息要保存在进程中。2. 将广播消息写入一个缓存队列。在此基础上,需要实现一个定时将缓存队列中的新数据持久化的服务。

  如果用 skynet 做聊天服务器的话,为了充分利用消息调度的机制 与 skynet 对多核的利用,可以采用 “skynet 服务池” 来处理所有玩家的聊天请求。

8. Gate

  "它的特征是监听一个 TCP 端口,接受连入的 TCP 连接,并把连接上获得的数据转发到 skynet 内部。Gate 可以用来消除外部数据包和 skynet 内部消息包的不一致性。"

9. Connection

  "Connection 分两个部分,一部分用于监听不同的系统 fd 的可读状态,这是用 epoll 实现的。如果在没有 epoll 支持的环境(比如 freebsd 下),可以很轻松的实现一个替代品。它收到这个连接上的数据后,会把所有数据不做任何分包,转发到另一个服务里去处理。"

  "使用提供好的 lua 模块,可以轻松的对这些数据分包(读一个指定字节数的数据块,或是读一个以回车结束的文本行)。Lua 的 coroutine 支持,可以轻松的在数据包并不完整时挂起,却不打断执行流程。"

10. Lua 层

  “Lua 的 coroutine 可以帮助我们把一个个在 C 层面分离的 callback 调用串成逻辑上连续的线索。当 Lua 编写的服务接收到一个外部请求时,对应的底层 callback 函数被调用,既而转发到 Lua 虚拟机中。skynet 的 lua 层会为每个请求创建一个独立的 coroutine 。一旦在处理这个请求的 coroutine 中发生远程调用,即发出一个消息包,coroutine 会挂起。在 C 层面,这次 callback 函数正常返回了。但在 Lua 中,则是记录下这个发出的消息包的 session ,记录 session 和挂起的 corutine 在一张对应表中。之后,一但收到回应包里有相同的 session ,对应的 coroutine 则被唤醒 resume 。”

时间: 2024-10-13 23:36:47

Skynet:特性收集的相关文章

delphi 各新版本特性收集

delphi 各新版本特性收集 Delphi XE6新增了一些特性并增强了原有的功能,主要有以下几个方面: IDE(整合开发环境) Internet XML(扩展标记语言) Compiler(编译器) COM/Active X Database support(数据库支持) CORBA Actions(动作) Custom Variants(可定义的可变类型) VCL 单元和特性 RTL单元和特性 Cross-platform development(跨平台开发) Translation too

Java 5/Java 6/Java7/Java 8新特性收集

前言: Java 8对应的JDK版本为JDK8,而官网下载回来安装的时候,文件夹上写的是JDK1.8,同一个意思.(而这个版本命名也是有规律的,以此类推) 一.Java 5 1.https://segmentfault.com/a/1190000004417288 二.Java 6 2.https://segmentfault.com/a/1190000004417536 三.Java 7 1.http://www.eclipse.org/jdt/ui/r3_8/Java7news/whats-

Java 5/Java 6/Java7/Java 8新特性收集(转载)

Java 8对应的JDK版本为JDK8,而官网下载回来安装的时候,文件夹上写的是JDK1.8,同一个意思.(而这个版本命名也是有规律的,以此类推) 一.Java 5 1.https://segmentfault.com/a/1190000004417288 二.Java 6 2.https://segmentfault.com/a/1190000004417536 三.Java 7 1.http://www.eclipse.org/jdt/ui/r3_8/Java7news/whats-new-

Java 8新特性

现在,是时候把所有Java8的重要特性收集整理成一篇单独的文章了,希望这篇文章能给你带来阅读上的乐趣.开始吧! 目录结构 介绍 Java语言的新特性 2.1 Lambdas表达式与Functional接口 2.2 接口的默认与静态方法 2.3 方法引用 2.4 重复注解 2.5 更好的类型推测机制 2.6 扩展注解的支持 Java编译器的新特性 3.1 参数名字 Java 类库的新特性 4.1 Optional 4.2 Streams 4.3 Date/Time API (JSR 310) 4.

Atitit  技术经理职责与流程表总结

Atitit  技术经理职责与流程表总结 1. (最重要) 理念 价值观建设  ***团队文化建设2 1.1. 加强跨项目组员沟通 ,防止重复劳动2 1.2. 活动聚餐2 2. (重要)方向建设 技术战略制定?规划,预测趋势12 2.1. 关键词?Throught技术雷达 趋势 没落 ?已死 ?辉煌 未来12 2.2. (比较重要)新特性收集(ui os,db,框架,类库)12 2.3. 1.4.(较为重要)学术会议交流22 2.4. 1.5.?规范涉猎与商业规划22 2.5. 3.4.?技术选

关于在C#对抽象类的理解

先说一下自己对类的理解吧.类就是指将一系列具有一些共同特性的事物归纳起来,按照不同的特性分为不同的类.比如在现实世界中人是一类,动物是一类.植物又是一类.但他们都是生命这一类的派生类.他们都继承了生命类的一些特性.但他们各自又有一些不同的属性.在计算机世界中也有这样的类.类这一特性在面向对象的语言中就有很好的体现. 个人理解C#中的抽象类是将某些类都具有的一些特性收集起来.然后再用这个抽象类来定义一些子类.当然这些子类可以自己再扩充一些私有的属性和方法.比如正方形和长方形他们都具有的属性是面积,

关于在C#中对抽象类的理解

先说一下自己对类的理解吧.类就是指将一系列具有一些共同特性的事物归纳起来,按照不同的特性分为不同的类.比如在现实世界中人是一类,动物是一类.植物 又是一类.但他们都是生命这一类的派生类.他们都继承了生命类的一些特性.但他们各自又有一些不同的属性.在计算机世界中也有这样的类.类这一特性在面向 对象的语言中就有很好的体现. 个人理解C#中的抽象类是将某些类都具有的一些特性收集起来.然后再用这个抽象类来定义一些子类.当然这些子类可以自己再扩充一些私有的属性和方法.比如 正方形和长方形他们都具有的属性是

Atitti cto的日常流程与职责attilax总结

1. (最重要)技术战略制定 规划,预测趋势1 1.1. 关键词 Throught技术雷达 趋势 没落  已死  辉煌 未来1 1.2. (比较重要)新特性收集(ui os,db,框架,类库)1 1.3. (内部建设)指标准化草案2 1.4. (较为重要)学术会议交流2 1.5. 规范涉猎与商业规划2 1.6. 工具链体系建设2 2. ***团队文化建设2 3. (一般)内部制度建设2 3.1. (内部建设)指明方向,推荐规范与标准化  开发流程与方法3 3.2. (内部建设)项目文档规范3 3

用Spring构建一个RESTful Web Service

本教程将手把手教你用Spring构建一个"hello world" RESTful Web Service. 你将构建什么 你将构建一个Web Service,用于接收HTTP GET请求,请求地址: http://localhost:8080/greeting 请求响应返回一段JSON格式的问候语: {"id":1,"content":"Hello, World!"} 你可以在请求中添加一个可选参数:name,定制问候语: