用于传输 FHIR 资源的 RSocket 与 HTTP 性能对比
RSocket vs HTTP performance for transferring FHIR resources
我最近开始了一系列关于使用 FHIR 资源的服务到服务通信的性能调查,以确定在以下方面花费的处理时间:
- 有效载荷communication/exchange
- 序列化和反序列化有效负载
在调查的过程中,遇到了两个结果,不明白,希望RSocket开发组的帮助。我会在后面详细说明结果和问题。
为了确定最快的通信方式,我分析了使用两种传输协议——HTTP 和 RSocket 的三种传输方式。更准确地说 - 我已经分析和基准测试:
- 使用 HAPI REST 服务器和 HAPI FHIR 客户端交换 FHIR 资源
- 使用 REST 通信交换字符串(序列化的 FHIR 资源),方法是使用 Spring
@RestController
使用 RestTemplate
网络客户端 访问端点
- 使用 RSocket 条消息交换 FHIR 资源
对前两种通信方法的分析表明,使用 HAPI REST 服务器交换 FHIR 资源与交换(原始)字符串有效负载(包括将这些有效负载反序列化为 FHIR 资源)之间存在巨大差异。更确切地说,对于大型 FHIR 资源,HAPI REST 服务器增加的开销大约是(原始)字符串通信和反序列化所带来的开销的 3-4 倍。
关于两个服务之间的RSocket通信——我尝试过使用两种模式来交换FHIR资源:
- 作为原始字符串,从 FHIR 资源序列化
- 作为原始 FHIR 资源,让 RSocket 处理序列化和反序列化
第一种方法(使用原始字符串)产生的负载交换开销几乎类似于 HTTP(使用 REST)通信所带来的开销。更确切地说,通信开销比 HTTP 通信高几个百分比 (5-10%)。这让我感到惊讶,因为我认为 RSocket 通信开销将比 HTTP 通信低 很多 - 我至少看过一个 Spring & Netifi 演示文稿,其中 RSocket 是宣传为“比 HTTP 快 10 倍”。
我的第一个想法是我在 RSocket 配置中做错了,因此我尝试了 RSocketRequester
Spring bean 的各种配置更改,从零复制帧的设置开始解码器。但是,其中 none 对整体性能做出了显着改进。
我的下一个尝试是通过实现 RSocket 编码器和解码器 类 来交换 FHIR 资源,从而在服务之间交换原始 FHIR 资源。在与 RSocket 编码器和解码器接口的实现进行了一些斗争之后,我设法在两个服务之间交换了 FHIR 资源。问题 - FHIR 资源通信的性能非常低,远低于 String
s 交换的性能。
对于很长的介绍/上下文设置相应的道歉,我的问题/帮助请求是:我做错了什么and/or我的分析中遗漏了,所以我没有获得性能优势RSocket 承诺?
我在 this Github repository. The most relevant classes are the RSocket configuration and the FHIR Bundle encoder and decoder.
中包含了两个示例项目(一个 RSocket 请求器和一个响应器)
免责声明:我知道这个问题在 Netifi community pages 上会得到更好的解决。在过去的几天里,该页面已无法访问,因此在此处写了这么长 post。
提前谢谢你。
这里是 RSocket 维护者。
简单看一下配置,我可能会说基准的格式不正确,显然会给出不正确的结果。
我可以直接说的是,在每个订阅中point you are calling readBundle
method which subscribe to the requesterMono every time you execute a remote call, which basically open a new TCP connection。
这意味着您实现的行为与标准 Http 1.0 行为完全相同(这就是您看到相同结果的原因)。
作为实现正确设置的第一步,我建议您缓存 Mono<RSocketRequester>
以便为所有调用重用相同的连接。
@Bean
public Mono<RSocketRequester> requester(BundleDecoder bundleDecoder, IntegerEncoder integerEncoder) {
final RSocketStrategies.Builder builder = RSocketStrategies.builder()
.decoder(bundleDecoder)
.encoder(integerEncoder);
return RSocketRequester.builder()
.rsocketFactory(factory -> factory.dataMimeType(MediaType.APPLICATION_CBOR_VALUE)
.frameDecoder(PayloadDecoder.ZERO_COPY))
.rsocketStrategies(builder.build())
.connectTcp(responderHost, responderPort)
.retry()
.cache();
}
除此之外,我可能会建议您查看 LoadBalancedRSocket
which let you efficiently reuse a couple of connections for tons of calls -> https://github.com/OlegDokuka/rsocket-issue-717
的用法
我最近开始了一系列关于使用 FHIR 资源的服务到服务通信的性能调查,以确定在以下方面花费的处理时间:
- 有效载荷communication/exchange
- 序列化和反序列化有效负载
在调查的过程中,遇到了两个结果,不明白,希望RSocket开发组的帮助。我会在后面详细说明结果和问题。
为了确定最快的通信方式,我分析了使用两种传输协议——HTTP 和 RSocket 的三种传输方式。更准确地说 - 我已经分析和基准测试:
- 使用 HAPI REST 服务器和 HAPI FHIR 客户端交换 FHIR 资源
- 使用 REST 通信交换字符串(序列化的 FHIR 资源),方法是使用 Spring
@RestController
使用RestTemplate
网络客户端 访问端点
- 使用 RSocket 条消息交换 FHIR 资源
对前两种通信方法的分析表明,使用 HAPI REST 服务器交换 FHIR 资源与交换(原始)字符串有效负载(包括将这些有效负载反序列化为 FHIR 资源)之间存在巨大差异。更确切地说,对于大型 FHIR 资源,HAPI REST 服务器增加的开销大约是(原始)字符串通信和反序列化所带来的开销的 3-4 倍。
关于两个服务之间的RSocket通信——我尝试过使用两种模式来交换FHIR资源:
- 作为原始字符串,从 FHIR 资源序列化
- 作为原始 FHIR 资源,让 RSocket 处理序列化和反序列化
第一种方法(使用原始字符串)产生的负载交换开销几乎类似于 HTTP(使用 REST)通信所带来的开销。更确切地说,通信开销比 HTTP 通信高几个百分比 (5-10%)。这让我感到惊讶,因为我认为 RSocket 通信开销将比 HTTP 通信低 很多 - 我至少看过一个 Spring & Netifi 演示文稿,其中 RSocket 是宣传为“比 HTTP 快 10 倍”。
我的第一个想法是我在 RSocket 配置中做错了,因此我尝试了 RSocketRequester
Spring bean 的各种配置更改,从零复制帧的设置开始解码器。但是,其中 none 对整体性能做出了显着改进。
我的下一个尝试是通过实现 RSocket 编码器和解码器 类 来交换 FHIR 资源,从而在服务之间交换原始 FHIR 资源。在与 RSocket 编码器和解码器接口的实现进行了一些斗争之后,我设法在两个服务之间交换了 FHIR 资源。问题 - FHIR 资源通信的性能非常低,远低于 String
s 交换的性能。
对于很长的介绍/上下文设置相应的道歉,我的问题/帮助请求是:我做错了什么and/or我的分析中遗漏了,所以我没有获得性能优势RSocket 承诺?
我在 this Github repository. The most relevant classes are the RSocket configuration and the FHIR Bundle encoder and decoder.
中包含了两个示例项目(一个 RSocket 请求器和一个响应器)免责声明:我知道这个问题在 Netifi community pages 上会得到更好的解决。在过去的几天里,该页面已无法访问,因此在此处写了这么长 post。
提前谢谢你。
这里是 RSocket 维护者。
简单看一下配置,我可能会说基准的格式不正确,显然会给出不正确的结果。
我可以直接说的是,在每个订阅中point you are calling readBundle
method which subscribe to the requesterMono every time you execute a remote call, which basically open a new TCP connection。
这意味着您实现的行为与标准 Http 1.0 行为完全相同(这就是您看到相同结果的原因)。
作为实现正确设置的第一步,我建议您缓存 Mono<RSocketRequester>
以便为所有调用重用相同的连接。
@Bean
public Mono<RSocketRequester> requester(BundleDecoder bundleDecoder, IntegerEncoder integerEncoder) {
final RSocketStrategies.Builder builder = RSocketStrategies.builder()
.decoder(bundleDecoder)
.encoder(integerEncoder);
return RSocketRequester.builder()
.rsocketFactory(factory -> factory.dataMimeType(MediaType.APPLICATION_CBOR_VALUE)
.frameDecoder(PayloadDecoder.ZERO_COPY))
.rsocketStrategies(builder.build())
.connectTcp(responderHost, responderPort)
.retry()
.cache();
}
除此之外,我可能会建议您查看 LoadBalancedRSocket
which let you efficiently reuse a couple of connections for tons of calls -> https://github.com/OlegDokuka/rsocket-issue-717