资讯专栏INFORMATION COLUMN

SpringCloud升级之路2020.0.x版-37. 实现异步的客户端封装配置管理的意义与设计

fxp / 466人阅读

摘要:对于异步的请求,使用的是异步客户端即。要实现的配置设计以及使用举例要实现的配置设计以及使用举例首先,我们要实现的,其包含三个重试重试的要在负载均衡之前,因为重试的时候,我们会从负载均衡器获取另一个实例进行重试,而不是在同一个实例上重试多次。

本系列代码地址:https://github.com/JoJoTec/spring-cloud-parent

为何需要封装异步 HTTP 客户端 WebClient

对于同步的请求,我们使用 spring-cloud-openfeign 封装的 FeignClient,并做了额外的定制。对于异步的请求,使用的是异步 Http 客户端即 WebClient。WebClient 使用也比较简单,举一个简单的例子即:

//使用 WebClient 的 Builder 创建 WebClientWebClient client = WebClient.builder()  //指定基址  .baseUrl("http://httpbin.org")  //可以指定一些默认的参数,例如默认 Cookie,默认 HttpHeader 等等  .defaultCookie("cookieKey", "cookieValue")  .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)   .build();

创建好 WebClient 后即可以使用这个 WebClient 进行调用:

// GET 请求 /anything 并将 body 转化为 StringMono stringMono = client.get().uri("/anything").retrieve().bodyToMono(String.class);//这里为了测试,采用阻塞获取String block = stringMono.block();

