UniqueService

云风 edited this page Aug 5, 2014 · 1 revision

我们可以通过 skynet.newservice 启动一个 lua 编写的服务。同一段脚本可以启动多份,每个有不同的地址。地址是区分不同服务的唯一标识。

但有时,整个系统中解决一类事务只需要一个服务,在系统启动时,它便启动好,而其它服务需要知道它的地址以便于使用它。这个时候,使用 skynet.uniqueservice 是更好的选择。

skynet.uniqueserviceskynet.newservice 的输入参数相同,都可以以一个脚本名称找到一段 lua 脚本并启动它,返回这个服务的地址。但和 newservice 不同,每个名字的脚本在同一个 skynet 节点只会启动一次。如果已有同名服务启动或启动中,后调用的人获得的是前一次启动的服务的地址。

它很大程度上取代了具名服务(不再推荐使用的早期特性)的功能。很多 skynet 库都附带有一个独立服务,你可以在库的初始化时,写上类似的语句:

local SERVICE
skynet.init(function()
  SERVICE = skynet.uniqueservice "foobar"
end)

这个范例会注册一个初始化函数去初始化 SERVICE 变量。而你的库函数就可以使用 SERVICE 这个地址来访问对应的唯一的 foobar 服务了。

uniqueservice 采用的是惰性初始化的策略。整个系统中第一次调用时,服务才会被启动起来。有时,你并不希望做惰性初始化,而在 skynet 启动脚本里明确把必须的服务初始化好(这个初始化过程可能比较漫长,惰性初始化会导致不必要的运行时延迟)。那么,如果你明确知道服务已经启动好,可以使用 skynet.queryservice 来查询已有服务。如果这个服务不存在,这个 api 会一直阻塞到它启动好为止。

默认情况下,uniqueservice 是不跨节点的。也就是说,不同节点上调用 uniqueservice 即使服务脚本名相同,服务也会独立启动起来。如果你需要整个网络有唯一的服务,那么可以在调用 uniqueservice 的参数前加一个 true ,表示这是一个全局服务。

对应的,查询服务 queryservice 也支持第一个参数为 true 的情况。这种全局服务,queryservice 更加有用。往往你需要明确知道一个全局服务部署在哪个节点上,以便于合理的架构。你可以在你设计的节点上的启动脚本中调用 skynet.uniqueservice(true, "foobar") 将服务启动后,然后再在其它使用它的地方调用 skynet.queryservice(true, "foobar")

DataCenter 不同,uniqueservice 是一个专用于服务管理的模块。它在服务地址管理上做了特别的优化。因为对于同一个名字,只允许启动一次,且不准更换。所以,在实现上,我们可以在每个节点缓存查询过的结果,而不必每次都去中心节点查询。

You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.