Skip to content

Customized Encoding

linux_china edited this page Mar 9, 2021 · 8 revisions

目前RSocket Broker在Java的Responder端提供以下序列化格式,并且服务提供端能够针对请求端的要求自行进行数据序列化适配。

  • Hessian: Java应用默认的数据序列化格式
  • JSON: JSON,如果你从Node或者浏览器端接入,建议使用JSON。
  • Google Protobuf: Google Protobuf,如果你非常关注性能,而且不在意idl编写方式,可以考虑Protobuf
  • Cbor: CBOR格式 https://cbor.io/
  • Avro: Kafka主要采用Avro,可以考虑这种方式
  • Java Object: Java原生Object序列化方式
  • String: 基于UTF-8的字符串序列化
  • CloudEvents: 支持CloudEvent单参数序列化

考虑到真实的场景中还有不少其他数据格式序列化的需求,也就是Customized Encoding,所以Alibaba RSocket Broker提供了自定义数据序列化。 步骤如下:

  • 创建一个Java类,实现ObjectEncodingHandler接口,如你打算采用SBE(Simple Binary Encoding)进行数据序列化,就创建ObjectEncodingHandlerSbeImpl类,然后实现对应的逻辑
  • 根据Java的ServiceLoader机制,进行Services加载。在资源目录下创建META-INF/services/com.alibaba.rsocket.encoding.ObjectEncodingHandler文件,然后输入ObjectEncodingHandlerSbeImpl对应类的全名

alibaba-rsocket-core会通过ServiceLoader机制自动完成自定义序列格式处理类的加载,并在通讯过程中进行数据自动序列化和反序列化。

RSocket已经支持单个Payload的数据编码设置,你可以参考 Stream Data MIME Types Metadata Extension

上述的格式同样多多语言场景有效,你只需要按照RSocket标准协议进行设置即可。

Hessian序列化说明

不少Java框架都使用Hessian进行对象序列化,如Dubbo, Sofa等。 Alibaba RSocket Broker从Dubbo Hessian Lite中copy相关的handler,这样做的目的主要是数据格式兼容,可以实现RSocket和Dubbo直接相互调用。 主要提升点有以下:

  • 删除了反射相关的代码,RSocket支持的Java版本是1.8+,而且反射操作影响性能。
  • 使用Hessian标准的Serializer扩展,也就是META-INF/hessian/serializers中添加自定义Serializer
  • 添加了Optional支持

还进行了其他方面的一些测试,仅供参考:

  • 如果你在使用Joda Time,我们建议你切换到Java 8 Time或者扩展Joda Time对应的Serializer,Hessian会自动进行加载。
  • 对于使用Kotlin的同学来说,我们建议你自行扩展Hessian支持,如Range、Pair、Triple、Result、UInt、ULong等等。
  • 我看到有同学反馈Emoji的问题,测试中4个字节的Emoji支持没有问题的。
private String emojiBear = "我是🐻";
  • JDK 14的Records支持,这个没有问题,还是一样的写法,如果要添加Json序列化支持(Jackson),需要添加对应的@JsonProperty,同时implements Serializable接口
public record UserRecord(@JsonProperty("id") Integer id, @JsonProperty("name") String name) implements Serializable {
}

CloudEvent支持说明

Alibaba RSocket Broker支持CloudEvents规范的CloudEvent接口,你可以在函数声明中使用CloudEvent作为参数类型或者返回值类型,代码如下:

    Mono<CloudEvent> processLoginEvent(CloudEvent loginEvent);

注意: 目前支持CloudEvent类型作为函数的唯一参数,如果函数包含多个参数,其中一个参数为CloudEvent,这种情况是不支持的。