skynet luaAPI
skynet.localname(name)
以 . 开头的服务名字
基于Skynet框架开发的服务器是由若干个服务(Service)构成的,可以将Skynet看作是操作系统,服务则可以视为操作系统下的进程。实际上,单个Skynet节点仅仅使用一个操作系统进程,服务之间的通讯是在进程内完成的,所以性能比普通的操作系统进程间通讯要高效。
Skynet框架是使用C语言编写的,所以它的服务也是用C语言开发的。但框架已经提供了一个叫做snlua
的服务模块(C语言开发的),snlua
通过解析Lua脚本来实现业务逻辑。也就是说,可以在Skynet中启动任意多个snlua
服务,只是它们承载的Lua脚本不同。因此,只需要编写文件后缀为.lua
的脚本文件,并把文件名作为启动参数,启动snlua
即可。
-- 引入Skynet
local skynet = require "skynet"
当引入Skynet时,当前服务不能在Skynet框架之外使用,使用标准的Lua解析器运行包含了Skynet模块的代码时会立即报错,这是因为每个Skynet服务都依赖于一个skynet_context
上下文的C对象,上下文对象是 由snlua
导入到Lua虚拟机中的。
消息的组成
每个Skynet服务的核心职责是处理其它服务发送过来的消息,并向其它服务发送消息。每个Skynet消息都由5部分构成:
-
session
大部分消息工作在请求回应模式下,也就是说一个服务向另一个服务发起一个请求,而后收到请求的服务在处理完消息后会回复一条消息。session
是由发起请求的服务生成的唯一消息标识。响应方在回应时,会将此session
带回。这样发送方才能识别出哪条消息是针对哪一条回应。
session
作为消息的唯一标识,实际上是一个非负整数。当一条消息不需要回复时,按照惯例使用0这个特殊的session
号表示。另外,session
是由Skynet框架生成并管理,使用者通常并不需要关心太多。 -
source
每个服务都是由一个32位的整数标识的,这个整数可以看作服务在Skynet系统中的地址,也就是消息源。即便是在服务退出后,新启动的服务通常也不会使用已经使用过的地址。除非发生回绕,但一般间隔时间非常长。每条接收到的消息都回携带消息源source
,以方便在回应的时候可以指定地址。地址的管理通常是由框架来完成的,所以使用者也无须关心太多。
type
消息类别表示每个消息可以接收256种不同类型的消息,每种消息可以有不同的消息编码格式。其中有十来种是框架保留的,通常不建议用户使用。因为用户完全可以利用已有的消息类别,并使用具体的消息内容来区分每条具体消息的含义。框架将这些消息类别映射为字符串以便于记忆。最常用的消息类别为lua
,它会广泛的用于Lua编写的服务之间的通讯上。
message
message
是消息的C指针,在Lua层看来message
是一个lightuserdata
,不过框架会隐藏这个细节。最终,用户处理的是经过解码后的Lua对象。只有极少数情况下,才需要在Lua层直接操作message
这个C指针。
size
size
表示消息的长度,通常和message
一起结合使用。
另外有部分API只在搭建框架时用到,普通服务并不会使用,所以这些API被抽离出来放在skynet.manager
模块中。需要时先引入:
require "skynet.manager"
为了兼容老代码,skynet.manager
共享skynet
命名空间,require "skynet"
模块后额外的API依旧存放在skynet
空间下,而require "skynet.manager"
的返回值同样是skynet
命名空间。这些额外的API包括:
skynet.launch
启动一个C服务skynet.kill
强行杀死一个服务skynet.abort
退出Skynet进程skynet.register
给自身注册一个名字skynet.name
为一个服务命名skynet.forward_type
将本服务实现为消息转发器,对一类消息进行转发。skynet.filter
过滤消息再处理skynet.monitor
给当前Skynet进程设置一个全局的服务监控
服务地址
每个服务都有一个32位的数字地址,这个地址的高8位表明服务所属的节点。
skynet.self()
用于获取当前服务的数字地址skynet.harbor()
用于获取服务所属的节点skynet.address(address)
用于将一个数字地址转换为一个可用于阅读的字符串
同时为了地址使用方便,可以给数字地址起一个字符串的名字。
skynet.register(name)
为服务注册一个别名,别名必须不超过16个字符。skynet.name(name, address)
为地址命名,skynet.name(name, skynet.self())
和skynet.register(name)
的功能等价。
服务别名一旦注册,在Skynet系统中是通用的,需要自己约定名字的管理方法。
服务别名一般分为两种类型,使用.
开头的名字是在同一个Skynet节点下是有效的,跨节点的Skynet服务对其它节点下的.
开头的名字是不可见的。不同的Skynet节点可以定义相同的.
开头的名字。
另外以字母开头的名字在整个Skynet网络中都是有效的,可以通过这种全局命名的方式将消息发送到其它节点。原则上不鼓励滥用全局别名,因为它有一定的管理成本。管理的方法是在业务层交换服务的数字地址,让服务自行记住其它服务的地址来传播消息。
skynet.localname(name)
用来查询一个以.
开头的名字所对应的地址,它是一个非阻塞的API,不可以查询跨节点的全局别名。
作者:JunChow520
链接:https://www.jianshu.com/p/9015bb091151
来源:简书