zoukankan      html  css  js  c++  java
  • restTemplate踩过的坑-spring clound

    现在公司项目基本都从臃肿的项目转换成微服务的方向转换,因此也从中使用了spring clound的一些组件,在此过程中就遇到了restTemplate的坑。

    起初,是直接注入RestTemplate,后来则不断的遇到错误日志无法请求,出现异常。

    异常信息:

    org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.IllegalStateException: No instances available for IP
    意思是说url必须是服务的名称,猜测应该是涉及到eureka,直接用ip跟url调用是直接报错的。

    因此不适用默认的,直接重新自定义,则引用了原有的注入修改一下。

    /**
     * 
     * 功能描述:
     * 
     * @作者 jimw 创建时间:2018-04
     *
     */
    @Configuration
    public class RestTemplateConfig {
    
    	public RestTemplate restTemplate() {
    		return new RestTemplate(getClientHttpRequestFactory());
    	}
    
    	/**
    	 * 配置HttpClient超时时间
    	 * 
    	 * @return
    	 */
    	private ClientHttpRequestFactory getClientHttpRequestFactory() {
    		RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(HTTP_SOCKET_TIMEOUT)
    				.setConnectTimeout(HTTP_CONNECT_TIMEOUT).build();
    		CloseableHttpClient client = HttpClientBuilder.create().setDefaultRequestConfig(requestConfig).build();
    		return new HttpComponentsClientHttpRequestFactory(client);
    	}
    
    	/** http请求socket连接超时时间,毫秒为单位 */
    	public static final int HTTP_SOCKET_TIMEOUT = 15000;
    
    	/** http请求连接超时时间,毫秒为单位 */
    	public static final int HTTP_CONNECT_TIMEOUT = 15000;
    }
    

      

    当配置了这个之后,服务正常了。观察了一段时间,发现在并发的高峰期,开多几个服务器负载,也会存在服务出现请求非常慢,导致接口出现阻塞的情况出现,经过分析

    1、出现阻塞的原因是因为高峰并发的时候,出现请求的链接数很大

    因此找了源码,发现是因为restTemplate的默认配置值小于请求的链接数,而且路由并发也是默认为5的,因为微服务之间的逻辑处理中也有一定的时间。出现大规模阻塞的坑就这么踩到了。 

     

    对代码改造一下,配置最大链接数,路由并发数,这个restTemplate的坑就这么解决了。

    package com.jingbei.guess.config.web;
    
    import java.security.KeyManagementException;
    import java.security.KeyStoreException;
    import java.security.NoSuchAlgorithmException;
    import java.security.cert.CertificateException;
    import java.security.cert.X509Certificate;
    
    import javax.net.ssl.HostnameVerifier;
    import javax.net.ssl.SSLContext;
    
    import org.apache.http.client.HttpClient;
    import org.apache.http.config.Registry;
    import org.apache.http.config.RegistryBuilder;
    import org.apache.http.conn.socket.ConnectionSocketFactory;
    import org.apache.http.conn.socket.PlainConnectionSocketFactory;
    import org.apache.http.conn.ssl.NoopHostnameVerifier;
    import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
    import org.apache.http.conn.ssl.SSLContextBuilder;
    import org.apache.http.conn.ssl.TrustStrategy;
    import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
    import org.apache.http.impl.client.HttpClientBuilder;
    import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
    import org.springframework.web.client.DefaultResponseErrorHandler;
    import org.springframework.web.client.RestTemplate;
    
    import lombok.extern.slf4j.Slf4j;
    
    /**
     * 
     * 功能描述:
     * 
     * @作者 jimw 创建时间: 2018-04
     *
     */
    @Slf4j
    @Configuration
    public class RestTemplateConfig {
    	@Bean
    	public RestTemplate restTemplate() {
    		RestTemplate restTemplate = new RestTemplate();
    		restTemplate.setRequestFactory(clientHttpRequestFactory());
    		restTemplate.setErrorHandler(new DefaultResponseErrorHandler());
    		return restTemplate;
    	}
    
    	@Bean
    	public HttpComponentsClientHttpRequestFactory clientHttpRequestFactory() {
    		try {
    			HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
    			SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
    				public boolean isTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
    					return true;
    				}
    			}).build();
    			httpClientBuilder.setSSLContext(sslContext);
    			HostnameVerifier hostnameVerifier = NoopHostnameVerifier.INSTANCE;
    			SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext,
    					hostnameVerifier);
    			Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
    					.register("http", PlainConnectionSocketFactory.getSocketFactory())
    					.register("https", sslConnectionSocketFactory).build();// 注册http和https请求
    			// 开始设置连接池
    			PoolingHttpClientConnectionManager poolingHttpClientConnectionManager = new PoolingHttpClientConnectionManager(
    					socketFactoryRegistry);
    			poolingHttpClientConnectionManager.setMaxTotal(2700); // 最大连接数2700
    			poolingHttpClientConnectionManager.setDefaultMaxPerRoute(100); // 同路由并发数100
    			httpClientBuilder.setConnectionManager(poolingHttpClientConnectionManager);
    			httpClientBuilder.setRetryHandler(new DefaultHttpRequestRetryHandler(3, true)); // 重试次数
    			HttpClient httpClient = httpClientBuilder.build();
    			HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory(
    					httpClient); // httpClient连接配置
    			clientHttpRequestFactory.setConnectTimeout(20000); // 连接超时
    			clientHttpRequestFactory.setReadTimeout(30000); // 数据读取超时时间
    			clientHttpRequestFactory.setConnectionRequestTimeout(20000); // 连接不够用的等待时间
    			return clientHttpRequestFactory;
    		} catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException e) {
    			log.error("初始化HTTP连接池出错", e);
    		}
    		return null;
    	}
    
    }
    

      在对应的插件中配置即可

    依赖包:

    <dependency>

    <groupId>org.apache.httpcomponents</groupId>

    <artifactId>httpclient</artifactId>

    <version>4.5.3</version>

    </dependency>

    <dependency>

    <groupId>org.apache.httpcomponents</groupId>

    <artifactId>httpcore</artifactId>

    <version>4.4.9</version>

    </dependency>

     

  • 相关阅读:
    jquery ajax 显示服务器时钟
    盒子阴影
    排版问题,div nav 里面包含的内容没有在其范围内
    jquery点击向右,点击向左
    juqery 点击显示点击隐藏,slideDown slideUp slideToggle
    css强制换行
    jquery动画
    R17下maps新增参数的问题
    现阶段github上的emysql编译无法通过的问题
    之前数据库读写模型的实现
  • 原文地址:https://www.cnblogs.com/jimw/p/9037542.html
Copyright © 2011-2022 走看看