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

为何需要封装异步 HTTP 客户端 WebClient
对于同步的请求,我们使用 spring-cloud-openfeign 封装的 FeignClient,并做了额外的定制。对于异步的请求,使用的是异步 Http 客户端即 WebClient。WebClient 使用也比较简单,举一个简单的例子即:
//使用 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 进行调用:
// 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 都被返回了):
{
"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:
@Autowired
ReactorLoadBalancerExchangeFilterFunction lbFunction;
创建 WebClient 的时候,将这个 Filter 加入:
//使用 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 就能调用微服务了。
但是,这样还不能满足我们的需求:
- 需要在 WebClient 加入像 Feignclient 里面加的类似的重试与断路机制,线程隔离就不需要了,因为都是异步请求不会阻塞任务线程。
- 需要针对不同的微服务配置不同的连接超时以及响应超时来适应不同微服务。
- 这些配置都增加了代码的复杂度,我们需要减少这些代码对于业务的侵入性,最好能通过纯配置实现这些 WebClient 的初始化。
要实现的配置设计以及使用举例
首先,我们要实现的 WebClient,其 Filter 包含三个:
- 重试 Filter:重试的 Filter 要在负载均衡 Filter 之前,因为重试的时候,我们会从负载均衡器获取另一个实例进行重试,而不是在同一个实例上重试多次。
- 负载均衡 Filter,其实就是内置的
ReactorLoadBalancerExchangeFilterFunction - 断路器 Filter:断路器需要在负载均衡之后,因为只有负载均衡之后才能拿到具体本地调用的服务实例,这样我们才能实现基于微服务实例方法级别的断路器。
需要重试的场景:
- 非 2xx 的响应码返回,并且方法是可以重试的方法。如何定义方法是可以重试的,首先 GET 方法是可以重试的,对于其他方法,根据配置中的是否配置了这个 URL 可以重试决定。
- 异常重试:
- 连接异常:例如连接超时,连接中断等等,所有请求的连接异常都可以重试,因为请求并没有发出去。
- 断路器异常:该服务实例方法级别的断路器打开了,需要直接重试其他实例,因为请求并没有发出去。
- 响应超时异常:这个重试逻辑和非 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,这个是我们后面要实现的
@Autowired
private WebClientNamedContextFactory webClientNamedContextFactory;
//通过微服务名称,获取对应的微服务调用的 WebClient
webClientNamedContextFactory.getWebClient("testService1");
接下来,我们会实现这些。
微信搜索“我的编程喵”关注公众号,每日一刷,轻松提升技术,斩获各种offer:

SpringCloud升级之路2020.0.x版-37. 实现异步的客户端封装配置管理的意义与设计的更多相关文章
- SpringCloud升级之路2020.0.x版-18.Eureka的客户端核心设计和配置
本系列代码地址:https://github.com/HashZhang/spring-cloud-scaffold/tree/master/spring-cloud-iiford Eureka 客户 ...
- SpringCloud升级之路2020.0.x版-1.背景
本系列为之前系列的整理重启版,随着项目的发展以及项目中的使用,之前系列里面很多东西发生了变化,并且还有一些东西之前系列并没有提到,所以重启这个系列重新整理下,欢迎各位留言交流,谢谢!~ Spring ...
- SpringCloud升级之路2020.0.x版-41. SpringCloudGateway 基本流程讲解(1)
本系列代码地址:https://github.com/JoJoTec/spring-cloud-parent 接下来,将进入我们升级之路的又一大模块,即网关模块.网关模块我们废弃了已经进入维护状态的 ...
- SpringCloud升级之路2020.0.x版-6.微服务特性相关的依赖说明
本系列代码地址:https://github.com/HashZhang/spring-cloud-scaffold/tree/master/spring-cloud-iiford spring-cl ...
- SpringCloud升级之路2020.0.x版-10.使用Log4j2以及一些核心配置
本系列代码地址:https://github.com/HashZhang/spring-cloud-scaffold/tree/master/spring-cloud-iiford 我们使用 Log4 ...
- SpringCloud升级之路2020.0.x版-43.为何 SpringCloudGateway 中会有链路信息丢失
本系列代码地址:https://github.com/JoJoTec/spring-cloud-parent 在开始编写我们自己的日志 Filter 之前,还有一个问题我想在这里和大家分享,即在 Sp ...
- SpringCloud升级之路2020.0.x版-21.Spring Cloud LoadBalancer简介
本系列代码地址:https://github.com/HashZhang/spring-cloud-scaffold/tree/master/spring-cloud-iiford 我们使用 Spri ...
- SpringCloud升级之路2020.0.x版-29.Spring Cloud OpenFeign 的解析(1)
本系列代码地址:https://github.com/JoJoTec/spring-cloud-parent 在使用云原生的很多微服务中,比较小规模的可能直接依靠云服务中的负载均衡器进行内部域名与服务 ...
- SpringCloud升级之路2020.0.x版-34.验证重试配置正确性(1)
本系列代码地址:https://github.com/JoJoTec/spring-cloud-parent 在前面一节,我们利用 resilience4j 粘合了 OpenFeign 实现了断路器. ...
随机推荐
- HTML对溢出的控制:overflow
用于对超出模块的内容进行控制 overflow的三种参数 1.visible(默认):溢出部分可见 2.hidden:溢出部分隐藏 3.auto:适当加入滚动条 overflow使用方法 1.常用 o ...
- 深入思考软件工程,开启 DevOps 之旅
20 世纪 60 年代,软件开始脱离硬件,逐渐成为一个独立产业.至今,软件开发过程从瀑布模型.CMM/CMMI,到 20 年前敏捷的诞生,再到今天 DevOps 的火热,一代代软件人在思考和探索,如何 ...
- 一个神秘的oj2587 你猜是不是dp(线段树优化建图)
哇 这难道不是happiness的翻版题嘛? 从\(S\)向一个点连染成白色的收益 从这个点向\(T\)连染成黑色的收益 对于额外的收益,建一个辅助点,跟区间内的每个点连\(inf\),然后向S/T, ...
- css单位px,em,rem区别
在css中单位长度用的最多的是px.em.rem,这三个的区别是: px是固定的像素,一旦设置了就无法因为适应页面大小而改变. em和rem相对于px更具有灵活性,他们是相对长度单位,意思是长度不是定 ...
- 2.2 DDD Layers & Clean Architecture DDD分层和简洁架构
DDD Layers & Clean Architecture DDD分层和简洁架构 There are four fundamental layers of a Domain Driven ...
- MarkDown之Typora使用
Typora:所见即所得 常用快捷键 加粗:ctrl + B 标题:ctrl + 16,对于与16级标题 插入公式:ctrl + Shift + m 插入代码:ctrl + Shift + K 插入图 ...
- mybatis学习笔记(2)基本原理
引言在mybatis的基础知识中我们已经可以对mybatis的工作方式窥斑见豹(参考:<MyBatis----基础知识>).但是,为什么还要要学习mybatis的工作原理?因为,随着myb ...
- 单片机I/O口推挽与开漏输出详解(力荐)
推挽输出:可以输出高,低电平,连接数字器件;推挽结构一般是指两个三极管分别受两互补信号的控制,总是在一个三极管导通的时候另一个截止. 开漏输出:输出端相当于三极管的集电极. 要得到高电平状态需要上拉电 ...
- 零基础要怎么样学习嵌入式Linux--走进嵌入式
零基础要怎么样学习嵌入式希望可以通过这一篇帖子让大家走进嵌入式,对嵌入式的学习不再那么陌生. 嵌入式Linux工程师的学习需要具备一定的C语言基础,因此面对许多朋友只是在大一或者大二学习过C(还不一定 ...
- 双堆DEAP
记录一道遇到的考研真题 特性分析: DEAP为一颗完全二叉树,左子树小堆,右子树大堆,故左右子树分别可以用l[].r[]数组存储,用m和n分别表示当前两完全二叉树的结点,左右子树高度差为1,且左子树的 ...