前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >SpringCloud升级之路2020.0.x版-37. 实现异步的客户端封装配置管理的意义与设计

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

作者头像
干货满满张哈希
发布2021-12-30 16:03:41
9710
发布2021-12-30 16:03:41
举报
文章被收录于专栏:干货满满张哈希

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

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

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

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

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

代码语言:javascript
复制
// GET 请求 /anything 并将 body 转化为 String
Mono<String> stringMono = client.get().uri("/anything").retrieve().bodyToMono(String.class);
//这里为了测试,采用阻塞获取
String block = stringMono.block();

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

代码语言:javascript
复制
{
  "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:

代码语言:javascript
复制
@Autowired
ReactorLoadBalancerExchangeFilterFunction lbFunction;

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

代码语言:javascript
复制
//使用 WebClient 的 Builder 创建 WebClient
WebClient 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

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

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

代码语言:javascript
复制
//自动装载 我们自定义的 WebClient 的 NamedContextFactory,这个是我们后面要实现的
@Autowired
private WebClientNamedContextFactory webClientNamedContextFactory;


//通过微服务名称,获取对应的微服务调用的 WebClient
webClientNamedContextFactory.getWebClient("testService1");

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

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021/11/19 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 为何需要封装异步 HTTP 客户端 WebClient
  • 要实现的配置设计以及使用举例
相关产品与服务
负载均衡
负载均衡(Cloud Load Balancer,CLB)提供安全快捷的四七层流量分发服务,访问流量经由 CLB 可以自动分配到多台后端服务器上,扩展系统的服务能力并消除单点故障。轻松应对大流量访问场景。 网关负载均衡(Gateway Load Balancer,GWLB)是运行在网络层的负载均衡。通过 GWLB 可以帮助客户部署、扩展和管理第三方虚拟设备,操作简单,安全性强。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档