skynet 控制檯管理使用技巧

skynet 自帶了一個控制檯服務,可以很方便獲取和調試 skynet 運行數據,而且可以熱更新代碼,所以,弄明白skynet控制檯管理可以讓你更好地使用skynet,甚至改進這個控制檯服務,以滿足不同業務需求。

個服務默認不會啓動,需要你手動啓動它,如下:
skynet.newservice("debug_console", 8000)

設計原因,調試控制檯只監聽本地地址 127.0.0.1 ,如果需要遠程使用,需要先登錄到本機,然後再連接。

使用時,通過 telnet 或 nc 登錄調試控制檯,啓動後顯示:
$ nc 127.0.0.1 8000
Welcome to skynet console
表示連接成功。

注:skynet控制檯不能使用上下鍵回溯歷史命令,退格鍵也不能使用(改用刪除鍵)等,這是由於 skynet 使用了自己的 IO 庫,很難接入 libreadline (不能在 readline 的 hook 中 yield)。如果希望在控制檯中使用 readline 的 history 等特性,可以自己使用 rlwrap 。

這時,你可以輸入調試指令,輸入 help 可以列出目前支持的所有指令。(不同版本結果不同)
$ nc 127.0.0.1 8000
Welcome to skynet console
help
clearcache      clear lua code cache
cmem    Show C memory info
debug   debug address : debug a lua service
exit    exit address : kill a lua service
gc      gc : force every lua service do garbage collect
help    This help message
info    Info address : get service infomation
inject  inject address luascript.lua
kill    kill address : kill service
list    List all the service
logoff  logoff address
logon   logon address
mem     mem : show memory status
service List unique service
signal  signal address sig
snax    lanuch a new snax service
start   lanuch a new lua service
stat    Dump all stats
task    task address : show service task detail
命令的一般格式是 命令 地址 ,有些命令不帶地址,會針對所有的服務。當輸入地址時,可以使用 :01000001 這樣的格式指代一個服務地址:由冒號開頭的 8 位 16 進制數字,也可以省略前面兩個數字的 harbor id 以及接下來的連續 0 ,比如 :01000001 可以簡寫爲 1 。所有活動的服務可以輸入 list 列出。

常用的通用指令:
list 列出所有服務,以及服務的啓動參數。
gc 對所有 lua 服務執行gc,並列出gc後所有服務的內存情況。
mem 列出所有 lua 服務的內存佔用情況。(注:只獲取 lua 服務的 lua vm 內存佔用情況,如果需要 C 模塊中內存使用情況,使用cmem。)
stat 列出所有 lua 服務的消息隊列長度,以及被掛起的請求(協程)數量。
service 列出所有的唯一 lua 服務。
注意,由於這些指令是逐個向每個服務發送消息並等待迴應,所以當某個 lua 服務過載時,可能需要等待很長時間纔有返回。

針對單個 lua 服務的指令:
exit address 退出指定 lua 服務
kill address 強制中止指定 lua 服務。
info address 讓指定 lua 服務輸出自己的內部信息(數據通過回調服務內 skynet.info_func 生成)
signal address sig 向服務發送一個信號,sig 默認爲 0 。當一個服務陷入死循環時,默認信號會打斷正在執行的 lua 字節碼,並拋出 error 顯示調用棧。這是針對 endless loop 的 log 的有效調試方法。(注:這裏的信號並非系統信號。)
task address 顯示一個服務中所有被掛起的請求的調用棧。
debug address 針對一個 lua 服務啓動內置的單步調試器。http://blog.codingnow.com/2015/02/skynet_debugger.html
logon/logoff address 記錄一個服務所有的輸入消息(source, type, session, data, size)到文件。(生成文件的路徑地址取配置 logpath) 。
inject address script 將 script 對應的腳本插入到指定服務中運行(通常可用於熱更新補丁)。


這裏重點說下 info address 和 inject address script,這兩個命令很重要。

獲取服務內部數據 - info address 

