SpringCloud开发之OpenFeign timeout和压缩等问题
在某些时候,我们希望某个同步调用执行更长的时间(异步暂时不考虑),这个时候,首先就是要设置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和压缩等问题的更多相关文章
- Android安全开发之ZIP文件目录遍历
		
1.ZIP文件目录遍历简介 因为ZIP压缩包文件中允许存在“../”的字符串,攻击者可以利用多个“../”在解压时改变ZIP包中某个文件的存放位置,覆盖掉应用原有的文件.如果被覆盖掉的文件是动态链接s ...
 - Asp.net Mvc模块化开发之“部分版本部分模块更新(上线)”
		
项目开发从来就不是一个简单的问题.更难的问题是维护其他人开发的项目,并且要修改bug.如果原系统有重大问题还需要重构. 怎么重构系统不是本文探讨的问题,但是重构后如何上线部署和本文关系密切.这个大家可 ...
 - ArcGIS Engine开发之旅05---空间数据库
		
原文:ArcGIS Engine开发之旅05---空间数据库 1 Geodatabase概念 Geodatabase是ArcInfo8引入的一种全新的面向对象的空间数据模型,是建立在DBMS之上的统 ...
 - Android开发之Java必备基础
		
Android开发之Java必备基础 Java类型系统 Java语言基础数据类型有两种:对象和基本类型(Primitives).Java通过强制使用静态类型来确保类型安全,要求每个变量在使用之前必须先 ...
 - iOS多线程开发之GCD(中篇)
		
前文回顾: 上篇博客讲到GCD的实现是由队列和任务两部分组成,其中获取队列的方式有两种,第一种是通过GCD的API的dispatch_queue_create函数生成Dispatch Queue:第二 ...
 - Android 安全开发之 ZIP 文件目录遍历
		
1.ZIP文件目录遍历简介 因为ZIP压缩包文件中允许存在"../"的字符串,攻击者可以利用多个"../"在解压时改变ZIP包中某个文件的存放位置,覆盖掉应用原 ...
 - Android开发之旅3:android架构
		
引言 通过前面两篇: Android 开发之旅:环境搭建及HelloWorld Android 开发之旅:HelloWorld项目的目录结构 我们对android有了个大致的了解,知道如何搭建andr ...
 - 高效开发之SASS篇     灵异留白事件——图片下方无故留白    你会用::before、::after吗    link 与 @import之对比    学习前端前必知的——HTTP协议详解    深入了解——CSS3新增属性    菜鸟进阶——grunt   $(#form :input)与$(#form input)的区别
		
高效开发之SASS篇 作为通往前端大神之路的普通的一只学鸟,最近接触了一样稍微高逼格一点的神器,特与大家分享~ 他是谁? 作为前端开发人员,你肯定对css很熟悉,但是你知道css可以自定义吗?大家 ...
 - .NET Core 跨平台 GUI 开发之 GTtkSharp 初级篇
		
.NET Core 跨平台 GUI 开发之 GTtkSharp 初级篇 本文作为初级篇,适合已经安装好.NET Core 环境以及 Gtk 环境,并具备了 C#开发基础知识,能跑一些简单的例子,希望更 ...
 - iOS多线程开发之GCD(中级篇)
		
前文回顾: 上篇博客讲到GCD的实现是由队列和任务两部分组成,其中获取队列的方式有两种,第一种是通过GCD的API的dispatch_queue_create函数生成Dispatch Queue:第二 ...
 
随机推荐
- NopCommerce支持多种类型的数据库
			
本文章的内容是根据本人阅读NopCommerce源码的理解,如有不对的地方请指正,谢谢. 阅读目录 1.类结构关系图 2.分析 3.NopCommerce应用 类结构关系图 分析 NopObjectC ...
 - 鸿蒙HarmonyOS实战-ArkUI事件(触屏事件)
			
前言 触屏事件是指通过触摸屏幕来进行操作和交互的事件.常见的触屏事件包括点击(tap).双击(double tap).长按(long press).滑动(swipe).拖动(drag)等.触屏事件通常 ...
 - 11个Python循环技巧
			
本文分享自华为云社区<Python中的循环技巧指南>,作者:柠檬味拥抱. 当我们处理数据时,有时候需要创建多个列表以存储不同类型或不同条件下的数据.在Python中,我们可以利用循环来快速 ...
 - van-tab吸顶后头部透明色渐变响应
			
方法一:监听滚动事件 $('.scrollContent').bind('touchmove', function(e){ var winHeight = $(window) ...
 - 圈子社交系统--在线了解前后端,APP小程序H5,三端源码交付-多重玩法,新奇有趣。
			
圈子论坛社区系统,含完整的后台PHP系统.功能:小程序授权登陆,H5和APP,手机号登陆,发帖,建圈子.发活动.圈主可置顶推荐帖子,关注.点赞.评论.交流等.可作为圈子贴吧等自媒体. 一款全开源支持免 ...
 - idea在商店无法搜索到插件
			
背景:我使用的版本是IDEA ultimate 2019.2 版本印象中,最初安装的时候,商店还是可以用的,突然有一天,就无法使用了.下边直入正题: 解决办法:1.首先浏览器登陆下:https://p ...
 - k8s-nginx实战部署1
			
目录 yaml 资源清单 run_deploy.sh .gitlab-ci.yml yaml 资源清单 deploy.yaml apiVersion: v1 kind: ConfigMap metad ...
 - ༺$Musique$༻
			
往期链接在文末 最近好喜欢听一些有年代感的歌啊. ~~头图~~ <$ On\ \And \ On $> Hold me close til I get up Time is barely ...
 - java学习之旅(day.19)
			
多线程 线程简介 多任务:同时做多件事 进程(Process):在操作系统中运行的程序就是进程,如QQ,播放器,游戏. 线程(Thread):一个进程可以有多个线程,如视频中同时听声音,看弹幕,看图像 ...
 - 部署springboot+vue项目文档(若依ruoyi项目部署步骤)
			
摘自:https://blog.csdn.net/Dreamboy_w/article/details/104389797 部署springboot+vue项目文档(若依ruoyi项目部署步骤)一:部 ...