传输总览
传输无关模型
Runa 的内核不绑定 HTTP。HTTP route、WebSocket、JSON-RPC 这类能力都作为传输块接入应用,通过 Provider、Host 和生命周期统一管理。
这意味着核心只负责把应用跑起来。你要 HTTP,就安装 route;要 WebSocket,就安装 ws;要 JSON-RPC,就安装 jsonrpc。不用的传输不会自动进入项目。
内核为什么不绑定 HTTP
内核只关心这些抽象:
- Provider 负责注册依赖、命令、Host 和生命周期回调
- Host 负责启动和停止长期运行的服务
- DI 负责把传输块和能力块串起来
- 生命周期负责按顺序 Init、Register、Resolve、Boot、Shutdown
因此一个应用可以只启动 HTTP,也可以只启动命令行或 worker。
现在有哪些传输块
| 传输 | 状态 | 安装路径 | 说明 |
|---|---|---|---|
| HTTP Route | 已实现 | github.com/duxweb/runa/route |
HTTP 路由、分组、域、强类型 handler |
| WebSocket | 已实现 | github.com/duxweb/runa/ws |
Hub、连接、频道、广播 |
| JSON-RPC | 已实现 | github.com/duxweb/runa/jsonrpc |
HTTP JSON-RPC 和可选 WebSocket |
| gRPC | 规划中 | 暂无 Go 包 | 未来按传输块规范接入 |
一个传输块通常怎么接入
一个传输块通常包含:
app.Install(transport.Provider(...))
Provider 内部完成:
- 注册核心对象到 DI
- 注册命令
- 注册 Host 或挂载到已有 route
- 在 Resolve 阶段处理延迟挂载
- 在 Shutdown 阶段释放连接和资源
HTTP route 的最小接入是:
app := runa.New()
app.Install(route.Provider(route.Addr(":8080")))
app.Freeze(context.Background())
route.Default().Get("/", func(ctx *route.Context) error {
return ctx.Text("ok")
})
app.Run(context.Background())
route.Provider(...) 会注册 HTTP Host,route.Default() 才能拿到默认路由注册表。只安装核心时不能写 HTTP handler。
传输块怎么使用能力
传输块负责接收请求,能力块负责业务能力。HTTP handler 中最常见的写法是使用能力包的 Default()。
route.Default().Get("/cache", func(ctx *route.Context) error {
pool := cache.Default().MustOf[string]("default")
value, _, err := pool.Get(ctx.Context(), "hello")
if err != nil {
return err
}
return ctx.Text(value)
})
ctx.Context() 是当前请求的标准库 context。数据库、缓存、队列、外部 HTTP 请求都应该优先传它,方便请求取消时及时停止下游操作。
怎么选择传输
- 普通 Web API:使用
route - 浏览器实时通信:使用
ws - 需要 JSON-RPC 2.0 协议:使用
jsonrpc - 需要 gRPC:当前还在规划中,不要在业务代码里假设已有
grpc包
大多数业务项目先从 route 开始。只有当你明确需要实时连接或 RPC 协议时,再增加 ws 或 jsonrpc。