Skip to content
This repository has been archived by the owner on Jul 16, 2024. It is now read-only.

RSocket Binary

Libing Chen edited this page May 28, 2023 · 5 revisions

在很多的情况下,我们会在网络上传输二进制数据,如用户的照片、头像、合同文件等等,这个时候我们就需要传输二进制数据。 在实际的业务中,我们如何设计这样的接口?

传统的字节数组方式

将二进制数据组装为字节数组,然后作为参数传输给服务方,服务接口如下:

public interface UserService {
    Mono<Void> updateAvatar(Integer userId, byte[] avatar);  
} 

但是这种方式非常浪费系统资源,涉及到各种内存copy操作,从input stream读取,然后转换为byte数组,然后再copy到堆外内存写到网络。当然这个过程还有对象序列化的操作,又是一堆内存copy。 总之,这种方式可以工作,但是绝对不是高效的方式。 如果是视频流媒体等,这个接口几乎无法工作。

ByteBuffer方式

首先我们不屏蔽技术,RSocket Java是基于Netty的,为了更好方便传输二进制数据,我们直接使用ByteBuf和ByteBuffer这两个接口传输byte数据流。看一下如下代码结构:

public interface UserService {
   default Mono<Void> updateAvatar(Integer id, ByteBuffer avatar) {
       CompositeByteBuf byteBuf = PooledByteBufAllocator.DEFAULT.compositeDirectBuffer(2, toByteBuf(id), toByteBuf(avatar));
       return updateAvatar(byteBuf);
    }

    Mono<Void> updateAvatar(ByteBuf byteBuf);  
} 

考虑到API的友好性,我们使用Java接口的default method提供给应用进行调用,如你看到的updateAvatar,还是非常容易理解的业务接口。 接下来我们在default method中稍微做一些代码处理, 将参数转换为Netty的ByteBuf,然后交给负责通讯的通讯接口。

而在服务端,我们只需调用ByteBuf的接口,读取相关的数据,然后进行逻辑处理就可以啦,逻辑也非常简单。当然考虑到实际的便捷性,你可以使用一些工具类来简化你的工作。

Mono<Void> updateAvatar(ByteBuf byteBuf) {
       int userId =  byteBuf.readInt();
       ByteBuf avatar = byteBuf.slice();
       ....
}

二进制作为返回值

如果ByteBuf作为返回值类型,这里主要有两个场景:

  • 第一种是用于告知RSocket SDK不要进行反序列化,因为我接下来要进行其他输出,如REST API输出
    //接口声明
    Mono<ByteBuffer> findById(Integer id);
    
    //服务端实现
    Mono<User> findById(Integer id);
  • 第二种是真的二进制,开发者要自行进行ByteBuf内容解析,至于如何解析,是服务实现方开发者自行决定的,如下:
public interface UserServiceExtra {
    @ServiceMapping(decoding = "application/json")
    Mono<ByteBuffer> findById(Integer id);
}

RSocket

Network Protocol

  • Binary: byte stream
  • Async message
  • Multi transports
  • Reactive Semantics

Symmetric interactions

  • request/response
  • request/stream
  • fire-and-forget
  • channel

Transports

  • TCP+TLS
  • WebSocket+TLS
  • UDP(Aeron)
  • RDMA

Polyglot

Clone this wiki locally