解决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的配置。代码如下:

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[]{};
    }
  }
}

补充知识:springcloud之FeignClient访问微服务接口缓慢

昨天开发FeignClient,想调用微服务。逻辑是A服务调用B服务。AB在同一个局域网内。

经过反复测试,有一个访问缓慢的现象,具体表现为:

程序启动第一次访问初始化1.2秒左右,还可以理解。

但后面访问还是要1.1秒左右(格式化到SSS毫秒打印日志监控的)。

但如果连续访问几次,后面几次又是几十毫秒。过一会再访问,或者换浏览器换post工具请求,又会1.2秒左右。

当时就有点懵逼,这么成熟的工具不可能会这么慢吧,都是一个局域网。

排查了eureka注册中心,发现B服务多注册了一个,IP地址是192开头,经过询问,是一个同事的笔记本连接wifi,wifi自动分配了192开头的ip,笔记本是可以访问注册中心和其他服务的。但其他服务是访问不了这台笔记本的。

也就是说,B服务的一个注册的网络和其他服务是不通的。

但不知道为什么eureka却认为192ip注册是一个正确的微服务,而且一直是UP状态。注册中心的ip肯定是访问不了笔记本192ip的。

手工访问了一下192ip,不会直接提示404或网络错误,而是会加载一会。

这也许导致了FeignClient认为192ip是一台可用的机器。所以第一次请求的时候就去请求192ip,但没返回,到了超时时间,再换B服务的其他地址,就导致了耗时。

让同事把服务停了,再次调用服务,速度就很快了。

总结:个别机器IP不通,会导致FeignClient调用微服务缓慢。而且在eureka中心中是UP状态,没有错误提示。

需要注意网络互通情况。

以上这篇解决feign调用接口不稳定的问题就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • Spring-cloud-eureka使用feign调用服务接口

    Spring-cloud-eureka使用feign调用服务接口的具体方法,供大家参考,具体内容如下 基于spring-boot 2.0以上版本完成的微服务架构 pom.xml <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.5.RELEASE<

  • SpringBoot如何使用feign实现远程接口调用和错误熔断

    这篇文章主要介绍了SpringBoot如何使用feign实现远程接口调用和错误熔断,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 1.第一步,新建两个简单的springboot项目并创建rest接口 demo系统的rest接口 plus系统的调用接口 2.在项目pom文件里导入feign和hystrix的pom依赖包 <properties> <java.version>1.8</java.version> <s

  • 解决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.SocketIn

  • Feign调用接口解决处理内部异常的问题

    问题描述: 当使用feign调用接口,出现400-500-的接口问题时.会出错feign:FeignException.(因为是错误,只能用catch Throwable,不可使用catch Exception捕获异常)导致程序无法继续运行. 问题原因: 由于feign默认的错误处理类是FunFeignFallback会throw new AfsBaseExceptio导致外部无法捕获异常. package com.ruicar.afs.cloud.common.core.feign; impo

  • 使用feign调用接口时调不到get方法的问题及解决

    目录 feign调用接口调不到get方法 feign调用拿不到数据 feign调用接口调不到get方法 记录今天在使用springcloud的feign调用接口时踩的坑. 调用的方法是get方法时调用不到接口的问题 1.feign调用时默认的请求方式是post请求,所以如果是要调用的请求为get请求,并且有参数传递时的解决方法: (1)在调用的接口上需要给参数添加@RequestParam注解 @RequestMapping(value = "/cust-archives", meth

  • 解决Feign调用的GET参数传递的问题

    目录 需求 思考 GET方式请求① GET方式请求② GET方式请求③ 需求 ​ 在消费方服务通过GET方式,访问服务提供方的接口,需要传递多参数,拆分成多个参数的方式访问,不太适合用在该场景,需要改造成合适的方式调用服务方的接口 思考 拆分成多个参数时,若GET请求的参数超过3个及以上时,便不适用该种方式请求服务,因为这样传递参数过于臃肿,可读性也比较差: 若改造成POST请求的方式,虽然解决参数过多的问题,但是也带来了其他的开销,参数被放到了body里面,然后请求到服务方提供的接口,服务方的

  • 微服务之间如何通过feign调用接口上传文件

    具体需求: 我们的项目是基于springboot框架的springcloud微服务搭建的,后端服务技术层面整体上分为business服务和core服务,business服务用于作为应用层,直接连接客户端,通常用于聚合数据,core服务用来客户端具体操作不同需求来控制数据库,文件上传是通过客户端上传接口,通过business服务,由服务端调用feign接口,也是第一次做这种文件中转,遇到各种问题,下面是我自己的解决方案,不喜勿喷,代码小白一枚; 一.core服务层接口@requestmapping

  • 解决feign接口返回泛型设置属性为null的问题

    简介 feign是一种声明式http请求调用方式,工作原理就是根据FeignClient注解生成新的接口(也就是传说中的动态代理),常见使用方式如下所示: @FeignClient(name="UserFeignService",url="${auth.url}", fallbackFactory = OrgFeignServiceFallback.class, configuration = FeignErrorDecoderConfiguration.class

  • 使用Feign设置Token鉴权调用接口

    目录 Feign设置Token鉴权调用接口 声明FeignClient指定url 调用测试 返回对象可以封装demo 先去implementsRequestInterceptor重写apply方法 配置拦截器 Feign调用进行Token鉴权 项目场景 解决办法 具体实现 注意有Bug!!! Feign设置Token鉴权调用接口 声明FeignClient 指定url /**  * CREATE BY songzhongjin ON 2021.05.08 15:58 星期六  * DESC:fe

  • 解决微服务feign调用添加token的问题

    微服务feign调用添加token 1.一般情况是这么配置的 具体的怎么调用就不说了 如下配置,就可以在请求头中添加需要的请求头信息. package localdate; import feign.RequestInterceptor; import feign.RequestTemplate; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; imp

  • springcloud本地调试feign调用出现的诡异404问题及解决

    目录 本地调试feign调用出现的诡异404问题 问题产生 技术框架 核心代码 诡异的404 心态 springcloud在本地调试的踩坑记录 1.在本地调试的时候 2.修改配置文件中关于eureka的配置 3.还是关于eureka的配置 本地调试feign调用出现的诡异404问题 问题产生 最近在给公司准备做分布式事务框架seata的调研,准备搭建一套demo,根据阿里云官网的案例,我准备搭建一套微服务架子,分别含有business.order.storage三个微服务组成,其中第一个微服务实

随机推荐