SpringCloud:Feign調用接口不穩定問題以及如何設置超時


1. Feign調用接口不穩定報錯

 

Caused by: java.net.SocketException: Software caused connection abort: recv failed
    at java.net.SocketInputStream.socketRead0(Native Method)
    at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
    at java.net.SocketInputStream.read(SocketInputStream.java:170)
    at java.net.SocketInputStream.read(SocketInputStream.java:141)
    at org.apache.http.impl.io.SessionInputBufferImpl.streamRead(SessionInputBufferImpl.java:137)
    at org.apache.http.impl.io.SessionInputBufferImpl.fillBuffer(SessionInputBufferImpl.java:153)
    at org.apache.http.impl.io.SessionInputBufferImpl.readLine(SessionInputBufferImpl.java:282)
    at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:140)
    at org.apache.http.impl.conn.DefaultHttpResponseParser.parseHead(DefaultHttpResponseParser.java:57)
    at org.apache.http.impl.io.AbstractMessageParser.parse(AbstractMessageParser.java:259)
    at org.apache.http.impl.DefaultBHttpClientConnection.receiveResponseHeader(DefaultBHttpClientConnection.java:163)
    at org.apache.http.impl.conn.CPoolProxy.receiveResponseHeader(CPoolProxy.java:167)
    at org.apache.http.protocol.HttpRequestExecutor.doReceiveResponse(HttpRequestExecutor.java:273)
    at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:125)
    at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:271)
    at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:184)
    at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:88)
    at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)
    at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:107)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:55)
    at feign.httpclient.ApacheHttpClient.execute(ApacheHttpClient.java:87)
    at org.springframework.cloud.netflix.feign.ribbon.RetryableFeignLoadBalancer$1.doWithRetry(RetryableFeignLoadBalancer.java:92)
    at org.springframework.cloud.netflix.feign.ribbon.RetryableFeignLoadBalancer$1.doWithRetry(RetryableFeignLoadBalancer.java:77)
    at org.springframework.retry.support.RetryTemplate.doExecute(RetryTemplate.java:286)
    at org.springframework.retry.support.RetryTemplate.execute(RetryTemplate.java:163)
    at org.springframework.cloud.netflix.feign.ribbon.RetryableFeignLoadBalancer.execute(RetryableFeignLoadBalancer.java:77)
    at org.springframework.cloud.netflix.feign.ribbon.RetryableFeignLoadBalancer.execute(RetryableFeignLoadBalancer.java:48)
    at com.netflix.client.AbstractLoadBalancerAwareClient$1.call(AbstractLoadBalancerAwareClient.java:109)
    at com.netflix.loadbalancer.reactive.LoadBalancerCommand$3$1.call(LoadBalancerCommand.java:303)
    at com.netflix.loadbalancer.reactive.LoadBalancerCommand$3$1.call(LoadBalancerCommand.java:287)
    at rx.internal.util.ScalarSynchronousObservable$3.call(ScalarSynchronousObservable.java:231)
    at rx.internal.util.ScalarSynchronousObservable$3.call(ScalarSynchronousObservable.java:228)
    at rx.Observable.unsafeSubscribe(Observable.java:10211)
    at rx.internal.operators.OnSubscribeConcatMap$ConcatMapSubscriber.drain(OnSubscribeConcatMap.java:286)
    at rx.internal.operators.OnSubscribeConcatMap$ConcatMapSubscriber.onNext(OnSubscribeConcatMap.java:144)
    at com.netflix.loadbalancer.reactive.LoadBalancerCommand$1.call(LoadBalancerCommand.java:185)
    at com.netflix.loadbalancer.reactive.LoadBalancerCommand$1.call(LoadBalancerCommand.java:180)
    at rx.Observable.unsafeSubscribe(Observable.java:10211)
    at rx.internal.operators.OnSubscribeConcatMap.call(OnSubscribeConcatMap.java:94)
    at rx.internal.operators.OnSubscribeConcatMap.call(OnSubscribeConcatMap.java:42)
    at rx.Observable.unsafeSubscribe(Observable.java:10211)
    at rx.internal.operators.OperatorRetryWithPredicate$SourceSubscriber$1.call(OperatorRetryWithPredicate.java:127)
    at rx.internal.schedulers.TrampolineScheduler$InnerCurrentThreadScheduler.enqueue(TrampolineScheduler.java:73)
    at rx.internal.schedulers.TrampolineScheduler$InnerCurrentThreadScheduler.schedule(TrampolineScheduler.java:52)
    at rx.internal.operators.OperatorRetryWithPredicate$SourceSubscriber.onNext(OperatorRetryWithPredicate.java:79)
    at rx.internal.operators.OperatorRetryWithPredicate$SourceSubscriber.onNext(OperatorRetryWithPredicate.java:45)
    at rx.internal.util.ScalarSynchronousObservable$WeakSingleProducer.request(ScalarSynchronousObservable.java:276)
    at rx.Subscriber.setProducer(Subscriber.java:209)
    at rx.internal.util.ScalarSynchronousObservable$JustOnSubscribe.call(ScalarSynchronousObservable.java:138)
    at rx.internal.util.ScalarSynchronousObservable$JustOnSubscribe.call(ScalarSynchronousObservable.java:129)
    at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
    at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
    at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
    at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
    at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
    at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
    at rx.Observable.subscribe(Observable.java:10307)
    at rx.Observable.subscribe(Observable.java:10274)
    at rx.observables.BlockingObservable.blockForSingle(BlockingObservable.java:445)
    at rx.observables.BlockingObservable.single(BlockingObservable.java:342)
    at com.netflix.client.AbstractLoadBalancerAwareClient.executeWithLoadBalancer(AbstractLoadBalancerAwareClient.java:117)
    at org.springframework.cloud.netflix.feign.ribbon.LoadBalancerFeignClient.execute(LoadBalancerFeignClient.java:63)
    at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:97)
    ... 117 common frames omitted

 