前面提到,這個命令讓指定 lua 服務輸出自己的內部信息,數據通過回調服務內 skynet.info_func 生成。
下面以 example/simpledb.lua做說明,這是個典型的skynet服務。
[plain] view plain copy
  1. local skynet = require "skynet"  
  2. require "skynet.manager"    -- import skynet.register  
  3. local db = {}  
  4.   
  5. local command = {}  
  6.   
  7. function command.GET(key)  
  8.   return db[key]  
  9. end  
  10.   
  11. function command.SET(key, value)  
  12.   local last = db[key]  
  13.   db[key] = value  
  14.   return last  
  15. end  
  16.   
  17. -- 新增的代碼 -- start  
  18. skynet.info_func(function() return "hello mycwq!" end)  
  19. -- 新增的代碼 -- end  
  20.   
  21.   
  22. skynet.start(function()  
  23.   skynet.dispatch("lua", function(session, address, cmd, ...)  
  24.     local f = command[string.upper(cmd)]  
  25.     if f then  
  26.       skynet.ret(skynet.pack(f(...)))  
  27.     else  
  28.       error(string.format("Unknown command %s", tostring(cmd)))  
  29.     end  
  30.   end)  
  31.   skynet.register "SIMPLEDB"  
  32. end)  
啓動example例子,連接控制檯,
$ nc 127.0.0.1 8000
Welcome to skynet console
list
:00000004       snlua cmaster
:00000005       snlua cslave
:00000007       snlua datacenterd
:00000008       snlua service_mgr
:0000000a       snlua protoloader
:0000000b       snlua console
:0000000c       snlua debug_console 8000
:0000000d       snlua simpledb
:0000000e       snlua watchdog
:0000000f       snlua gate
OK
info :0000000d
hello mycwq!

代碼熱更新 - inject address script

前面提到,這個命令將 script 對應的腳本插入到指定服務中運行
下面寫個簡單的inject例子,保存爲 example/inject_simpledb.lua
[plain] view plain copy
  1. if not _P then  
  2.   print "inject error!!"  
  3.   return  
  4. end  
  5. local command = _P.lua.command  
  6. command.TEST = function() return "TEST" end  
  7.   
  8. print "inject ok!"  
啓動example例子,連接控制檯,
$ nc 127.0.0.1 8000
Welcome to skynet console
list
:00000004       snlua cmaster
:00000005       snlua cslave
:00000007       snlua datacenterd
:00000008       snlua service_mgr
:0000000a       snlua protoloader
:0000000b       snlua console
:0000000c       snlua debug_console 8000
:0000000d       snlua simpledb
:0000000e       snlua watchdog
:0000000f       snlua gate
OK
inject :0000000d example/inject_simpledb.lua
inject ok!

使用 rlwrap 強化 skynet 控制檯

前面提到了skynet控制檯不能使用上下鍵回溯歷史命令,退格鍵也不能使用等,爲了彌補這個不足,可以使用 rlwrap
這裏以 centos做說明, rlwrap依賴 readline,系統必須裝有 readline ,在現有很多linux系統,readline都可自動化安裝:
[plain] view plain copy
  1. yum -y install readline-devel  
rlwrap則需要手動安裝,這裏附 rlwrap下載地址,點這裏安裝 rlwrap很簡單,如下:
[plain] view plain copy
  1. tar -zxf rlwrap-0.37.tar.gz   
  2. cd rlwrap-0.37  
  3. ./configure  
  4. make && make install  
以後,skynet控制檯的連接方式改成這樣,就可以回溯命令了。
$ rlwrap nc 127.0.0.1 8000
Welcome to skynet console
list
:01000004       snlua cmaster
:01000005       snlua cslave
:01000007       snlua datacenterd
:01000008       snlua service_mgr
:0100000a       snlua protoloader
:0100000b       snlua console
:0100000c       snlua debug_console 8000
:0100000d       snlua simpledb
:0100000e       snlua watchdog
:0100000f       snlua gate
OK
最後,這裏列舉 rlwrap常用的快捷鍵:
Ctrl+L 清屏,實際是將當前行置頂
Ctrl+P 上一條命令
Ctrl+N 下一條命令
Ctrl+U 從光標處刪除到行首
Ctrl+W 向前刪除一個單詞
Ctrl+B 光標向前移動一個位置
Ctrl+T 光標處字符與前一個字符交換位置
Ctrl+Z 後臺運行,使用fg調出
Ctrl+H 相當於刪除鍵
Ctrl+J 相當於回車鍵
Ctrl+O 相當於回車鍵
Ctrl+M 相當於回車鍵

參考:
[1] DebugConsole   雲風
[2] skynet 控制檯管理使用技巧 沒有開花的樹
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章