Skip to content

RSocket P2P

linux_china edited this page May 8, 2021 · 5 revisions

在一些性能非常关键的场景中,我们需要通过直连的服务提供方,这样性能比较高。

服务直连的优点:

  • 性能非常高:不需要经过Broker,可以减少TCP两跳,性能更高一些

服务直连的缺点:

  • 服务提供方需要提供对应的端口监听
  • 服务提供方要对服务台消费者连接时要进行对应的权限判断,可能还需要设置TLS等
  • 服务调用方的网络和服务提供方的网络是打通的,可以直接连接
  • 服务提供方要维护大量的网络连接,相对比较消耗资源

通常我们不建议服务消费方到服务提供方之间的直连,只有是性能非常关键的场景,才建议开启P2P直连。

服务直连是基于服务接口级别的,而不是基于应用级别的,一个应用提供的服务列表中,并不全是高QPS的场景。
那么如何开启服务的直连?

  • application.properties文件中添加 rsocket.p2p-services=com.alibaba.user.UserService2 配置项
  • RSocketRemoteServiceBuilder中调用p2p()方法设置该服务接口直连

如果服务提供者未提供对应的端口监听,则会通过Broker完成对应的调用。

RSocket服务直连的背后原理:

  • 服务消费方要告知UpstreamManager(连接管理器),有相关的service需要直连
  • 应用启动时,并不会创建直连服务,而是和Broker创建连接,所有的服务调用此时还是通过Broker进行转发的。
  • 应用和Broker创建连接后,如果Broker发现有应用有直连的服务接口信息,这时Broker会从路由表中查询直连服务对应的服务实例信息,过滤条件就是服务实例列表包含监听端口,然后就推送ServiceInstancesChangedEvent事件
  • 应用接收到ServiceInstancesChangedEvent事件后,如果服务对应的UpstreamCluster(服务连接管理器)不存在,则会创建该服务接口对应的UpstreamCluster,如果对应的UpstreamCluster已存在,则进行实例列表更新
  • 当有服务对应的实例上下线时,这个时候Broker会主动推送对应的ServiceInstancesChangedEvent,通知应用调整连接地址。
  • 为了确保服务对应的列表幂等,如推送的事件丢失等,UpstreamManager会每隔120秒进行一次和Broker同步,刷新直连服务对应的列表。
  • 服务消费方在调用远程服务,如果服务接口对应包含UpstreamCluster,则会走对应的UpstreamCluster方式,也就是服务直连,不然就是走Broker完成调用。

当然在实际的业务场景中,如果遇到服务提供方的地址非常多,可以考虑随机推送部分服务提供者的IP地址,这样服务连接方不用和服务提供方创建非常多的连接。 要知道这个设计中是有容错的,即便所有直连都错误,还是有Broker转发兜底的,所以不用太担心,服务总是能被调用的。

基于该服务列表推送机制,还可以完成其他一些场景,如某一应用调用某一服务接口的量特别大,这个时候,通过Metrics审计系统可以给Broker发一个推送服务地址列表事件,而应用侧收到该事件后,就会主动和服务提供方直连,这样即便应用侧没有设置直连,Metrics审计系统可以更加数据进行对应的调整。

如何解决P2P直连时安全验证问题

在服务直连的情况下,服务提供者如何验证服务消费者?每一个应用在启动后都会生成一个UUID,该UUID是惟一的,所以可以服务提供方可以根据UUID向Broker查询,Broker会根据应用接入的JWT token判断服务方能否可以调用对应的服务,如果合法,然后服务提供方允许应用方进行连接和服务调用访问。 发给服务提供者时,不需要发送JWT Token,只要发送AppMetadata给服务方就可以。

注意:这种方式存在安全风险,如从控制台查询到应用列表从而获得应用的UUID,但是对于内部通讯来说,还是有一定的安全保证的,主要是应用的UUID在应用重新启动后会使用新的。

该方案目前还是草案,RSocket Broker还没有添加对应的安全限制,还是开放连接的(未进行权限),并没有进行对应的安全验证。

Metrics

服务直连后,虽然请求不进过Broker啦,但是Metrics和Tracing这些数据还是都包含的,不会丢失。在RSocket Broker设计中,Broker是可以主动采集任何应用的Metrics信息的,所以这些数据都不会丢失的。

RSocket Broker提供的服务连接方式

  • 指定IP调用: 也就是指定服务对应的IP地址,这个主要是用于开发阶段,如你开发一个服务接口,其他同学抱怨接口有错误返回,只需将服务接口的对应的连接IP调整为你笔记本IP就可以啦。
  • Broker调用: 通过Broker转发请求,这个是RSocket Broker标准做法
  • 直连调用: 也就是本文说到的场景,核心是性能要求,当然还可以支持A/B testing,智能推送等。