feign在調用時,會有不穩定的情況出現,時而出現接口調不通。解決方案如下,復寫FeignRibbonClientAutoConfiguration中的HttpClient的配置。

 

解決辦法:

創建FeignRibbonHttpClientPoolConfig配置類。

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.impl.NoConnectionReuseStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.ssl.SSLContexts;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
 
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.security.KeyManagementException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
 
 
@Component
public class FeignRibbonHttpClientPoolConfig {
 
    private static final int POOL_MAX_TOTAL = 3000;
    private static final int DEFAULT_MAX_PER_ROUTE = 500;
 
    //validateAfterInactivity 空閑永久連接檢查間隔,這個牽扯的還比較多
    //官方推薦使用這個來檢查永久鏈接的可用性,而不推薦每次請求的時候才去檢查
    private static final int VALIDATE_AFTER_INACTIVITY = 1000;
 
    @Bean(name = "httpClient", destroyMethod = "close")
    CloseableHttpClient httpClient() throws KeyManagementException {
        return buildCloseableHttpClient();
    }
 
    /**
     * 構建HttpClient連接池
     *
     * @return
     * @throws KeyManagementException
     */
    public CloseableHttpClient buildCloseableHttpClient() throws KeyManagementException {
        SSLContext sslcontext = SSLContexts.createDefault();
        sslcontext.init(null, new TrustManager[]{new TrustAnyManager()}, null); //設置https客戶端信任萬能證書
        SSLConnectionSocketFactory ssf = new SSLConnectionSocketFactory(sslcontext, NoopHostnameVerifier.INSTANCE);
        //注冊請求方式,根據URL自動請求
        Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("http", PlainConnectionSocketFactory.INSTANCE)
                .register("https", ssf)
                .build();
        //創建Http連接池,單位時間內釋放已使用過連接池中的連接
        PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
        connectionManager.setMaxTotal(POOL_MAX_TOTAL);
        connectionManager.setDefaultMaxPerRoute(DEFAULT_MAX_PER_ROUTE);
        connectionManager.setValidateAfterInactivity(VALIDATE_AFTER_INACTIVITY);
 
        return HttpClients.custom()
                .setConnectionManager(connectionManager)
                .setConnectionReuseStrategy(NoConnectionReuseStrategy.INSTANCE)
                .build();
    }
 
    class TrustAnyManager implements X509TrustManager {
        public void checkClientTrusted(X509Certificate[] chain,
                                       String authType) throws CertificateException {
        }
 
        public void checkServerTrusted(X509Certificate[] chain,
                                       String authType) throws CertificateException {
        }
 
        public X509Certificate[] getAcceptedIssuers() {
            return new X509Certificate[]{};
        }
    }
}

 

2. Feign調用出現 connect  time  out 超時問題.

因為feign已經集成robbon,hystrix,調用在規定時間內達不到就會報上述錯誤,並且這個規定時間會很短

解決辦法:配置文件加入如下配置: 指的是在調用的一方

#連接超時和讀超時(以properties文件形式為例):

feign.client.config.springApplicationName.connectTimeout=60000.

feign.client.config.springApplicationName.readTimeout=60000.
#禁用Hystrix熔斷檢測(熔斷檢測默認是1秒)
feign.hystrix.enabled= false #spring.ApplicationName是服務提供方注冊到eureka上的應用名稱.

配置完成后,還需要配置Hystrix的熔斷時間,如果Hystrix時長小於feign的超時時長,那feign的超時設置就不會生效

#配置hystrix的熔斷時間
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds = 60000

 

或者

設置全局配置

 

#設置連接超時
ribbon.ConnectTimeout= 1000
#設置讀取超時
ribbon.ReadTimeout= 1000

 

指定服務配置

#設置針對my-plan服務的連接超時
my-plan.ribbon.ConnectTimeout= 10000
#設置針對my-plan服務的讀取超時
my-plan.ribbon.ReadTimeout= 10000
#設置針對my-plan服務所有操作請求都進行重試
my-plan.ribbon.OkToRetryOnAllOperations= true
#設置針對my-plan服務切換實例的重試次數
my-plan.ribbon.MaxAutoRetriesNextServer= 2
#設置針對my-plan服務的當前實例的重試次數
my-plan.ribbon.MaxAutoRetries= 1

 

文章轉載至:https://blog.csdn.net/flysun3344/article/details/81117403

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM