现象:
从这里可以看到是当前服务在调用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)
这样配置后,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中注册的详细信息:
像下面这样: 这里可以很清晰的看到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等,这样有利于诊断故障
原文地址:https://blog.csdn.net/jiaohuizhuang6019/article/details/134523858
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.7code.cn/show_5567.html
如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除!