---
title: "Solon Rpc 通讯通道和序列化组件"
---


一次 Nami 调用至少要解决两件事：**通过什么传输**，以及**如何把 Java 数据变成字节**。

```text
接口代理 → Channel → 请求字节/HTTP body → 服务端 Server
         ↘ Encoder/Decoder ↗       ↘ Serialization
```




### 1、通道组件


| 通道 | 客户端组件 | 对口的服务端支持组件 | 
| -------- | -------- |  -------- | 
| Http 通道     | nami-channel-http     |  solon-server-jdkhttp<br/>solon-server-smarthttp<br/>solon-server-jetty<br/>solon-server-undertow | 
| Socket.D 通道     | nami-channel-socketd + socket.d    |  solon-server-socketd + socket.d |


### 2、序列化方案组件

| 序列化方案 | 客户端组件 | 对口的服务端组件 | 
| -------- | -------- |  -------- | 
| Form 方案     | 表单模式     |   | 
| Json 方案     | nami-coder-snack3<br/>nami-coder-snack4<br/>nami-coder-fastjson<br/>nami-coder-fastjson2<br/>nami-coder-jackson    | solon-serialization-snack3<br/>solon-serialization-snack4<br/>solon-serialization-fastjson<br/>solon-serialization-fastjson2<br/>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` + <br/>`nami-coder-snack4` | HTTP server +  <br/>`solon-serialization-snack4` |
| HTTP + Jackson | `nami-channel-http` + <br/>`nami-coder-jackson` | HTTP server + <br/>`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

```java
@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 注入时，可以明确指定：

```java
UserService service = Nami.builder()
    .url("http://localhost:9001/rpc/v1/user")
    .encoder(Snack4Encoder.instance)
    .decoder(Snack4Decoder.instance)
    .channel(HttpChannel.instance)
    .create(UserService.class);
```

需要导入：

```java
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。

