ekfa/docs/efka_iot_protocol.md

256 lines
5.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# EFKA 与 IOT 交互协议
本文档描述 `efka``iot` 之间的 TLS 长连接协议。当前协议由 Erlang term 直接序列化,发送端使用 `term_to_binary/1`,接收端使用 `binary_to_term(PacketBin, [safe])`
## 传输层
- `efka` 作为 TLS client 连接 `iot`
- `iot` 作为 TLS server 接收多个 `efka` 连接,一个连接对应一个 `ssl_channel` 进程。
- socket 使用 `{packet, 4}`,每个 Erlang term binary 作为一个完整包发送。
- `Ref` 使用 `make_ref()` 生成,只在当前连接的 inflight 表内匹配。
## 顶层帧
协议顶层 tuple 用来表达交互语义:
```erlang
{request, Ref, Body}
{response, Ref, Reply}
{command, Ref, {Domain, Payload}}
{command_response, Ref, {Domain, Reply}}
{message, Body}
```
语义说明:
| 帧 | 方向 | 语义 |
| --- | --- | --- |
| `{request, Ref, Body}` | efka -> iot | efka 发起请求,需要 iot 回复 |
| `{response, Ref, Reply}` | iot -> efka | iot 对 efka request 的回复 |
| `{command, Ref, {Domain, Payload}}` | iot -> efka | iot 下发命令,需要 efka 回复 |
| `{command_response, Ref, {Domain, Reply}}` | efka -> iot | efka 对 iot command 的回复 |
| `{message, Body}` | 双向 | 异步消息,不要求回复 |
`command``command_response``Domain` 表示业务域,目前支持:
- `auth`
- `container`
## 鉴权请求
初始连接由 `efka` 发起鉴权 request
```erlang
{request, Ref, {auth_request, #{
uuid => UUID,
token => Token,
timestamp => Timestamp
}}}
```
`iot` 回复:
```erlang
{response, Ref, {auth_response, ok}}
{response, Ref, {auth_response, {error, {denied, Reason}}}}
{response, Ref, {auth_response, {error, {failed, Reason}}}}
```
处理语义:
- `ok``efka` 进入 `activated` 状态。
- `{error, {denied, Reason}}``efka` 进入 `restricted` 状态,不能正常上报数据,但仍可接收部分命令。
- `{error, {failed, Reason}}`:鉴权失败,连接关闭后重连。
## 授权控制命令
`iot``efka` 的授权控制使用 command 语义:
```erlang
{command, Ref, {auth, activate}}
{command, Ref, {auth, deactivate}}
```
`efka` 回复:
```erlang
{command_response, Ref, {auth, ok}}
{command_response, Ref, {auth, {error, Reason}}}
```
处理语义:
- `activate`:如果 `efka` 已经是 `activated`,直接回复 `ok`;否则重新发送 `auth_request`,等待鉴权结果后再回复该 command。
- `deactivate``efka` 进入 `restricted` 状态,并回复 `ok`
## 容器管理命令
`iot``efka` 的容器管理使用 command 语义:
```erlang
{command, Ref, {container, CommandMap}}
```
`efka` 回复:
```erlang
{command_response, Ref, {container, Reply}}
```
`Reply` 取值:
```erlang
ok
{ok, Result}
{error, Reason}
```
### list
```erlang
#{action => list}
```
返回当前 `efka` 主机上的容器列表。
### deploy
```erlang
#{
action => deploy,
task_id => TaskId,
params => Params
}
```
触发容器部署。部署过程中的流式日志不通过该 command response 返回,而是通过 `message``task_event` 上报。
### start
```erlang
#{
action => start,
target => Target
}
```
### stop
```erlang
#{
action => stop,
target => Target,
timeout_seconds => TimeoutSeconds
}
```
### kill
```erlang
#{
action => kill,
target => Target,
signal => Signal
}
```
### remove
```erlang
#{
action => remove,
target => Target,
force => Force,
remove_volumes => RemoveVolumes
}
```
### config
```erlang
#{
action => config,
target => Target,
config => Config
}
```
更新容器配置文件。
### Target
容器目标使用 map 表示:
```erlang
#{
name => ContainerName,
id => ContainerId
}
```
`name``id` 至少一个非空;优先使用 `name``name` 为空时使用 `id`
## 异步消息
`message` 不带 `Ref`,不要求对端回复。
### efka -> iot: data
```erlang
{message, {data, #{
route_key => RouteKey,
metric => Metric
}}}
```
用于 `efka` 上报业务指标数据。
### efka -> iot: task_event
```erlang
{message, {task_event, #{
task_id => TaskId,
type => Type,
stream => Stream
}}}
```
任务事件流关闭时:
```erlang
{message, {task_event, #{
task_id => TaskId,
type => <<"close">>,
stream => Reason
}}}
```
### iot -> efka: pub
```erlang
{message, {pub, #{
topic => Topic,
qos => Qos,
content => Content
}}}
```
用于 `iot``efka` 本地订阅系统发布 topic 消息。
## 状态与超时
- `efka` 鉴权超时时间5 秒。
- `iot` command inflight 超时时间60 秒。
- `iot` 管理多个 `efka` 时,每个连接有独立 `ssl_channel` 和独立 inflight 表。
- command 超时后,`iot` 删除 inflight 记录;之后如果迟到的 `command_response` 到达,会被视为未预期响应。
## 兼容性
当前协议不兼容旧 tuple
- 旧容器管理:`{request, Ref, {container_request, ...}}`
- 旧容器回复:`{response, Ref, {container_response, ...}}`
- 旧授权控制:`{message, {auth_control, Command}}`
如果需要滚动升级,应先增加临时兼容分支或引入协议版本协商。