【skynet】服务调度实验

写在前面

skynet 是一个多线程框架,功能按服务划分,正确区分各个名词十分重要。

  • 线程:程序可以并行运行多少个执行序
  • 服务:模块运行时的实例,多个服务可以并发执行
  • 协程:调度最小单元,一个服务由多个协程组成

文章目录

  • 写在前面
  • 准备工作
  • 代码演示
    • 基本示例
      • 主服务
      • hello 服务
      • 运行结果
    • 示例变体一
      • 将 hello 服务改成死循环
      • 运行结果
    • 示例变体二
      • 启动两个 hello 服务,启动线程改为 2
      • 运行结果
  • 结论


准备工作

首先要有一个编译好,而且工作正常的 skynet 。最好已经对服务间通信有一定了解。

代码演示

基本示例

我们将启用两个服务,一个 hello 服务,每秒打印一次 Hello, World! 。另一个是 main 服务,每秒打印一次 This is main.

主服务

-- main.lua
local skynet = require "skynet"

skynet.init(function()
    -- 启动 hello
    skynet.newservice("hello")
end)

skynet.start(function()
    skynet.fork(function()
        while true do
            -- 每秒打印一次
            skynet.error("This is main.")
            skynet.sleep(100)
        end
    end)
end)

hello 服务

-- hello.lua
local skynet = require "skynet"

skynet.start(function()
    skynet.fork(function()
        while true do
            -- 每秒打印一次
            skynet.error("Hello, World!")
            skynet.sleep(100)
        end
    end)
end)

运行结果

[:00000002] LAUNCH snlua bootstrap
[:00000003] LAUNCH snlua launcher
[:00000004] LAUNCH snlua cdummy
[:00000005] LAUNCH harbor 0 4
[:00000006] LAUNCH snlua datacenterd
[:00000007] LAUNCH snlua service_mgr
[:00000008] LAUNCH snlua main
[:00000009] LAUNCH snlua hello
[:00000009] Hello, World!
[:00000008] This is main.
[:00000002] KILL self
[:00000009] Hello, World!
[:00000008] This is main.
[:00000009] Hello, World!
[:00000008] This is main.

结果为 main 服务和 hello 服务每秒打印一次。

示例变体一

将 hello 服务改成死循环

修改代码,验证服务间的独立性。

  • main 服务不变
  • hello 服务加入死循环代码
-- hello.lua
local skynet = require "skynet"

skynet.start(function()
    skynet.fork(function()
        while true do
            -- 每秒打印一次
            skynet.error("Hello, World!")
            skynet.sleep(100)
            -- 进入死循环
            while true do
            end
        end
    end)
end)

运行结果

[:00000002] LAUNCH snlua bootstrap
[:00000003] LAUNCH snlua launcher
[:00000004] LAUNCH snlua cdummy
[:00000005] LAUNCH harbor 0 4
[:00000006] LAUNCH snlua datacenterd
[:00000007] LAUNCH snlua service_mgr
[:00000008] LAUNCH snlua main
[:00000009] LAUNCH snlua hello
[:00000009] Hello, World!
[:00000008] This is main.
[:00000002] KILL self
[:00000008] This is main.
[:00000008] This is main.
[:00000008] This is main.
[:00000008] This is main.
[:00000008] This is main.
[:00000008] This is main.
[:00000008] This is main.
[:00000008] This is main.
[:00000008] This is main.
[:00000008] This is main.
[:00000000] A message from [ :00000000 ] to [ :00000009 ] maybe in an endless loop (version = 85)
[:00000008] This is main.
...

结果为

  • hello 服务只打印了一次
  • main 服务正常执行,每秒打印一次
  • monitor 还识别出来 hello 服务死循环了

示例变体二

启动两个 hello 服务,启动线程改为 2

  • hello 服务保持死循环不变
  • 修改 main 服务,启动两个 hello 服务
  • 修改配置,改成两个线程
-- main.lua
local skynet = require "skynet"

skynet.init(function()
    -- 启动 2 个 hello
    skynet.newservice("hello")
    skynet.newservice("hello")
end)

skynet.start(function()
    skynet.fork(function()
        while true do
            -- 每秒打印一次
            skynet.error("This is main.")
            skynet.sleep(100)
        end
    end)
end)

运行结果

[:00000002] LAUNCH snlua bootstrap
[:00000003] LAUNCH snlua launcher
[:00000004] LAUNCH snlua cdummy
[:00000005] LAUNCH harbor 0 4
[:00000006] LAUNCH snlua datacenterd
[:00000007] LAUNCH snlua service_mgr
[:00000008] LAUNCH snlua main_ping
[:00000009] LAUNCH snlua hello
[:00000009] Hello, World!
[:0000000a] LAUNCH snlua hello
[:0000000a] Hello, World!
[:00000008] This is main.
[:00000002] KILL self

结果为

  • hello 服务只打印了一次
  • main 服务只打印了一次
  • monitor 不能识别出来死循环

结论

  • 同一个模块的多个服务实例,可以占用多个线程,享有平等执行权。
  • 其他服务不能抢占当前服务,只能等当前服务让出执行权。

你可能感兴趣的:(skynet,skynet)