在某些时候,我们希望某个同步调用执行更长的时间(异步暂时不考虑),这个时候,首先就是要设置OpenFeign的timeout设定。

下面我们举例来说明,可以如何设定TimeOut参数。

一、环境

脱离环境说明问题就是流氓。

cloud的版本为 2021.0.0

spring-boot-starter-parent 本本是2.6.2

通过官网和下载的jar包可以看到,OpenFeign有关的版本是3.1.0。

于是我们取看下官网的文档。

二、概述

1.通过官网的timeout章节,我们可以看到设置timeout至少有两种方式:通过属性文件(properties/yml)和配置

2.这个版本的openFeign设计至少是比较合理的

三、代码

分为四个部分:

1.目标服务CustomerService的list接口

    @RequestMapping(value = "/list")
@ResponseBody
public Object list() throws InterruptedException { // TODO:
Thread.sleep(25000);
Map<String,Object> customer=new HashMap<String,Object>();
customer.put("name","lzf");
customer.put("sex","男");
customer.put("age","99");
customer.put("address","中华");
return customer;
}
以上代码故意演示25秒。

2.测试服务ConfigServiceTest的属性文件

feign:
client:
config:
default:
connectTimeout: 30000
readTimeout: 30000

connectTimeout--连接超时

readTimeout--读取超时

二者的区别在于:readTimeout只有成功连接后才会触发。所以如果连接总是没有问题,但是执行太久,那么就必须设定readTimeout。

并非二者必须配对使用。

--

注意:default关键字标识对所有client生效,如果是想针对某个服务,可以直接写服务名称,例如这里可以写 CustomerService.

3.测试服务ConfigServiceTest的java配置

配置类

public class CustomerServiceFeignInter {

    @Bean
public Integer connectTimeOut() {
return 30000;
} @Bean
public Integer readTimeOut() {
return 30000;
} @Bean
public ErrorDecoder feignErrorDecoder() {
return new ErrorHandler();
} @Bean
public RequestInterceptor currentUserRequestInterceptor() {
return (RequestTemplate template) -> {
//Map<String, Collection<String>> header=template.request().headers();
//System.out.println(JSON.toJSONString(header, true));
String token = LoginCache.get();
System.out.println(token);
template.header("Authorization", token);
};
} }

注:根据关方文档,config还有另外一种下发,如下:

@Import(FeignClientsConfiguration.class)
class FooController { private FooClient fooClient; private FooClient adminClient; @Autowired
public FooController(Client client, Encoder encoder, Decoder decoder, Contract contract, MicrometerCapability micrometerCapability) {
this.fooClient = Feign.builder().client(client)
.encoder(encoder)
.decoder(decoder)
.contract(contract)
.addCapability(micrometerCapability)
.requestInterceptor(new BasicAuthRequestInterceptor("user", "user"))
.target(FooClient.class, "https://PROD-SVC"); this.adminClient = Feign.builder().client(client)
.encoder(encoder)
.decoder(decoder)
.contract(contract)
.addCapability(micrometerCapability)
.requestInterceptor(new BasicAuthRequestInterceptor("admin", "admin"))
.target(FooClient.class, "https://PROD-SVC");
}
}

服务接口bean

@FeignClient(value = "CustomerService",configuration= CustomerServiceFeignInter.class)
@Component
public interface CustomerServiceOpenFeignInterface {
@RequestMapping(value = "/customer/list")
public Object list();
}

注:根据spring官网的说明,如果有属性和java配置的时候,属性处于优先低位,java配置对应部分被无视。

4.测试服务ConfigServiceTest的测试代码

    @RequestMapping(value = "/timeout")
@ResponseBody
public PublicReturn timeout() { // TODO:
try{
Object result=customerService.list();
Map<String,Object> resultMap=new HashMap<>();
resultMap.put("customer",result);
PublicReturn re= PublicReturn.getSuccessful("ok",resultMap);
return re;
}
catch (Exception e){
return PublicReturn.getUnSuccessful(e.getMessage());
}
}

四、测试和结论

1.如果只是设置属性,那么可以生效,在超过25秒之后,可以看到返回结果。

{
"flag": 1,
"message": "ok",
"data": {
"customer": {
"address": "中华",
"sex": "男",
"name": "lzf",
"age": "99"
}
}
}

2.如果只是设置java配置(即上文的CustomerServiceFeignInter),那么结果同1

