当前位置: 首页 > news >正文

解决kubernetes中微服务pod之间调用失败报错connection refused的问题

现象:

 

从这里可以看到是当前服务在调用product service服务是出现了连接拒绝connection refused

走读一下原始代码:

可以看到请求是由FeignClient代理发出的 ,但问题在于为什么Feign请求的时候会产生connection refused错误?

上面的日志又没有给出详细信息。我们需要看到feign请求网址的完整信息。

解决办法:新建一个配置类

import feign.Logger; import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

@Configuration public class FeignConfig {

         @Bean

           Logger.Level feignLoggerLevel() {

           return Logger.Level.FULL; // 设置Feign日志级别为FULL

    }

}

然后把这个配置类写到@FeignClient注解里的configration里面

@FeignClient(name = "your-service", configuration = FeignConfig.class)

public interface YourServiceClient { // Feign客户端的方法定义 }

这样配置后,Feign将以Full日志级别打印详细的HTTP请求和响应信息,包括完整的URL

因为我的@FeignClient注解里面的configration里面已经有配置类了,所以我把上面的那个bean直接追加到那个配置类里面:

然后再来查看日志果然发现:feign请求的地址有问题:竟然请求到当前自身ip 127.0.0.1了,

难怪会连接拒绝。

 2023-11-21 02:14:07.336  INFO 1 --- [oduct-service-1] c.n.l.DynamicServerListLoadBalancer      : DynamicServerListLoadBalancer for client product-service initialized: DynamicServerListLoadBalancer:{NFLoadBalancer:name=product-service,current list of Servers=[127.0.0.1:8081],Load balancer stats=Zone stats: {defaultzone=[Zone:defaultzone;  Instance count:1;       Active connections count: 0;      Circuit breaker tripped count: 0;       Active connections per server: 0.0;]
},Server stats: [[Server:127.0.0.1:8081;        Zone:defaultZone;       Total Requests:0;       Successive connection failure:0;  Total blackout seconds:0;       Last connection made:Thu Jan 01 00:00:00 GMT 1970;      First connection made: Thu Jan 01 00:00:00 GMT 1970;      Active Connections:0;   total failure count in last (1000) msecs:0;     average resp time:0.0;    90 percentile resp time:0.0;    95 percentile resp time:0.0;    min resp time:0.0;      max resp time:0.0;      stddev resp time:0.0] 

看了一下springboot配置文件

原来是ip-address设置在作怪,因为它主动上报eureka自身的ip地址为127.0.0.1, 那其他服务调用该服务时从eureka拿到的地址就会是127.0.0.1, 从而向自身发起调用,这样必须会产生连接拒绝错误(因为你本来就是跨服务调用,自身怎么会有你需要的服务)

注意: 不要手动设置ip-address,而应该让Eureka自动获取。这样,服务将以实际的网络地址注册到Eureka,Feign在调用时将获得正确的服务地址

然后去掉这个ip-address配置以后,仍然报错:java.net.UnknownHostException: product-service-deploy-674d77cffd-4rj4m

 2023-11-21 04:57:26.847 ERROR 1 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in co  ntext with path [] threw exception [Request processing failed; nested exception is com.netflix.hystrix.exception.HystrixRuntimeException: ProductService  Api#findProductsByCategory(Integer) failed and no fallback available.] with root cause
java.net.UnknownHostException: product-service-deploy-674d77cffd-4rj4m

这回看起来feign请求的时候没有请求ip , 但是解析到k8s的pod ip了。

为什么会这样?

使用下面的api查看一下product-service在eureka中注册的详细信息:

${eureka-IP}:port/eukeka/apps/${server-name}

 像下面这样: 这里可以很清晰的看到produc-service在eureka中的详细信息,

特别是hostName和ipAddr, 从上面的情况来看,应该是eureka返回给服务调用方的是被调用服务的hostName而不是ip

 然后同时测试一下服务需求方是否能正常从k8s的内网ip ping通被调用服务,也就是测试服务之间的网络连通性。

 可以看到两个服务之间网络联通正常,然后从下图可以看到在宿主机上也可以通过内网ip和端口访问到该服务。

问题还是出现在eureka在springboot的配置中

eureka的client注册到server时默认是使用hostname而不是ip,这就导致client在多台机器时,服务间相互调用时也会使用hostname进行调用,从而调用失败。

 为解决这个问题,eureka必须配置prefer-ip-address: true, 要求优先使用ip地址向eureka注册。

那么最后调用方从eureka拿到的就是ip地址了而不是hostname.

为什么会这样?因为eureka源码就是这样定义的(EurekaInstanceConfigBean.class),如下所示

但是发现加了prefer-ip-address以后,feign日志获取的还是pod id不是容器的ip地址。

这里需要特别注意:pod拉取镜像的默认策略是:如果本地已经有镜像,那么就不会从仓库拉取新镜像! 这是新配置不能生效的关键原因!

所以你必须要么临时改变镜像拉取的策略改成始终拉取镜像,要么删除旧的镜像

删除旧的docker镜像,加上prefer-ip-address以后,再通过eureka api查询上述服务的信息,发现之前的hostName也变成了ip地址:

把上面的prefer-ip-address: true配置加上去以后,以为问题解决了, 但是又报错如下:

 大概意思请求失败,没有fallback降级服务,但是我明明有写降级服务啊:

后来发现原来是application没有配置熔断降级,加上去就可以了:

feign:hystrix:enabled: true #启用熔断降级

 最后问题终于解决,没再报错了。

总结一下解决办法:

1. springboot eureka配置中不要手动设置ip-address,此配置必须去掉!

2. springboot eureka必须配置prefer-ip-address: true

3.  当feign调用报错信息不明时,应设置Feign日志级别为FULL,查看详细的服务调用信息,包括请求url等,这样有利于诊断故障

相关文章:

  • Nginx(资源压缩)
  • 人工智能 -- 神经网络
  • 【React】打包优化-配置CDN
  • echart一键生成迁徙图
  • 了解FastSam:一个通用分割模型(草记)
  • Qt5.15.2静态编译 VS2017 with static OpenSSL
  • 存算一体还是存算分离?谈谈数据库基础设施的架构选择
  • 2023.11.22 数据仓库2-维度建模
  • Centos 7 离线安装(tar) NodeJS 16 和 Vue
  • docker启动容器失败,然后查看日志,docker logs查看容器出现报错:
  • 面试问题--智能指针
  • U盘报错无法访问文件或目录损坏且无法读取的解决办法
  • Proteus仿真--高仿真数码管电子钟
  • 了解JSX
  • vue升级题
  • CSS选择器——伪元素选择器之处理父元素高度及外边距溢出
  • DataBase in Android
  • in typeof instanceof ===这些运算符有什么作用
  • NSTimer学习笔记
  • PHP 小技巧
  • Sublime Text 2/3 绑定Eclipse快捷键
  • vagrant 添加本地 box 安装 laravel homestead
  • 机器人定位导航技术 激光SLAM与视觉SLAM谁更胜一筹?
  • 利用DataURL技术在网页上显示图片
  • 前端面试总结(at, md)
  • 使用Swoole加速Laravel(正式环境中)
  • 通过git安装npm私有模块
  • 网络应用优化——时延与带宽
  • 容器镜像
  • 小白应该如何快速入门阿里云服务器,新手使用ECS的方法 ...
  • ​Base64转换成图片,android studio build乱码,找不到okio.ByteString接腾讯人脸识别
  • ​VRRP 虚拟路由冗余协议(华为)
  • # MySQL server 层和存储引擎层是怎么交互数据的?
  • # 手柄编程_北通阿修罗3动手评:一款兼具功能、操控性的电竞手柄
  • #QT(智能家居界面-界面切换)
  • (01)ORB-SLAM2源码无死角解析-(66) BA优化(g2o)→闭环线程:Optimizer::GlobalBundleAdjustemnt→全局优化
  • (2)(2.10) LTM telemetry
  • (2020)Java后端开发----(面试题和笔试题)
  • (板子)A* astar算法,AcWing第k短路+八数码 带注释
  • (动态规划)5. 最长回文子串 java解决
  • (分类)KNN算法- 参数调优
  • (强烈推荐)移动端音视频从零到上手(下)
  • (太强大了) - Linux 性能监控、测试、优化工具
  • (转)如何上传第三方jar包至Maven私服让maven项目可以使用第三方jar包
  • .“空心村”成因分析及解决对策122344
  • .cn根服务器被攻击之后
  • .Net 6.0 处理跨域的方式
  • .net core 6 使用注解自动注入实例,无需构造注入 autowrite4net
  • .net 程序 换成 java,NET程序员如何转行为J2EE之java基础上(9)
  • [ C++ ] STL---string类的使用指南
  • [2019/05/17]解决springboot测试List接口时JSON传参异常
  • [AIGC] Spring Interceptor 拦截器详解
  • [C++]C++入门--引用
  • [CTF]2022美团CTF WEB WP
  • [Flutter]设置应用包名、名称、版本号、最低支持版本、Icon、启动页以及环境判断、平台判断和打包