Skip to content
Hanlei Qin edited this page Jan 14, 2016 · 85 revisions

fork了一份副本本组织
是否需要将本页wiki内容转移至相关的wiki页面
算了,暂时还是在这里汇总为主吧。

资料汇总

其他

概览

设计理念

  • 作者的设计综述:
    http://blog.codingnow.com/2012/09/the_design_of_skynet.html
  • 单进程多线程
  • 核心功能:服务
  • 主张所有的服务都在同一个 OS 进程中协作完成
  • 可以视Skynet为一个简单的操作系统,每个服务都是这个系统中的进程。
  • 核心层内,不考虑跨机通讯的机制
  • 不为单独一个服务的崩溃,重启等提供相应的支持 (任其崩溃哲学

Actor model

Source Architecture

源码文件解析见 skynet source files

// 未给出注释的,可在本wiki页内搜索相关主题
Skynet (2016-01-14 以tree命令导出, 3rd/jemalloc/ 处有删减)
├─3rd
│  ├─jemalloc   // 可选是否hook的,高效内存分配库 
│  ├─lpeg       // lua 的模式匹配库,看云风的博客[注1]可做解析protocol buffer用 
│  ├─lua        // lua5.3 修改版 (详见后文)
│  └─lua-md5
├─examples      // 示例
│  └─login      
├─lualib        // lua 实现的程序库
│  ├─http
│  ├─sharedata
│  ├─skynet
│  └─snax       // 详见后文
├─lualib-src    // C 实现的动态库,供 Lua 调用
│  └─sproto     // 类 protocol buffer 的精简版
├─service       // lua 实现的 服务(详见后文) ,供 snlua 服务启动
├─service-src   // C 实现的 服务
├─skynet-src    // skynet 核心
└─test


1.Proto Buffers in Lua

服务

定义

  • 从动态库(so 文件)中启动起来的一个符合规范的 C 模块,该模块称为服务(service)。
  • 每个服务都是被一个个消息包驱动,当没有包到来的时候,它们就会处于挂起状态,对 CPU 资源零消耗。

属性

  • 绑定有一个永不重复(即使模块退出)的数字 id 做为其 handle
  • handle 的最终限制在 24bit 内,也就是 16M 个。
  • handle 高8位,保留给集群间通讯用的。

行为

  • 可以向 Skynet 框架注册一个 callback 函数,用来接收发给它的消息。
  • 服务间可以自由发送消息

扩展

  • 如需自主逻辑,可用 Skynet 系统提供的 timeout 消息,定期触发。

Skynet 中的 Lua修改版

集群

Master/Slave

  • 对单台物理机计算能力不足情况下的补充
  • 整个网络中任意一个节点都必须正常工作,节点间的联系也不可断开。
    1. 这就好比你一台物理机上如果插了多块 CPU ,任意一个损坏都会导致整台机器不能正常工作一样。
    2. 不要把这个模式用于跨机房的组网,所有 slave 节点都应该在同一局域网内。
节点
  • 每个 skynet 节点有不同的 id 。
  • 允许 255 个 skynet 节点部署在不同的机器上协作
  • 每个节点都是一个 slave
  • 选某个slave配置standalone来启动一个cmaster 服务,该节点同时为master
  • master 节点用于协调 slave 组网
harbor

Cluster

  • 多组 Master/Slave 网络。
  • 部署多组 master/slave 网络,然后再用 cluster 将它们联系起来。
  • 比较简单的结构是,每个集群中每个节点都配置为单节点模式(将 harbor id 设置为 0)。

通讯

摘要:

  目前 skynet 的 gate 服务约定的协议是,2 字节( 大头编码)表示一个 64K 字节内的数据包,然后接下来就是这个长度的字节数。我曾经考虑过使用 4 字节或 google proto buffer 用的 varint ,但最后都放弃了。
  考虑到实现的便捷,通常收到长度后,会在内存考虑指定长度的 buffer 等待后续的数据输入。这样,如果有大量攻击者发送超长包头,就会让服务器内存瞬间消进。所以,这种协议只要实现的不小心,很容易变成攻击弱点。
  注:skynet 最早期的 gate 实现反而没有这个问题。因为它使用了单一的 ringbuffer ,只发送包头却不发送数据的连接会在 ringbuffer 回绕的时候被踢掉。
  游戏服务器如果只使用一条 TCP 长连接的情况下,单个数据包过大(> 64K),也是不合适的。 大包会阻塞应用逻辑(收取和发送它们都需要很长的时间),如果在应用层有心跳控制的话,也很容易造成心跳超时。所以一般在应用层对大数据包再做上层协议的切割处理。

Snax

Run Skynet

工具

实战经验谈

以下斜体字为摘要,链接地址上有文章创建的日期(注意时效性,有些或与当前skynet架构不符)

Clone this wiki locally