3.如果二者都有设置,且属性的timeOut是5秒,而配置还是30秒,那么结果是属性胜出,客户端5秒之后报告异常

feign:
client:
config:
default:
connectTimeout: 5000
readTimeout: 5000
compression:
request:
enabled: true
min-request-size: 2048
response:
enabled: true
    @RequestMapping(value = "/timeout")
@ResponseBody
public PublicReturn timeout() { // TODO:
long start=System.currentTimeMillis();
try{
Object result=customerService.list();
Map<String,Object> resultMap=new HashMap<>();
resultMap.put("customer",result);
PublicReturn re= PublicReturn.getSuccessful("ok",resultMap);
return re;
}
catch (Exception e){
long end=System.currentTimeMillis();
return PublicReturn.getUnSuccessful("连接异常"+e.getMessage()+",当前耗费时间"+(end-start));
}
}

结果:

{
"flag": 0,
"message": "连接异常Read timed out executing GET http://CustomerService/customer/list,当前耗费时间5178",
"data": {}
}

属性配置胜出!

五、相干问题-压缩

如果觉得是因为没有压缩导致的timeout或者性能等考虑,那么可以启动压缩,尽量避免超时。

具体设置见前文。

六、相关问题-异步

如果实在不想等太久,那么可以考虑采用异步的方式调用。

关于异步的调用,可以参考https://www.jb51.net/article/212227.htm#_label2

    @Bean
public CustomerServiceOpenFeignInterface originFeignClient(SpringEncoder springEncoder, SpringDecoder springDecoder) {
return AsyncFeign.asyncBuilder()
.encoder(springEncoder)
.decoder(springDecoder)
.target(CustomerServiceOpenFeignInterface.class, "http://localhost.charlesproxy.com:8090");
}

测试代码

@GetMapping("testApi")
public String testAsyncClient() throws ExecutionException, InterruptedException {
List<CompletableFuture<String>> results = new ArrayList<>();
for(int i = 0; i < 10; i++) {
results.add(originFeignClient.api(i+""));
}
Thread.sleep(3000);
int index = 0;
for (CompletableFuture<String> result : results) {
String str = result.get();
log.info(String.format("%d, result:%s, ", index, str));
index++;
}
return "success";
}

或者官网的文档

七、结论

openFeign越来越完善的情况下,我们倾向于直接使用它的功能。

不过openFeign的一些写法,我也不是很苟同--例如在破坏原有编码习惯的情况下,编写代码,例如下面的:

public interface UserService {

    @RequestMapping(method = RequestMethod.GET, value ="/users/{id}")
User getUser(@PathVariable("id") long id);
} @RestController
public class UserResource implements UserService { } package project.user; @FeignClient("users")
public interface UserClient extends UserService { }

看起来比较怪异,我个人不是很习惯和接受,已经强烈要求大伙不那么写。

