文章目录
目录
- skynet.call 详细解析
- 1. 函数签名与参数
- 2. 内部实现机制
- 3. 会话ID与协程调度
- 4. 超时与错误处理
- 5. 返回值处理
- 6. 协议类型的影响
- 7. skynet.call vs skynet.send
- 8. 示例代码分析
- 9. 最佳实践
- 10. 总结

函数签名:
skynet.call(addr, typename, ...)
addr:目标服务的地址(整数或字符串形式的服务名)。typename:消息协议类型(如"lua"、"text"),决定消息的编码方式。...:消息内容(具体参数,可以是任意Lua值)。
示例:
local result = skynet.call("db_service", "lua", "query", "SELECT * FROM users")
- 同步调用:
skynet.call 是同步操作,发送请求后阻塞当前协程,直到收到响应。
- 会话管理: 生成会话ID:调用时生成唯一的会话ID(
session),用于匹配请求与响应。
- 发送消息:将消息和会话ID发送到目标服务。
- 协程挂起:当前协程通过
skynet.wait 挂起,等待响应。
- 响应处理:目标服务处理完成后,通过会话ID返回结果,唤醒挂起的协程。
skynet.call 是同步操作,发送请求后阻塞当前协程,直到收到响应。session),用于匹配请求与响应。
- 发送消息:将消息和会话ID发送到目标服务。
- 协程挂起:当前协程通过
skynet.wait挂起,等待响应。 - 响应处理:目标服务处理完成后,通过会话ID返回结果,唤醒挂起的协程。
- 会话ID:每个
skynet.call 调用对应一个唯一会话ID,确保请求与响应一一匹配。
- 协程关联:会话ID与当前协程绑定,响应到达时通过会话ID找到对应协程并唤醒。
skynet.call 调用对应一个唯一会话ID,确保请求与响应一一匹配。
- 默认无超时:
skynet.call 默认无限等待响应,若目标服务未响应,协程将永久挂起。
- 手动超时:可通过
skynet.timeout 结合 skynet.response 实现超时逻辑:
local response = skynet.response()
skynet.timeout(500, function()
response(false, "Timeout")
end)
local result = skynet.call("service", "lua", "slow_task")
- 错误传递:若目标服务抛出错误,
skynet.call 会将错误信息通过 skynet.ret 返回。
skynet.call 默认无限等待响应,若目标服务未响应,协程将永久挂起。skynet.timeout 结合 skynet.response 实现超时逻辑:skynet.call 会将错误信息通过 skynet.ret 返回。
- 多返回值支持:目标服务可通过
skynet.ret(skynet.pack(a, b)) 返回多个值。
- 返回值解包:
skynet.call 自动解包返回值,直接返回多个结果:
local a, b = skynet.call("service", "lua", "get_values")
skynet.ret(skynet.pack(a, b)) 返回多个值。skynet.call 自动解包返回值,直接返回多个结果:
"lua" 协议:
- 编码方式:使用
skynet.pack 和 skynet.unpack 序列化数据。
- 适用场景:服务间结构化数据传递(推荐)。
"text" 协议:
- 编码方式:直接传递字符串,无需序列化。
- 适用场景:简单文本消息或调试。
- 自定义协议:需通过
skynet.register_protocol 注册编码/解码函数。
"lua" 协议:
- 编码方式:使用
skynet.pack和skynet.unpack序列化数据。 - 适用场景:服务间结构化数据传递(推荐)。
"text" 协议:
- 编码方式:直接传递字符串,无需序列化。
- 适用场景:简单文本消息或调试。
- 自定义协议:需通过
skynet.register_protocol注册编码/解码函数。
| 特性 | skynet.call |
skynet.send |
|---|---|---|
| 同步/异步 | 同步(阻塞等待响应) | 异步(立即返回) |
| 返回值 | 返回目标服务的响应 | 无返回值 |
| 会话ID | 自动生成并管理 | 无需会话ID |
| 典型场景 | 需要即时结果的请求(如数据库查询) | 通知型消息(如日志记录、事件触发) |
服务端处理请求:
-- 目标服务(db_service)
skynet.start(function()
skynet.dispatch("lua", function(session, source, cmd, ...)
if cmd == "query" then
local sql = ...
local data = execute_query(sql)
skynet.ret(skynet.pack(data)) -- 返回查询结果
end
end)
end)
客户端调用:
-- 调用方服务
local result = skynet.call("db_service", "lua", "query", "SELECT * FROM users")
print("Query result:", result)
- 协议选择:优先使用
"lua" 协议,支持复杂数据结构。
- 超时机制:关键操作添加超时逻辑,避免服务死锁。
- 错误处理:在目标服务中捕获异常并通过
skynet.ret 返回错误信息。
- 避免阻塞:长时间操作使用
skynet.fork 创建子协程,避免阻塞主消息循环。
"lua" 协议,支持复杂数据结构。skynet.ret 返回错误信息。skynet.fork 创建子协程,避免阻塞主消息循环。
skynet.call 是 Skynet 中实现服务间同步调用的核心 API,通过会话ID和协程调度机制实现高效的请求-响应模型。理解其内部机制和协议类型的选择,能够帮助开发者构建稳定、高效的服务间通信逻辑。
到此这篇关于skynet.call使用详解的文章就介绍到这了,更多相关skynet.call使用内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客!
您可能感兴趣的文章:
- skynet.rawcall使用应用场景分析
- skynet.dispatch 使用示例详解