HttpClient、OKhttp、RestTemplate选择

1.对外部第三方服务调用,使用RestTemplate最为方便快捷

@Slf4j
@Configuration
public class RestTemplateConfig {
    //最大连接数
    @Value("${RestTemplateHttp.maxTotal:200}")
    private Integer maxTotal;

    //并发数
    @Value("${RestTemplateHttp.defaultMaxPerRoute:200}")
    private Integer defaultMaxPerRoute;

    //创建连接的最长时间
    @Value("${RestTemplateHttp.connectTimeout:15000}")
    private Integer connectTimeout;

    //从连接池中获取到连接的最长时间
    @Value("${RestTemplateHttp.connectionRequestTimeout:30000}")
    private Integer connectionRequestTimeout;

    //数据传输的最长时间
    @Value("${RestTemplateHttp.socketTimeout:30000}")
    private Integer socketTimeout;

    //可用空闲连接过期时间,重用空闲连接时会先检查是否空闲时间超过这个时间,如果超过,释放socket重新建立
    @Value("${RestTemplateHttp.validateAfterInactivity:10000}")
    private Integer validateAfterInactivity;

    @Autowired
    private TokenRequestInterceptor requestInterceptor;

    @Bean
    @Primary
    public RestTemplate restTemplate() {
        return  new RestTemplate(httpRequestFactory());
    }

    /**
     * 只用于 {@link BaseClientApi}
     * @return
     */
    @Bean("baseApiRestTemplate")
    public RestTemplate baseApiRestTemplate() {
        RestTemplate restTemplate = new RestTemplate(httpRequestFactory());
        restTemplate.setInterceptors(Arrays.asList(requestInterceptor));
      /*  //换上fastjson
        List> messageConverters= restTemplate.getMessageConverters();
        Iterator> iterator=messageConverters.iterator();
        while(iterator.hasNext()){
            HttpMessageConverter converter=iterator.next();
            //原有的String是ISO-8859-1编码 去掉
            if(converter instanceof StringHttpMessageConverter){
                iterator.remove();
            }
            //由于系统中默认有jackson 在转换json时自动会启用  但是我们不想使用它 可以直接移除
            if(converter instanceof GsonHttpMessageConverter || converter instanceof MappingJackson2HttpMessageConverter){
                iterator.remove();
            }
        }
        messageConverters.add(new StringHttpMessageConverter(Charset.forName("utf-8")));
        FastJsonHttpMessageConverter fastJsonHttpMessageConverter = new FastJsonHttpMessageConverter();
        List mediaTypes = new ArrayList<>(16);
        mediaTypes.add(MediaType.APPLICATION_JSON);
        mediaTypes.add(MediaType.APPLICATION_ATOM_XML);
        mediaTypes.add(MediaType.APPLICATION_FORM_URLENCODED);
        mediaTypes.add(MediaType.APPLICATION_OCTET_STREAM);
        fastJsonHttpMessageConverter.setSupportedMediaTypes(mediaTypes);
        FastJsonConfig fastJsonConfig = new FastJsonConfig();
        fastJsonConfig.setSerializerFeatures(
                SerializerFeature.QuoteFieldNames,
                SerializerFeature.WriteMapNullValue,
                SerializerFeature.WriteNullListAsEmpty,
                SerializerFeature.WriteNullNumberAsZero,
                SerializerFeature.WriteNullBooleanAsFalse,
                SerializerFeature.WriteNullStringAsEmpty,
                SerializerFeature.BrowserCompatible,
                SerializerFeature.BrowserCompatible,
                SerializerFeature.WriteSlashAsSpecial,
                SerializerFeature.WriteDateUseDateFormat,
                SerializerFeature.DisableCircularReferenceDetect);
        fastJsonHttpMessageConverter.setFastJsonConfig(fastJsonConfig);
        messageConverters.add(fastJsonHttpMessageConverter);*/
        return restTemplate;
    }

    @Bean
    public ClientHttpRequestFactory httpRequestFactory() {
        return new HttpComponentsClientHttpRequestFactory(httpClient());
    }

    @Bean
    public HttpClient httpClient() {
        Registry registry = RegistryBuilder.create()
                .register("http", PlainConnectionSocketFactory.getSocketFactory())
                .register("https", SSLConnectionSocketFactory.getSocketFactory())
                .build();
        PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry);
        connectionManager.setMaxTotal(maxTotal); // 最大连接数
        connectionManager.setDefaultMaxPerRoute(defaultMaxPerRoute);    //单个路由最大连接数
        connectionManager.setValidateAfterInactivity(validateAfterInactivity); // 最大空间时间
        RequestConfig requestConfig = RequestConfig.custom()
                .setSocketTimeout(socketTimeout)        //服务器返回数据(response)的时间,超过抛出read timeout
                .setConnectTimeout(connectTimeout)      //连接上服务器(握手成功)的时间,超出抛出connect timeout
                .setConnectionRequestTimeout(connectionRequestTimeout)//从连接池中获取连接的超时时间,超时间未拿到可用连接,会抛出org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool
                .build();
        return HttpClientBuilder.create()
                .setRetryHandler((exception, executionCount, context) -> {
                    if (executionCount > 3) {
                        log.warn("Maximum tries reached for client http pool ");
                        return false;
                    }
                    if (exception instanceof NoHttpResponseException     //NoHttpResponseException 重试
                            || exception instanceof ConnectTimeoutException //连接超时重试
              || exception instanceof SocketTimeoutException    //响应超时不重试,避免造成业务数据不一致
                    ) {
                        log.warn("NoHttpResponseException on " + executionCount + " call");
                        return true;
                    }
                    return false;
                })
                .setDefaultRequestConfig(requestConfig)
                .setConnectionManager(connectionManager)
                .build();
    }

}

2.对微服务之间使用fegin接口调用,使用OKhttp代替HttpClient,OKhttp可以灵活设置长链接的超时时间等参数

@Configuration
@ConditionalOnClass(Feign.class)
@AutoConfigureBefore(FeignAutoConfiguration.class)
public class FeignOkHttpConfig {

    @Value("${httpclient.connect-timeout-seconds: 1}")
    private int connectTimeoutSeconds;

    @Value("${httpclient.read-timeout-seconds: 1}")
    private int readTimeoutSeconds;

    @Value("${httpclient.write-timeout-seconds: 1}")
    private int writeTimeoutSeconds;

    @Value("${httpclient.connection-pool.max-idle: 100}")
    private int maxIdle;;

    @Value("${httpclient.connection-pool.keep-alive-duration-seconds: 300}")
    private int keepAliveDurationSeconds;;

    @Bean
    public okhttp3.OkHttpClient okHttpClient() {
        return new okhttp3.OkHttpClient.Builder()
                .readTimeout(readTimeoutSeconds, TimeUnit.SECONDS)
                .connectTimeout(connectTimeoutSeconds, TimeUnit.SECONDS)
                .writeTimeout(writeTimeoutSeconds, TimeUnit.SECONDS)
                .connectionPool(new ConnectionPool(maxIdle, keepAliveDurationSeconds, TimeUnit.SECONDS))
                .build();
    }

}

你可能感兴趣的:(java,网络)