浅谈 Socket.D 与响应式编程
一、Socket.D 的主要特性
首先,Scoket.D 是高效一个二进制的网络通讯协议(官方的讲法是:基于事件和语义消息流的网络应用协议),能够满足很多场景下使用。其次,Scoket.D 是温和的响应式(采用回调风格)。
1、三种通讯模式
- send 只是发送(发送后不管了)
发送一个请求,无需为这个请求发送答复报文。适用于监控埋点,日志上报等,这种场景下无需回执,丢失几个请求无伤大雅。
- sendAndRequest(发送并请求,要求一个“答复”)
发送一条请求消息,响应方收到后发回一个答复消息。传统的 HTTP 就是典型的 sendAndRequest。
- sendAndSubscribe(发送并订阅,可接收N个“答复”)
发送一个订阅消息,响应方收到后发回N个答复报文。传统的 MQ 是典型的 sendAndSubscribe。
2、双向监听双向会话
Server 可以监听 Client 发来的消息;Client 也可以监听 Server 发来的消息。形成的 Session,更是可以相互对发消息。
3、其它
- 二进制协议,紧凑高效
- 有语议、有事件
- 多路复用
- 灵活的传输层切换: TCP/UDP/WebSocket等
- 支持自动分等高级特性
4、与其它协议对比
感观上像是各协议的优点提纯。简单且强大,非常有未来感!
对比项目 | socket.d | http | websocket | rsocket | socket.io |
---|---|---|---|---|---|
发消息(Qos0) | 有 | 无 | 有 | 有 | 有 |
发送并请求(Qos1) | 有 | 有 | 无 | 有 | 无 |
发送并订阅 | 有 | 无 | 无 | 有 | 无 |
答复或响应 | 有 | 有 | 无 | 有 | 无 |
单连接双向通讯 | 有 | 无 | 有(不便) | 有 | 有(不便) |
数据分片 | 有 | / | 无 | 有 | 有 |
断线自动重连 | 有 | / | 无 | 有 | 有 |
有元信息 | 有 | 有 | 无 | 有 | 无 |
有事件(或路径) | 有 | 有 | 无 | 无 | 有 |
有流(或消息关联性) | 有 | 无 | 无 | 有 | 无 |
Broker 模式集群 | 有 | 无 | 无 | 有 | 无 |
异步 | 异步 | 同步 | 异步 | 异步 | 异步 |
接口体验 | 经典 | 经典 | 经典 | 响应式(复杂) | 经典 |
基础传输协议 | tcp, udp, ws | tcp | http | tcp, udp, ws | ws |
二、Socket.D 的内部实现
1、帧的设计
socket.d 是以帧为单位进行传输。大的帧还会自动分片成小帧进行传输(超过 16MB 自动分裂重组,大小可配置),到达接收端后再自动聚合。
- 帧的逻辑结构
frame: {flag, message: {sid, event, entity: { metaString, data}}}
帧的数据逻辑结构:帧里有标志和消息;消息里有流标识、事件、实体;实体里有元信息字符串和数据。
- 完整的标准帧码
[len:int][flag:int][sid:str(<64)][\n][event:str(<512)][\n][metaString:str(<4k)][\n][data:byte(<16m)]
字段 | 类型 | 大小 | 说明 |
---|---|---|---|
len | int | 4字节 | 帧长度(包括它自己的 4字节占位) |
flag | int | 4字节 | 标志(相当于协议指令) |
sid | String | 64字节以内 | 流标识。格式为: guid |
event | String | 512字节以内 | 事件。格式为:可见字符 string |
metaString | String | 4Kb以内 | 元信息字符串。格式为:通用的 uri queryString |
data | byte[] | 16Mb以内 | 数据。格式为: byte[] |
注意:当使用 udp 传输时,帧长度不能超过 2k (听说,实际不能超过 1.4k )
- 简化的辅助帧码(Ping, Pong, Close),取消了 message 部分
[len:int][flag:int]
2、数据实体——Entity
基于帧之上,一般开发者接触到的是 Entity, 它类似一个HTTP报文,可以是一个Request,也可以是一个Response。由两个部分组成:
- MetaString 元信息字符串,类似 HTTP 的 header。格式:字符串
- Data 数据,类似 HTTP 的 body。格式:二进制
3、玩法
Socket.D 有很多玩法,传统的 RPC 自然不在话下,用来做 IM 也未尝不可,开发 MQ 也很简单(FolkMQ 就是用它开发的)。某些特性也可以用来做代理或者网络穿透。
IoT的场景,比如小明的家里有个智能空调,小明想在外面通过手机 APP 来控制空调开关,如何优雅地描述这个控制问题?最精炼的解决方案就是"小明调用空调上开关的API"。
另外最经典的玩法就是Broker了,Broker类似一种“软路由”的方案,可以让服务的发布访问变得简单。发布服务只要连接到Broker,调用方通过反向请求的方式来让Broker透明转发即可,摒弃了传统的注册中心,端口管理等常见的服务治理手段。
4、关于 Socket.D Broker
Broker 有很多优势,发布服务不需要监听端口,无需 Sidecar,服务注册变得简单,无需 zk、etcd 之类,LoadBalance 变得简单,也更安全,没监听端口后很难攻击。也有很多劣势,网络上多了一跳,性能是有一定损耗的,Broker 是中心化设计,类似我们平时全局的 Nginx 一样,但是 Broker 的优雅启停显然更加复杂,受限于整个 Broker 集群的瓶颈等等。上帝为你关闭了一扇门,就一定会为你打开一扇窗。
三、响应式编程,难吗?
响应式编程是个老话题了,它早已无处不在,甚至你在Excel里SUM求和,本质上也是种响应式的思维。响应式本质上就是响应变化的数据流。Socket.D 这个协议本身就是以响应式之名,将其扩展到网络层面。
但是,响应式接口对一般程序员,不太友好。Socket.D 是响应式,但采用"经典的回调界面"。
四、总结
Socket.D 是个很有趣的网络协议,未来应该会普及流行。它解决问题的思路和设计很令人耳目一新。如果大家有兴趣,可以去它的官网了解下。