Linkis架构解析系列(一)——Linkis RPC架构解析

Stella981
• 阅读 679

为了提升Linkis的高并发能力,Linkis基于微服务架构,在Feign的基础之上,实现了一套自己的底层RPC通信方案,用以提升微服务间的通信性能和并发能力。

基于Feign的微服务之间HTTP接口调用,只能满足简单的A微服务实例根据简单的规则随机访问B微服务之中的某个服务实例,而这个B微服务实例如果想异步回传信息给调用方,是根本无法实现的。

同时,由于Feign只支持简单的服务选取规则,无法做到将请求转发给指定的微服务实例,无法做到将一个请求广播给接收方微服务的所有实例。

Linkis RPC是基于Spring Cloud + Feign实现的一套微服务间的异步请求和广播通信服务,可以独立于Linkis而使用。

01

简介

Linkis RPC作为底层的通信方案,将提供SDK集成到有需要的微服务之中。

一个微服务既可以作为请求调用方,也可以作为请求接收方。

作为请求调用方时,将通过Sender请求目标接收方微服务的Receiver,作为请求接收方时,将提供Receiver用来处理请求接收方Sender发送过来的请求,以便完成同步响应或异步响应。

Linkis架构解析系列(一)——Linkis RPC架构解析

02

实现

基于请求调用方的Sender体系和请求接收方的Receiver体系,构成了Linkis RPC的全部架构。

Linkis架构解析系列(一)——Linkis RPC架构解析

发送端

Linkis RPC作为底层的通信层,发送端无需使用者写任何的实际代码。

  • 使用者通过调用Linkis RPC提供的SDK,通过微服务名(Service Name)或指定微服务实例(微服务名+微服务实例的IP和端口),获取一个Sender发送器。

       Sender提供的可使用方法,见如下伪代码:

abstract class Sender {    Object ask(Object message);    Object ask(Object message, Duration timeout);    void send(Object message);    void deliver(Object message);}

       其中:

1. ask方法为同步请求响应方法,要求接收端必须同步返回响应;2. send方法为同步请求方法,只负责同步将请求发送给接收端,不要求接收端给出答复;3. deliver则为异步请求方法,只要发送端的进程不异常退出,在稍后会通过其它线程将请求发送给接收端。
  • 使用者作为发送端,通过Sender发送器提供的请求方法,发送请求给接收端。

  • Sender发送器会将使用者的请求传递给拦截器。拦截器拦截请求,开始对请求做额外的功能性处理:

广播拦截器

广播拦截器只对需要进行广播的请求生效。

广播拦截器会提供特殊的广播接口,如果本次请求实现了该广播接口,且该请求不是正在广播中,广播拦截器则认为本次请求需要进行广播,这时会触发广播操作。

重试拦截器

重试拦截器会对接下来的所有步骤提供重试功能。

如果接收端要求重试,或者发送请求时出现了ConnectException(连接异常),或者使用者指定某些异常需要重试,这时重试拦截器会自动进行重试。

缓存拦截器

缓存拦截器是针对一些响应内容不大可能经常变动的同步请求而设定的。

缓存拦截器也会提供特殊的缓存接口,如果本次请求实现了缓存接口,会首先在缓存拦截器中寻找缓存,不存在缓存才会继续请求,并在拿到响应后,先将响应缓存起来,再将响应返回。

默认拦截器

默认拦截器用于调用接下来的处理步骤。

自定义拦截器

使用者也可以自己实现自定义拦截器,用于实现一些特定的功能。

  • 请求编码器会先将用户请求的数据(实体Bean)转换成序列化的JSON字符串,然后传递给Feign客户端生成器。

  • Feign客户端生成器,生成可访问接收端Restful请求接收器的Feign客户端。

  • 生成的Feign客户端,会调用Eureka客户端,获取所有微服务列表,通过服务选择器,如果使用者指定微服务名,则通过Feign的负载均衡策略,选择一个合适的接收方微服务实例进行请求转发,否则服务选择器会重写Spring Cloud Feign的FeignLoadBalancer(Feign负载均衡器),在创建LoadBalancerCommand时,请求使用者指定的微服务实例(微服务名+微服务实例address)。

  • 调用Feign客户端,开始请求接收端的Restful请求接收器。

接收端

