skynet框架應用 (五) 服務別名
5 服務別名
每個服務啟動之後,都有一個整形數來表示id,也可以使用字串id來表示,例如::01000010,其實就是把id:0x01000010轉換成字串。
但是這個數字的表示方式會根據服務的啟動先後順序而變化,不是一個固定的值。如果想要方便的獲取某個服務,那麼可以通過給服務設定別名來。
5.1 本地別名與全域性別名
在skynet中,服務別名可以分為兩種:
一種是本地別名,本地別名只能在當前skynet節點使用,本地別名必須使用. 開頭,例如:.testalias
一種是全域性別名,全域性別名可以在所有skynet中使用,全域性別名不能以. 開頭, 例如:testalias
5.2 別名註冊與查詢介面
------------------------------[[取別名]]--------------------------
local skynet = require "skynet"
require "skynet.manager"
--給當前服務定一個別名,可以是全域性別名,也可以是本地別名
skynet.register(aliasname)
--給指定servicehandler的服務定一個別名,可以是全域性別名,也可以是本地別名
skynet.name(aliasname, servicehandler)
-------------------------------------------------------------------
----------------------[[查詢別名]]------------------------------
--查詢本地別名為aliasname的服務,返回servicehandler,不存在就返回nil
skynet.localname(aliasname)
--[[
查詢別名為aliasname的服務,可以是全域性別名也可以是本地別名,
1、當查詢本地別名時,返回servicehandler,不存在就返回nil
2、當查詢全域性別名時,返回servicehandler,不存在就阻塞等待到該服務初始化完成
]]--
local skynet = require "skynet.harbor"
harbor.queryname(aliasname)
-------------------------------------------------------------------
注意:本地別名與全域性別名可以同時存在。
5.3 給服務註冊別名
5.3.1給普通服取別名
示例程式碼:testalias.lua
local skynet = require "skynet"
require "skynet.manager"
local harbor = require "skynet.harbor"
skynet.start(function()
local handle = skynet.newservice("test")
skynet.name(".testalias", handle) --給服務起一個本地別名
skynet.name("testalias", handle) --給服務起一個全域性別名
handle = skynet.localname(".testalias")
skynet.error("localname .testalias handle", skynet.address(handle))
handle = skynet.localname("testalias") --只能查本地,不能查全域性別名
skynet.error("localname testalias handle", skynet.address(handle))
handle = harbor.queryname(".testalias")
skynet.error("queryname .testalias handle", skynet.address(handle))
handle = harbor.queryname("testalias")
skynet.error("queryname testalias handle", skynet.address(handle))
end)
上面服務通過skynet.newservice來啟動一個test.lua服務,test.lua程式碼如下:
local skynet = require "skynet"
skynet.start(function()
skynet.error("My new service")
end)
執行結果:
$ ./skynet examples/config
testalias #執行main.lua後在終端輸入
[:0100000a] LAUNCH snlua testalias
[:0100000b] LAUNCH snlua test
[:0100000b] My new service
[:0100000a] localname .testalias handle :0100000b #skynet.localname查到本地名
[:0100000a] localname testalias handle nil #skynet.localname查不到全域性名
[:0100000a] queryname .testalias handle :0100000b #harbor.queryname查到本地名
[:0100000a] queryname testalias handle :0100000b #harbor.queryname查到全域性名
5.3.2 全域性別名查詢阻塞
如果全域性別名不存在,那麼這個時候呼叫函式harbor.queryname,將會阻塞,直到全域性別名的服務建立成功。
示例程式碼:testalias.lua
local skynet = require "skynet"
require "skynet.manager"
local harbor = require "skynet.harbor"
skynet.start(function()
handle = skynet.localname(".testalias") --查詢本地別名不阻塞
skynet.error("localname .testalias handle", skynet.address(handle))
handle = skynet.localname("testalias") --無法查詢全域性別名
skynet.error("localname testalias handle", skynet.address(handle))
handle = harbor.queryname(".testalias") --查詢本地別名不阻塞
skynet.error("queryname .testalias handle", skynet.address(handle))
handle = harbor.queryname("testalias") --查詢全域性別名阻塞
skynet.error("queryname testalias handle", skynet.address(handle))
end)
執行結果:
$ ./skynet examples/config
testalias
[:0100000a] LAUNCH snlua testalias
[:0100000a] localname .testalias handle nil #skynet.localname查到本地名
[:0100000a] localname testalias handle nil #skynet.localname查不到全域性名
[:0100000a] queryname .testalias handle nil #harbor.queryname查到本地名
#harbor.queryname查不到全域性名, 函式阻塞
5.3.3 多節點中的全域性別名
啟動兩個skynet節點,在節點1取別名,節點2查詢別名:
節點1,testaliasname.lua
local skynet = require "skynet"
require "skynet.manager"
local harbor = require "skynet.harbor"
skynet.start(function()
local handle = skynet.newservice("test")
skynet.name(".testalias", handle) --給服務起一個本地別名
skynet.name("testalias", handle) --給服務起一個全域性別名
end)
節點2, testaliasquery.lua
local skynet = require "skynet"
require "skynet.manager"
local harbor = require "skynet.harbor"
skynet.start(function()
handle = skynet.localname(".testalias")
skynet.error("localname .testalias handle", skynet.address(handle))
handle = skynet.localname("testalias")
skynet.error("localname testalias handle", skynet.address(handle))
handle = harbor.queryname(".testalias")
skynet.error("queryname .testalias handle", skynet.address(handle))
handle = harbor.queryname("testalias")
skynet.error("queryname testalias handle", skynet.address(handle))
end)
先啟動節點1執行testaliasname.lua,再啟動節點2執行
testaliasquery
[:0200000a] LAUNCH snlua testaliasquery
[:0200000a] localname .testalias handle nil
[:0200000a] localname testalias handle nil
[:0200000a] queryname .testalias handle nil
[:0200000a] queryname testalias handle :0100000b --查詢到節點1建立的服務
5.3.4 殺死帶別名的服務
給一個服務取了別名後,殺死它,本地別名將會登出掉,但是全域性別名依然存在,通過全域性別名查詢到的handle已經沒有意義。如果通過handle進行一些操作將得到不可預知的問題。
local skynet = require "skynet"
require "skynet.manager"
local harbor = require "skynet.harbor"
skynet.start(function()
local handle = skynet.newservice("test")
skynet.name(".testalias", handle) --給服務起一個本地別名
skynet.name("testalias", handle) --給服務起一個全域性別名
handle = skynet.localname(".testalias")
skynet.error("localname .testalias handle", skynet.address(handle))
handle = skynet.localname("testalias")
skynet.error("localname testalias handle", skynet.address(handle))
handle = harbor.queryname(".testalias")
skynet.error("queryname .testalias handle", skynet.address(handle))
handle = harbor.queryname("testalias")
skynet.error("queryname testalias handle", skynet.address(handle))
skynet.kill(handle) --殺死帶別名服務
handle = skynet.localname(".testalias")
skynet.error("localname .testalias handle", skynet.address(handle))
handle = skynet.localname("testalias")
skynet.error("localname testalias handle", skynet.address(handle))
handle = harbor.queryname(".testalias")
skynet.error("queryname .testalias handle", skynet.address(handle))
handle = harbor.queryname("testalias")
skynet.error("queryname testalias handle", skynet.address(handle))
end)
執行結果:
testalias
[:0100000a] LAUNCH snlua testalias
[:0100000b] LAUNCH snlua test
[:0100000b] My new service
[:0100000a] localname .testalias handle :0100000b
[:0100000a] localname testalias handle nil
[:0100000a] queryname .testalias handle :0100000b
[:0100000a] queryname testalias handle :0100000b
[:0100000a] KILL :100000b
[:0100000a] localname .testalias handle nil
[:0100000a] localname testalias handle nil
[:0100000a] queryname .testalias handle nil
[:0100000a] queryname testalias handle :0100000b #全域性別名還存在,但是已經殺死該服務了。
skynet的全域性別名服務是在cslave裡面實現的,現在不允許二次修改全域性別名繫結關係,所以全域性別名一般用來給一個永遠不會退出的服務來啟用。
但是有些情況下,我們確實需要二次修改全域性別名繫結關係,那麼這個時候,我們可以嘗試去修改一下cslave.lua檔案,修改內容如下:
function harbor.REGISTER(fd, name, handle)
--assert(globalname[name] == nil) --將這一行註釋掉
globalname[name] = handle
response_name(name)
socket.write(fd, pack_package("R", name, handle))
skynet.redirect(harbor_service, handle, "harbor", 0, "N " .. name)
end
執行一個二次修改全域性別名繫結關係的服務,例如:
local skynet = require "skynet"
require "skynet.manager"
local harbor = require "skynet.harbor"
skynet.start(function()
local handle = skynet.newservice("test")
skynet.name("testalias", handle) --給服務起一個全域性別名
handle = harbor.queryname("testalias")
skynet.error("queryname testalias handle", skynet.address(handle))
skynet.kill(handle) --殺死帶全域性別名服務
handle = skynet.newservice("test")
skynet.name("testalias", handle) --全域性別名給其他服務使用
handle = harbor.queryname("testalias")
skynet.error("queryname testalias handle", skynet.address(handle))
end)
執行結果:
testalias
[:0100000a] LAUNCH snlua testalias
[:0100000b] LAUNCH snlua test
[:0100000b] My new service
[:0100000a] queryname testalias handle :0100000b
[:0100000a] KILL :100000b
[:0100000c] LAUNCH snlua test
[:0100000c] My new service
[:0100000a] queryname testalias handle :0100000c #服務別名二次修改成功
5.4 全域性別名與全域性唯一服名區別
全域性唯一服名與這裡的全域性別名是兩個概念的名詞。
全域性唯一服名稱: 是用來標識服務是唯一的,服務名稱一般就是指令碼名稱,無法更改。
全域性別名: 是用來給服務起別名的,既可以給普通服起別名,也可以給全域性唯一服起別名。
他們兩種名字是在不同的體系中的,有各種的起名字的方式,以及查詢的方式。
所以不要嘗試用skynet.queryservice查詢一個全域性別名,也不要嘗試使用harbor.queryname去查詢一個全域性唯一服。
例如:
local handle = skynet.uniqueservice("test") --啟動一個全域性唯一服,名字為test
handle = harbor.queryname("test") --查不到的,會一直阻塞
或者:
local handle = skynet.uniqueservice("test") --啟動一個全域性唯一服,名字為test
skynet.name("testalias", handle) --再起一個全域性別名
handle = skynet.queryservice("testalias") --查不到的,也會一直阻塞
---------------------
作者:嚇人的猿
來源:CSDN
原文:https://blog.csdn.net/qq769651718/article/details/79432868
版權宣告:本文為博主原創文章,轉載請附上博文連結!