SpringCloud开发之OpenFeign timeout和压缩等问题的更多相关文章

  1. Android安全开发之ZIP文件目录遍历

    1.ZIP文件目录遍历简介 因为ZIP压缩包文件中允许存在“../”的字符串,攻击者可以利用多个“../”在解压时改变ZIP包中某个文件的存放位置,覆盖掉应用原有的文件.如果被覆盖掉的文件是动态链接s ...

  2. Asp.net Mvc模块化开发之“部分版本部分模块更新(上线)”

    项目开发从来就不是一个简单的问题.更难的问题是维护其他人开发的项目,并且要修改bug.如果原系统有重大问题还需要重构. 怎么重构系统不是本文探讨的问题,但是重构后如何上线部署和本文关系密切.这个大家可 ...

  3. ArcGIS Engine开发之旅05---空间数据库

    原文:ArcGIS Engine开发之旅05---空间数据库 1  Geodatabase概念 Geodatabase是ArcInfo8引入的一种全新的面向对象的空间数据模型,是建立在DBMS之上的统 ...

  4. Android开发之Java必备基础

    Android开发之Java必备基础 Java类型系统 Java语言基础数据类型有两种:对象和基本类型(Primitives).Java通过强制使用静态类型来确保类型安全,要求每个变量在使用之前必须先 ...

  5. iOS多线程开发之GCD(中篇)

    前文回顾: 上篇博客讲到GCD的实现是由队列和任务两部分组成,其中获取队列的方式有两种,第一种是通过GCD的API的dispatch_queue_create函数生成Dispatch Queue:第二 ...

  6. Android 安全开发之 ZIP 文件目录遍历

    1.ZIP文件目录遍历简介 因为ZIP压缩包文件中允许存在"../"的字符串,攻击者可以利用多个"../"在解压时改变ZIP包中某个文件的存放位置,覆盖掉应用原 ...

  7. Android开发之旅3:android架构

    引言 通过前面两篇: Android 开发之旅:环境搭建及HelloWorld Android 开发之旅:HelloWorld项目的目录结构 我们对android有了个大致的了解,知道如何搭建andr ...

  8. 高效开发之SASS篇 灵异留白事件——图片下方无故留白 你会用::before、::after吗 link 与 @import之对比 学习前端前必知的——HTTP协议详解 深入了解——CSS3新增属性 菜鸟进阶——grunt $(#form :input)与$(#form input)的区别

    高效开发之SASS篇   作为通往前端大神之路的普通的一只学鸟,最近接触了一样稍微高逼格一点的神器,特与大家分享~ 他是谁? 作为前端开发人员,你肯定对css很熟悉,但是你知道css可以自定义吗?大家 ...

  9. .NET Core 跨平台 GUI 开发之 GTtkSharp 初级篇

    .NET Core 跨平台 GUI 开发之 GTtkSharp 初级篇 本文作为初级篇,适合已经安装好.NET Core 环境以及 Gtk 环境,并具备了 C#开发基础知识,能跑一些简单的例子,希望更 ...

  10. iOS多线程开发之GCD(中级篇)

    前文回顾: 上篇博客讲到GCD的实现是由队列和任务两部分组成,其中获取队列的方式有两种,第一种是通过GCD的API的dispatch_queue_create函数生成Dispatch Queue:第二 ...

随机推荐

  1. dotnet 读 WPF 源代码笔记 GlyphRun 的 DeviceFontName 的功能是什么

    在 WPF 里面的 GlyphRun 里,有一个令人迷惑的 DeviceFontName 属性,似乎给这个属性传入什么值,结果都不会有变更.通过阅读源代码,可以了解到,这是一个没什么用途的属性.本文将 ...

  2. 剪贴板被占用导致应用使用剪贴板拷贝内容失败抛出 COMException 0x800401D0 错误

    本文记录某些软件,例如 向日葵远程控制 软件占用剪贴板,导致 WPF 应用使用剪贴板拷贝内容和设置剪贴板时,抛出 System.Runtime.InteropServices.COMException ...

  3. RT-Thead移植时缺少SystemCoreClockUpdate函数

    一.问题 在移植 RT-Thead 时,需要获取mcu当前的 HCLK 时钟频率来设置滴答时钟,而我使用的库函数中刚好缺少SystemCoreClockUpdate函数. 我之前在RT-Thread移 ...

  4. vue+vant+js实现购物车原理小demo(高级版选择与反选)

    新增反选功能.上图(这个系列系利用前端框架的原创): main.js: Vue.use(Stepper); Vue.use(Checkbox); Vue.use(CheckboxGroup); .vu ...

  5. htts证书申请

    https://freessl.cn/ 教程: https://www.bilibili.com/video/BV1Ug411673P/?spm_id_from=333.337.search-card ...

  6. Docker基础 ubuntu安装docker

    目录 如何在Linux深度系统deepin下安装docker 介绍 安装docker 在ubuntu的docker中运行ubuntu 在ubuntu的docker中运行centos 卸载docker ...

  7. cuBlas API Launch Latency 耗时异常分析记录

    一.背景 最近在做 AI 编译器生成 Kernel 支持 Bert 模型训练调优工作,在分析 bert 的timeline中发现,在每个 step 的前两个 cinn_instruction_run ...

  8. 80x86汇编—分支循环程序设计

    文章目录 查表法: 实现16进制数转ASCII码显示 计算AX的绝对值 判断有无实根 地址表形成多分支 从100,99,...,2,1倒序累加 输入一个字符,然后输出它的二进制数 大小写转换 大写转小 ...

  9. 在身份认证后建立用户对象ICurrentUser

    app.UseAuthentication(); 这个中间件添加后,他会为HttpContext.User设置一个ClaimsPrincipal对象.里面有身份认证token里面携带的信息. 其访问方 ...

  10. .NET Aspire 正式发布:简化 .NET 云原生开发

    .NET团队北京时间2024年5月22日已正式发布.NET Aspire ,在博客文章里做了详细的介绍:.NET Aspire 正式发布:简化 .NET 云原生开发 - .NET 博客 (micros ...