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


    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

    1. import com.f4.ts.org.manager.constants.NumberConstant;
    2. import com.f4.ts.org.manager.interceptor.RestTemplateInterceptor;
    3. import okhttp3.ConnectionPool;
    4. import okhttp3.OkHttpClient;
    5. import org.springframework.beans.factory.annotation.Autowired;
    6. import org.springframework.context.annotation.Bean;
    7. import org.springframework.context.annotation.Configuration;
    8. import org.springframework.http.client.OkHttp3ClientHttpRequestFactory;
    9. import org.springframework.web.client.RestTemplate;
    10. import java.util.concurrent.TimeUnit;
    11. /**
    12. * restful风格模板配置
    13. *
    14. * @author tengqy
    15. * @create 2022-07-04 8:33
    16. * @date 2022/07/05
    17. */
    18. @Configuration
    19. public class RestTemplateConfig {
    20. /**
    21. * restful风格模板拦截器
    22. */
    23. @Autowired
    24. private RestTemplateInterceptor restTemplateInterceptor;
    25. /**
    26. * 企业restful风格模板
    27. *
    28. * @return {@link RestTemplate}
    29. */
    30. @Bean
    31. public RestTemplate enterpriseRestTemplate() {
    32. OkHttpClient.Builder builder = new OkHttpClient.Builder();
    33. builder.connectTimeout(NumberConstant.NUM_INT_1000, TimeUnit.MILLISECONDS).readTimeout(NumberConstant.NUM_INT_1000, TimeUnit.MILLISECONDS)
    34. .writeTimeout(NumberConstant.NUM_INT_1000, TimeUnit.MILLISECONDS)
    35. .connectionPool(new ConnectionPool(NumberConstant.NUM_INT_50,
    36. NumberConstant.NUM_INT_13, TimeUnit.MINUTES)).addInterceptor(restTemplateInterceptor);
    37. RestTemplate restTemplate = new RestTemplate(new OkHttp3ClientHttpRequestFactory(builder.build()));
    38. return restTemplate;
    39. }
    40. }

    2. 配置拦截器

    1. import com.alibaba.fastjson.JSON;
    2. import com.f4.ts.org.manager.config.TimeOutConfig;
    3. import com.f4.ts.org.manager.constants.NumberConstant;
    4. import com.f4.ts.utils.StringUtils;
    5. import lombok.extern.slf4j.Slf4j;
    6. import okhttp3.Interceptor;
    7. import okhttp3.Request;
    8. import okhttp3.Response;
    9. import org.springframework.beans.factory.annotation.Autowired;
    10. import org.springframework.stereotype.Component;
    11. import javax.annotation.PostConstruct;
    12. import java.io.IOException;
    13. import java.util.Arrays;
    14. import java.util.List;
    15. import java.util.Map;
    16. import java.util.concurrent.ConcurrentHashMap;
    17. import java.util.concurrent.TimeUnit;
    18. /**
    19. * restful风格模板拦截器
    20. *
    21. * @author tengqy
    22. * @create 2022-07-04 8:35
    23. * @date 2022/07/05
    24. */
    25. @Component
    26. @Slf4j
    27. public class RestTemplateInterceptor implements Interceptor {
    28. /**
    29. * 时间配置
    30. */
    31. @Autowired
    32. private TimeOutConfig timeOutConfig;
    33. /**
    34. * 超时地图
    35. */
    36. private static Map> timeoutMap = new ConcurrentHashMap<>();
    37. /**
    38. * 最后一次
    39. */
    40. private long lastTime;
    41. /**
    42. * 全部url
    43. */
    44. private static final String DEFAULT_URL = "*";
    45. /**
    46. * 初始化
    47. */
    48. @PostConstruct
    49. public void init() {
    50. lastTime = System.currentTimeMillis();
    51. String timeoutCof = timeOutConfig.getTimeoutCof();
    52. log.info("初始化http超时时间配置 {}", timeoutCof);
    53. if (StringUtils.isNotBlank(timeoutCof)) {
    54. String[] split = timeoutCof.split(";");
    55. for (String s : split) {
    56. String[] strings = s.split(",");
    57. String connectionTimeout = "2000";
    58. String readTimeout = "2000";
    59. String writeTimeout = "2000";
    60. if (strings.length == NumberConstant.NUM_INT_4) {
    61. connectionTimeout = strings[NumberConstant.NUM_INT_1];
    62. readTimeout = strings[NumberConstant.NUM_INT_2];
    63. writeTimeout = strings[NumberConstant.NUM_INT_3];
    64. }
    65. timeoutMap.put(strings[0], Arrays.asList(Integer.valueOf(connectionTimeout), Integer.valueOf(readTimeout),
    66. Integer.valueOf(writeTimeout)));
    67. }
    68. }
    69. timeoutMap.put(DEFAULT_URL, Arrays.asList(NumberConstant.NUM_INT_2000, NumberConstant.NUM_INT_2000, NumberConstant.NUM_INT_2000));
    70. log.info("初始化http超时时间配置结束 {}", JSON.toJSONString(timeoutMap));
    71. }
    72. /**
    73. * 拦截
    74. *
    75. * @param chain 链
    76. * @return {@link Response}
    77. * @throws IOException ioexception
    78. */
    79. @Override
    80. public Response intercept(Chain chain) throws IOException {
    81. if (System.currentTimeMillis() - lastTime > (long) NumberConstant.NUMBER_600000) {
    82. init();
    83. lastTime = System.currentTimeMillis();
    84. }
    85. Request request = chain.request();
    86. String requestUrl = request.url().toString();
    87. for (Map.Entry> entry : timeoutMap.entrySet()) {
    88. if (requestUrl.endsWith(entry.getKey())) {
    89. return chain.withConnectTimeout(entry.getValue().get(NumberConstant.NUM_INT_0), TimeUnit.MILLISECONDS)
    90. .withReadTimeout(entry.getValue().get(NumberConstant.NUM_INT_1), TimeUnit.MILLISECONDS)
    91. .withWriteTimeout(entry.getValue().get(NumberConstant.NUM_INT_2), TimeUnit.MILLISECONDS)
    92. .proceed(request);
    93. }
    94. }
    95. List defaultTime = timeoutMap.get(DEFAULT_URL);
    96. return chain.withConnectTimeout(defaultTime.get(NumberConstant.NUM_INT_0), TimeUnit.MILLISECONDS)
    97. .withReadTimeout(defaultTime.get(NumberConstant.NUM_INT_1), TimeUnit.MILLISECONDS)
    98. .withWriteTimeout(defaultTime.get(NumberConstant.NUM_INT_2), TimeUnit.MILLISECONDS)
    99. .proceed(request);
    100. }
    101. }

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

    1. import lombok.Data;
    2. import org.springframework.beans.factory.annotation.Value;
    3. import org.springframework.boot.context.properties.ConfigurationProperties;
    4. import org.springframework.stereotype.Component;
    5. /**
    6. * 时间配置
    7. *
    8. * @author tengqy
    9. * @create 2022-07-05 9:18
    10. * @date 2022/07/05
    11. */
    12. @Component
    13. @Data
    14. @ConfigurationProperties
    15. public class TimeOutConfig {
    16. /**
    17. * 超时
    18. */
    19. @Value("${http.timeout.conf:*,2000,2000,2000}")
    20. private String timeoutCof;
    21. /**
    22. * 得到超时
    23. *
    24. * @return {@link String}
    25. */
    26. public String getTimeoutCof() {
    27. return timeoutCof;
    28. }
    29. /**
    30. * 设置超时
    31. *
    32. * @param timeoutCof 超时咖啡
    33. */
    34. public void setTimeoutCof(String timeoutCof) {
    35. this.timeoutCof = timeoutCof;
    36. }
    37. }

     超时时间配置如下

    1. http:
    2. timeout:
    3. conf: url1;url2,1000,2000,2000

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

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

  • 相关阅读:
    STM32获取最大堆栈空间
    8.4 【MySQL】文件系统对数据库的影响
    分组后将成员拼成字符串
    html写一个table表
    浅谈Spring中的IOC和DI
    如何做gif动图?手把手教你在线制作动图
    算法-链表-合并两个升序链表
    java-php-python-基于ASP.NETMVC的苗木购销系统计算机毕业设计
    剑指offer专项突击版第29天
    深入理解JVM笔记
  • 原文地址:https://blog.csdn.net/starryninglong/article/details/128093551