http和dubbo接口调用主动设置超时时间
创始人
2024-02-27 23:05:31

http接口超时方案

  • 方案1:多个resttemplate,不同超时时间的使用不同的template,优点:简单,扩展起来复制粘贴,缺点:代码冗余,多个template占用内存不够优雅

  • 方案2:单个resttemplate,调用过程中反射修改超时时间,优点:比较高端,缺点:可能有多线程问题,需要充分测试,反射影响一点点性能

  • 方案3:使用OkHttpClient包装一层resttemplate,再使用OkHttpClient提供的拦截器,每次调用的时候拦截根据url修改超时时间,优点:优雅;使用RestTemplateInterceptor包装后,可以动态修改每个接口的超时时间。缺点:需要引用自己的resttemplate,autowire的地方需要修改。

dubbo接口超时方案

  • 利用自带的dubbot的timeount属性设置超时时间:dubbo的超时时间可以设置在生产者和消费者,并且消费者可以覆盖生产者的配置,所以我们只需要关心消费者的配置

     

  • 方法 > 接口 > 全局

  • 同级别下消费 > 生产

  • 不仅针对超时timeout属性,所有可配置属性都具备该优先级规则

  • 有个小坑需要注意,在@Reference上设置的超时时间可能出现无效的情况,当存在多个@Reference配置时,程序启动的时候,会根据加载顺序进行加载并覆盖之前的配置,所以要想得到正确的配置,需要所有引用接口的地方的超时时间设置一样

http超时设置代码

1. 配置RestTemplate的bean

import com.f4.ts.org.manager.constants.NumberConstant;
import com.f4.ts.org.manager.interceptor.RestTemplateInterceptor;
import okhttp3.ConnectionPool;
import okhttp3.OkHttpClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.OkHttp3ClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;import java.util.concurrent.TimeUnit;/*** restful风格模板配置** @author tengqy* @create 2022-07-04 8:33* @date 2022/07/05*/
@Configuration
public class RestTemplateConfig {/*** restful风格模板拦截器*/@Autowiredprivate RestTemplateInterceptor restTemplateInterceptor;/*** 企业restful风格模板** @return {@link RestTemplate}*/@Beanpublic RestTemplate enterpriseRestTemplate() {OkHttpClient.Builder builder = new OkHttpClient.Builder();builder.connectTimeout(NumberConstant.NUM_INT_1000, TimeUnit.MILLISECONDS).readTimeout(NumberConstant.NUM_INT_1000, TimeUnit.MILLISECONDS).writeTimeout(NumberConstant.NUM_INT_1000, TimeUnit.MILLISECONDS).connectionPool(new ConnectionPool(NumberConstant.NUM_INT_50,NumberConstant.NUM_INT_13, TimeUnit.MINUTES)).addInterceptor(restTemplateInterceptor);RestTemplate restTemplate = new RestTemplate(new OkHttp3ClientHttpRequestFactory(builder.build()));return restTemplate;}
}

2. 配置拦截器

import com.alibaba.fastjson.JSON;
import com.f4.ts.org.manager.config.TimeOutConfig;
import com.f4.ts.org.manager.constants.NumberConstant;
import com.f4.ts.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;import javax.annotation.PostConstruct;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;/*** restful风格模板拦截器** @author tengqy* @create 2022-07-04 8:35* @date 2022/07/05*/
@Component
@Slf4j
public class RestTemplateInterceptor implements Interceptor {/*** 时间配置*/@Autowiredprivate TimeOutConfig timeOutConfig;/*** 超时地图*/private static Map> timeoutMap = new ConcurrentHashMap<>();/*** 最后一次*/private long lastTime;/*** 全部url*/private static final String DEFAULT_URL = "*";/*** 初始化*/@PostConstructpublic void init() {lastTime = System.currentTimeMillis();String timeoutCof = timeOutConfig.getTimeoutCof();log.info("初始化http超时时间配置 {}", timeoutCof);if (StringUtils.isNotBlank(timeoutCof)) {String[] split = timeoutCof.split(";");for (String s : split) {String[] strings = s.split(",");String connectionTimeout = "2000";String readTimeout = "2000";String writeTimeout = "2000";if (strings.length == NumberConstant.NUM_INT_4) {connectionTimeout = strings[NumberConstant.NUM_INT_1];readTimeout = strings[NumberConstant.NUM_INT_2];writeTimeout = strings[NumberConstant.NUM_INT_3];}timeoutMap.put(strings[0], Arrays.asList(Integer.valueOf(connectionTimeout), Integer.valueOf(readTimeout),Integer.valueOf(writeTimeout)));}}timeoutMap.put(DEFAULT_URL, Arrays.asList(NumberConstant.NUM_INT_2000, NumberConstant.NUM_INT_2000, NumberConstant.NUM_INT_2000));log.info("初始化http超时时间配置结束 {}", JSON.toJSONString(timeoutMap));}/*** 拦截** @param chain 链* @return {@link Response}* @throws IOException ioexception*/@Overridepublic Response intercept(Chain chain) throws IOException {if (System.currentTimeMillis() - lastTime > (long) NumberConstant.NUMBER_600000) {init();lastTime = System.currentTimeMillis();}Request request = chain.request();String requestUrl = request.url().toString();for (Map.Entry> entry : timeoutMap.entrySet()) {if (requestUrl.endsWith(entry.getKey())) {return chain.withConnectTimeout(entry.getValue().get(NumberConstant.NUM_INT_0), TimeUnit.MILLISECONDS).withReadTimeout(entry.getValue().get(NumberConstant.NUM_INT_1), TimeUnit.MILLISECONDS).withWriteTimeout(entry.getValue().get(NumberConstant.NUM_INT_2), TimeUnit.MILLISECONDS).proceed(request);}}List defaultTime = timeoutMap.get(DEFAULT_URL);return chain.withConnectTimeout(defaultTime.get(NumberConstant.NUM_INT_0), TimeUnit.MILLISECONDS).withReadTimeout(defaultTime.get(NumberConstant.NUM_INT_1), TimeUnit.MILLISECONDS).withWriteTimeout(defaultTime.get(NumberConstant.NUM_INT_2), TimeUnit.MILLISECONDS).proceed(request);}
}

 3. 动态配置接口的超时时间,可以配置到配置中心等地方

import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;/*** 时间配置** @author tengqy* @create 2022-07-05 9:18* @date 2022/07/05*/
@Component
@Data
@ConfigurationProperties
public class TimeOutConfig {/*** 超时*/@Value("${http.timeout.conf:*,2000,2000,2000}")private String timeoutCof;/*** 得到超时** @return {@link String}*/public String getTimeoutCof() {return timeoutCof;}/*** 设置超时** @param timeoutCof 超时咖啡*/public void setTimeoutCof(String timeoutCof) {this.timeoutCof = timeoutCof;}
}

 超时时间配置如下

http:timeout:conf: url1;url2,1000,2000,2000

其中,如果不配置超时时间,则默认超时时间都是2s/2s/2s,否则配置了超时时间则按照

接口,a,b,c; 配置,其中a、b、c分别为建立连接超时时间、读超时时间、写超时时间

相关内容

热门资讯

埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...