| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119 |
- package com.zsElectric.boot.config;
- import lombok.extern.slf4j.Slf4j;
- import okhttp3.ConnectionPool;
- import okhttp3.Interceptor;
- import okhttp3.OkHttpClient;
- import okhttp3.Request;
- import okhttp3.Response;
- import org.springframework.beans.factory.annotation.Value;
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
- import java.io.IOException;
- import java.net.SocketTimeoutException;
- import java.time.Duration;
- import java.util.concurrent.TimeUnit;
- @Slf4j
- @Configuration
- public class OkHttpConfig {
-
- @Value("${okhttp.connect-timeout:30}")
- private Duration connectTimeout;
-
- @Value("${okhttp.read-timeout:120}")
- private Duration readTimeout;
-
- @Value("${okhttp.write-timeout:60}")
- private Duration writeTimeout;
-
- @Value("${okhttp.retry-on-connection-failure:true}")
- private boolean retryOnConnectionFailure;
-
- @Value("${okhttp.connection-pool.max-idle-connections:200}")
- private int maxIdleConnections;
-
- @Value("${okhttp.connection-pool.keep-alive-duration:300}")
- private Duration keepAliveDuration;
-
- @Value("${okhttp.max-retry-count:2}")
- private int maxRetryCount;
- @Bean
- public ConnectionPool connectionPool() {
- return new ConnectionPool(maxIdleConnections, keepAliveDuration.toMillis(), TimeUnit.MILLISECONDS);
- }
- @Bean
- public OkHttpClient okHttpClient(ConnectionPool connectionPool) {
- return new OkHttpClient.Builder()
- .connectTimeout(connectTimeout)
- .readTimeout(readTimeout)
- .writeTimeout(writeTimeout)
- .retryOnConnectionFailure(retryOnConnectionFailure)
- .connectionPool(connectionPool)
- .addInterceptor(retryInterceptor())
- .build();
- }
-
- /**
- * 重试拦截器
- */
- private Interceptor retryInterceptor() {
- return chain -> {
- Request request = chain.request();
- Response response = null;
- IOException lastException = null;
-
- for (int i = 0; i <= maxRetryCount; i++) {
- try {
- if (i > 0) {
- log.warn("第 {} 次重试请求: {}", i, request.url());
- // 重试前等待一段时间,使用指数退避策略
- // 第1次重试等待2秒,第2次等待4秒
- long waitTime = (long) Math.pow(2, i) * 1000;
- log.info("重试前等待 {} 毫秒", waitTime);
- Thread.sleep(waitTime);
- }
- response = chain.proceed(request);
- // 如果响应成功,直接返回
- if (response.isSuccessful()) {
- if (i > 0) {
- log.info("第 {} 次重试成功: {}", i, request.url());
- }
- return response;
- }
- // 如果是客户端错误(4xx),不重试
- if (response.code() >= 400 && response.code() < 500) {
- log.warn("客户端错误,不重试: {}, 状态码: {}", request.url(), response.code());
- return response;
- }
- } catch (SocketTimeoutException e) {
- lastException = e;
- log.error("请求超时: {}, 第 {} 次尝试", request.url(), i + 1, e);
- if (response != null) {
- response.close();
- }
- } catch (IOException e) {
- lastException = e;
- log.error("请求失败: {}, 第 {} 次尝试", request.url(), i + 1, e);
- if (response != null) {
- response.close();
- }
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- throw new IOException("重试被中断", e);
- }
- }
-
- // 所有重试都失败了
- if (lastException != null) {
- log.error("所有重试都失败了: {}, 总共尝试 {} 次", request.url(), maxRetryCount + 1);
- throw lastException;
- }
-
- return response;
- };
- }
- }
|