返回的结果如下所示(请求 http://httporg.bin/anything 会将请求中的所有内容原封不动返回,从这里我们可以看出上面测试的 Header 还有 cokkie 都被返回了):

{  "args": {},   "data": "",   "files": {},   "form": {},   "headers": {    "Accept": "*/*",     "Accept-Encoding": "gzip",     "Cookie": "TestCookie=TestCookieValue,getAnythingCookie=getAnythingCookieValue",     "Getanythingheader": "getAnythingHeaderValue",     "Host": "httpbin.org",     "Testheader": "TestHeaderValue",     "User-Agent": "ReactorNetty/1.0.7"  },   "json": null,   "method": "GET",   "origin": "12.12.12.12",   "url": "http://httpbin.org/anything"}

我们也可以加入负载均衡的功能,让 WebClient 利用我们内部的 LoadBalancer,负载均衡调用其他微服务,首先注入负载均衡 Filter:

@AutowiredReactorLoadBalancerExchangeFilterFunction lbFunction;

创建 WebClient 的时候,将这个 Filter 加入:

//使用 WebClient 的 Builder 创建 WebClientWebClient client = WebClient.builder()  //指定基址微服务  .baseUrl("http://微服务名称")  //可以指定一些默认的参数,例如默认 Cookie,默认 HttpHeader 等等  .defaultCookie("cookieKey", "cookieValue")  .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)   //负载均衡器,改写url  .filter(lbFunction)  .build();

这样,这个 WebClient 就能调用微服务了。

但是,这样还不能满足我们的需求:

  1. 需要在 WebClient 加入像 Feignclient 里面加的类似的重试与断路机制,线程隔离就不需要了,因为都是异步请求不会阻塞任务线程。
  2. 需要针对不同的微服务配置不同的连接超时以及响应超时来适应不同微服务。
  3. 这些配置都增加了代码的复杂度,我们需要减少这些代码对于业务的侵入性,最好能通过纯配置实现这些 WebClient 的初始化。

要实现的配置设计以及使用举例

首先,我们要实现的 WebClient,其 Filter 包含三个:

  1. 重试 Filter:重试的 Filter 要在负载均衡 Filter 之前,因为重试的时候,我们会从负载均衡器获取另一个实例进行重试,而不是在同一个实例上重试多次
  2. 负载均衡 Filter,其实就是内置的 ReactorLoadBalancerExchangeFilterFunction
  3. 断路器 Filter:断路器需要在负载均衡之后,因为只有负载均衡之后才能拿到具体本地调用的服务实例,这样我们才能实现基于微服务实例方法级别的断路器

需要重试的场景:

  1. 非 2xx 的响应码返回,并且方法是可以重试的方法。如何定义方法是可以重试的,首先 GET 方法是可以重试的,对于其他方法,根据配置中的是否配置了这个 URL 可以重试决定
  2. 异常重试
    1. 连接异常:例如连接超时,连接中断等等,所有请求的连接异常都可以重试,因为请求并没有发出去。
    2. 断路器异常:该服务实例方法级别的断路器打开了,需要直接重试其他实例,因为请求并没有发出去。
    3. 响应超时异常:这个重试逻辑和非 2xx 的响应码返回一样。

我们需要实现的配置方式是,通过这样配置 application.yml

webclient:  configs:    //微服务名称    testService1:      //请求基址,第一级域名作为微服务名称      baseUrl: http://testService1      //最多的 http 连接数量      maxConnection: 50      //连接超时      connectTimeout: 500ms      //响应超时      responseTimeout: 60s      //除了 GET 方法外,哪些路径还能重试      retryablePaths:        - /retryable/**        - /user/orders

加入这些配置,我们就能获取载对应微服务的 WebClient 的 Bean,例如:

//自动装载 我们自定义的 WebClient 的 NamedContextFactory,这个是我们后面要实现的@Autowiredprivate WebClientNamedContextFactory webClientNamedContextFactory;//通过微服务名称,获取对应的微服务调用的 WebClientwebClientNamedContextFactory.getWebClient("testService1");

接下来,我们会实现这些。

微信搜索“我的编程喵”关注公众号,每日一刷,轻松提升技术,斩获各种offer

 

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/123997.html

相关文章

  • SpringCloud升级之路2020.0.x-41. SpringCloudGateway 基本

    摘要:将请求封装成将请求封装成的接口定义是但是最外层传进来的参数是和,需要将他们封装成,这个工作就是在中做的。其实主要任务就是将各种参数封装成除了和本次请求相关的和,还有会话管理器,编码解码器配置,国际化配置还有用于扩展。本系列代码地址:https://github.com/JoJoTec/spring-cloud-parent接下来,将进入我们升级之路的又一大模块,即网关模块。网关模块我们废弃了...

    不知名网友 评论0 收藏0
  • SpringCloud升级之路2020.0.x-41. SpringCloudGateway 基本

    摘要:在这里,会将上下文中载入的拼接成,然后调用其方法的,它是的处理请求业务的起点。添加相关依赖之后,会有这个。路由权重相关配置功能相关实现类,这个我们这里不关心。本系列代码地址:https://github.com/JoJoTec/spring-cloud-parent我们继续分析上一节提到的 WebHandler,经过将请求封装成 ServerWebExchange 的 HttpWebHand...

    不知名网友 评论0 收藏0
  • SpringCloud升级之路2020.0.x-41. SpringCloudGateway 基本

    摘要:在这里,会将上下文中载入的拼接成,然后调用其方法的,它是的处理请求业务的起点。添加相关依赖之后,会有这个。路由权重相关配置功能相关实现类,这个我们这里不关心。 本系列代码地址:​​https://github.com/JoJoTec/spring-cloud-parent​​我们继续分析上一节提到的 ​​WebHandle...

    番茄西红柿 评论0 收藏2637
  • SpringCloud升级之路2020.0.x-44.避免链路信息丢失做设计(1)

    摘要:运行不切换线程,这样其实限制了的灵活调度,是有一些性能损失的。我们其实想尽量就算加入了链路追踪信息,也不用强制运行不切换线程。本系列代码地址:https://github.com/JoJoTec/spring-cloud-parent我们在这一节首先分析下 Spring Cloud Gateway 一些其他可能丢失链路信息的点,之后来做一些可以避免链路信息丢失的设计,之后基于这个设计去实现我...

    不知名网友 评论0 收藏0
  • SpringCloud升级之路2020.0.x-44.避免链路信息丢失做设计(1)

    摘要:仅仅为了暴露的使用的工具类下一节,我们将继续讲解避免链路信息丢失做的设计,主要针对获取到现有之后,如何保证每个都能保持链路信息。 本系列代码地址:​​https://github.com/JoJoTec/spring-cloud-parent​​我们在这一节首先分析下 Spring Cloud Gateway 一些其他可能...

    番茄西红柿 评论0 收藏2637

发表评论

0条评论

最新活动
阅读需要支付1元查看
<