接收端需要使用者实现Receiver接口,用于处理真正的业务逻辑。

  1. Restful请求接收器作为Linkis RPC内嵌的HTTP请求Web Service服务,负责接收发送端的请求

  2. Restful请求接收器接收到请求后,先调用请求解码器对请求进行解码,解析出实际的请求信息和发送端微服务信息(微服务名+微服务实例的IP和端口),如果解析失败,会直接响应解析请求失败。

  3. 将解析后的请求信息和发送端微服务信息放入请求消息队列;

  4. 请求消费器会消费请求消息队列里,已经解码的发送端请求。

        通过调用Receiver管理器获取一个合适的Receiver;同时通过发送端微服务信息,使用Sender生成器生成一个指向发送端的Sender。

        然后请求消费器将实际的请求信息和生成的发送端Sender,传给Receiver进行处理。

  1. Receiver作为用户请求的实际处理单元,要求使用者必须实现Receiver接口,完成对调用端请求的实际处理逻辑。

       Receiver的伪代码如下:

public interface Receiver {    void receive(Object message, Sender sender);    Object receiveAndReply(Object message, Sender sender);    Object receiveAndReply(Object message, Duration duration, Sender sender);}

       Receiver提供了处理同步请求和异步请求的方法。

  1. 如果本次请求是异步请求,则调用Receiver的receive方法,由上层业务决定是否需要通过发送端的Sender回传响应。

  2. 如果本次请求是同步请求,则调用 Receiver的receiveAndReply方法,将返回值作为响应结果,回传发送端。

03

使用

Linkis RPC是两个微服务实例之间的相互访问,所以这里需要启动两个微服务,一个用于接收请求的TestReceiver微服务,一个用于发送请求的TestSender微服务。

TestReceiver微服务

  • 引入maven依赖

  • 配置application.yml

在resources下新建application.yml文件,以下为所有的配置信息:

请注意: 其中Eureka的URL地址必须与实际Eureka的首页地址相同。

server:
  • 配置linkis.properties

    是否开启测试模式

  • 实现Receiver接口

请注意: Receiver实现类必须以注解@Component或@Bean的方式,声明为一个spring bean。

@Component
  • 启动TestReceiver

Linkis架构解析系列(一)——Linkis RPC架构解析

至此,TestReceiver模块已成功启动,等待TestSender发送请求。

TestSender微服务

  • TestSender引入maven依赖、配置application.yml和linkis.properties的方式与TestReceiver大体一致,唯一的区别是application.yml的微服务名和端口需做修改,如下:

    server:
    
  • 请求TestReceiver

    public class TestSender {

  • 启动TestSender,即可看到TestReceiver接收到了TestSender的两个请求,且TestSender拿到了TestReceiver的第二个同步返回结果。

04

总结

Linkis作为计算中间件,为了提升微服务间的通信能力和并发能力,做了很多的尝试和努力。

Linkis RPC作为Linkis底层的核心模块之一,为实现Linkis的全异步访问和调用,重构了一套全新的通信机制。

欢迎大家试用和使用Linkis!

本文分享自微信公众号 - WeDataSphere(gh_273e85fce73b)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
AWS国庆双重礼,仅限7天
自2021年10月1日00:00起至2021年10月7日24:00,新注册并激活(需全部完成账号注册的五个步骤,否则账号状态并未激活)AWS海外区域账户,填写页面下方表单,即可申领价值$200美元的AWS海外区域账户服务抵扣券直充到您的账户,用以抵扣服务消费,助您轻松体验多个云迁移应用场景。同时,您还可获赠AWS精美祥云纪念T恤一件。,仅限7天$20
AWS国庆双重礼,仅限7天
自2021年10月1日00:00起至2021年10月7日24:00,新注册并激活(需全部完成账号注册的五个步骤,否则账号状态并未激活)AWS海外区域账户,填写页面下方表单,即可申领价值$200美元的AWS海外区域账户服务抵扣券直充到您的账户,用以抵扣服务消费,助您轻松体验多个云迁移应用场景。同时,您还可获赠AWS精美祥云纪念T恤一件。,仅限7天$20
Wesley13 Wesley13
2年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
2年前
Docker 部署SpringBoot项目不香吗?
  公众号改版后文章乱序推荐,希望你可以点击上方“Java进阶架构师”,点击右上角,将我们设为★“星标”!这样才不会错过每日进阶架构文章呀。  !(http://dingyue.ws.126.net/2020/0920/b00fbfc7j00qgy5xy002kd200qo00hsg00it00cj.jpg)  2
AWS国庆双重礼,仅限7天
自2021年10月1日00:00起至2021年10月7日24:00,新注册并激活(需全部完成账号注册的五个步骤,否则账号状态并未激活)AWS海外区域账户,填写页面下方表单,即可申领价值$200美元的AWS海外区域账户服务抵扣券直充到您的账户,用以抵扣服务消费,助您轻松体验多个云迁移应用场景。同时,您还可获赠。国庆双重礼,仅限7天$200美元AWS服务抵
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
3个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这