http和dubbo接口调用主动设置超时时间

8 篇文章 0 订阅
4 篇文章 0 订阅

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风格模板拦截器
     */
    @Autowired
    private RestTemplateInterceptor restTemplateInterceptor;

    /**
     * 企业restful风格模板
     *
     * @return {@link RestTemplate}
     */
    @Bean
    public 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 {
    /**
     * 时间配置
     */
    @Autowired
    private TimeOutConfig timeOutConfig;


    /**
     * 超时地图
     */
    private static Map<String, List<Integer>> timeoutMap = new ConcurrentHashMap<>();

    /**
     * 最后一次
     */
    private long lastTime;


    /**
     * 全部url
     */
    private static final String DEFAULT_URL = "*";

    /**
     * 初始化
     */
    @PostConstruct
    public 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
     */
    @Override
    public 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<String, List<Integer>> 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<Integer> 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分别为建立连接超时时间、读超时时间、写超时时间

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值