Solon Rpc 通讯通道和序列化组件
2026年9月11日 下午5:37:43
一次 Nami 调用至少要解决两件事:通过什么传输,以及如何把 Java 数据变成字节。
接口代理 → Channel → 请求字节/HTTP body → 服务端 Server
↘ Encoder/Decoder ↗ ↘ Serialization
1、通道组件
| 通道 | 客户端组件 | 对口的服务端支持组件 |
|---|---|---|
| Http 通道 | nami-channel-http | solon-server-jdkhttp solon-server-smarthttp solon-server-jetty solon-server-undertow |
| Socket.D 通道 | nami-channel-socketd + socket.d | solon-server-socketd + socket.d |
2、序列化方案组件
| 序列化方案 | 客户端组件 | 对口的服务端组件 |
|---|---|---|
| Form 方案 | 表单模式 | |
| Json 方案 | nami-coder-snack3 nami-coder-snack4 nami-coder-fastjson nami-coder-fastjson2 nami-coder-jackson | solon-serialization-snack3 solon-serialization-snack4 solon-serialization-fastjson solon-serialization-fastjson2 solon-serialization-jackson |
| Hessian 方案 | nami-coder-hessian | solon-serialization-hessian |
| Fury 方案 | nami-coder-fury | solon-serialization-fury |
| Kryo 方案 | nami-coder-kryo | solon-serialization-kryo |
| Protostuff 方案 | nami-coder-protostuff | solon-serialization-protostuff |
| Abc 方案 | nami-coder-abc | solon-serialization-abc |
选择序列化方案时,尽量客户端与服务端的框架一一对应。
3、 常见的配对组合
| 类型 | 客户端 | 服务端 |
|---|---|---|
| HTTP + JSON | nami-channel-http + nami-coder-snack4 | HTTP server + solon-serialization-snack4 |
| HTTP + Jackson | nami-channel-http + nami-coder-jackson | HTTP server + solon-serialization-jackson |
| Socket.D | nami-channel-socketd | solon-server-socketd |
| Hessian | nami-coder-hessian | solon-serialization-hessian |
| Fury/Kryo/Protostuff | 对应 nami-coder-* | 对应 solon-serialization-* |
客户端和服务端应选择同一种 wire format。只更换客户端 coder,通常会得到解码失败,而不是“自动兼容”。
4、 为什么示例要写 JSON Header
@NamiClient(
url = "http://localhost:9001/rpc/v1/user",
headers = ContentTypes.JSON)
UserService userService;
ContentTypes.JSON 会声明请求和接收内容类型。Nami 初始化配置时会根据 Accept 选择 decoder;HTTP channel 发送带 body 的请求时会根据 Content-Type 选择 encoder。显式声明后更容易确认实际协议。
5、 Builder 中显式指定组件
脱离 Solon 注入时,可以明确指定:
UserService service = Nami.builder()
.url("http://localhost:9001/rpc/v1/user")
.encoder(Snack4Encoder.instance)
.decoder(Snack4Decoder.instance)
.channel(HttpChannel.instance)
.create(UserService.class);
需要导入:
import org.noear.nami.channel.http.HttpChannel;
import org.noear.nami.coder.snack4.Snack4Decoder;
import org.noear.nami.coder.snack4.Snack4Encoder;
实际项目也可以只配置 URL 和注解头,让插件自动按 scheme/content type 查找组件。显式配置适合独立 Java 程序、排查“组件是否注册”问题。
6、 HTTP 参数是怎样发送的
根据当前 HttpChannel 源码:
- GET 请求的普通参数会拼到 query string。
- 有
@NamiBody的参数会作为 body,其他参数仍可进入 query。 Content-Type为表单类型时走表单提交。- 没有 body、没有可用 encoder 时,非 GET 请求会走表单参数。
- 有 body 或 encoder 时,使用 encoder 生成 body。
因此,实体请求建议明确写 @NamiBody/@Body,不要依赖参数猜测。
7、 如何选择
- 浏览器、网关、跨语言:HTTP + JSON。
- 强调长连接或 Socket.D 能力:单独学习 Socket.D,不要把 HTTP 配置照搬过去。
- 内部高性能二进制协议:评估 Hessian、Fury、Kryo、Protostuff,并建立兼容性测试。
遇到 There is no channel available,先查 URL scheme 和 nami-channel-*;遇到 There is no matching decoder 或解码异常,再查 coder、Content-Type 和服务端 serialization。