Feign远程调用失败问题

今天在调试代码的时候遇到了一个远程调用失败的问题,用Feign调用服务名时,无法从服务名解析成对应的URL。FeignClient接口如下:

@FeignClient("blogservice")
public interface BlogClient {

    @RequestMapping("/category/getCategoryListTest")
    List<CategoryVo> getCategoryList();

    @RequestMapping("/category/getNacosConfig")
    NacosConfigEntity getNacosConfig();

}

按理来说,FeignClient应该将"/blogservice/category/getNacosConfig"解析为Nacos中的blogservice服务,即“http://localhost:8888/category/getNacosConfig”,而我在调用时报错“nested exception is java.net.UnknownHostException”,且调用的URL显示的是服务名称,而不是真正的URL;在我显式指定了FeignClient对应的URL地址后,又能够成功访问了,说明确实出现了服务名解析问题。

//显式指定的方法,相当于写死URL,无法依靠负载均衡策略做分布式,没什么意义
@FeignClient(value = "blogservice", url = "http://localhost:8888/")

没道理啊,我另一个工程代码基本一模一样,调用没一点问题,于是我开始了对这个问题漫长的分析。

首先怀疑是负载均衡失效,Ribbon无法根据服务名寻找到正确的服务,以及它对应的URL。为了印证是负载均衡的问题,我用RestTemplate代替Feign来进行远程调用,同样用服务名来调用服务。这时报出了这样的错误“java.lang.IllegalStateException: No instances available for localhost”,意为没有找到对应的服务实例,而Nacos控制台的服务全部注册成功且健康无比,说明问题确实出现在负载均衡上。

接下来我继续使用RestTemplate,看看调整负载均衡策略是否能解决这个问题。于是我在RestTemplate上加入了@LoadBalanced开启负载均衡,并注入IRule中的随机策略。加入@LoadBalanced的RestTemplate会被加上一个loadBalancerInterceptor拦截器,在这个RestTemplate发起请求时,会将其拦住并寻找对应的实例地址,再根据负载均衡策略进行挑选。

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }

    @Bean
    public IRule randomRule() {
        return new RandomRule();
    }

但是代码中IRule一直爆红,怎么都无法引入。IRule来自于“com.netflix.loadbalancer”中,虽然资料显示SpringCloudAlibaba是整合了Netflix相关组件的,但是SpringCloud新版本对于Netflix支持不是很友好,所以我自己引入了一个netflix-ribbon

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
            <version>2.2.10.RELEASE</version>
        </dependency>

这个时候IRule确实是不爆红了,再次调用接口还是显示没有服务实例。按理来说负载均衡策略应该已经生效了,数个服务实例也都正常运行,但还是没法正常调用,只能把思路转向另一个方向。

项目一开始的版本管理是SpringBoot 2.5.0 + SpringCloud 2020.0.3 + SpringCloud Alibaba 2.2.5.RELEASE,之前因为SpringBoot与SpringCloud版本有强对应关系,导致Nacos的无法正常启动,因此我调整过对应的版本很多次。但我在让SpringBoot和SpringCloud版本对应的时候,并没有管SpringCloud Alibaba的版本。于是我去搜索了一下他们三者的版本对应关系,果然一查发现SpringCloud Hoxton.SR8才能与SpringCloud Alibaba 2.2.5.RELEASE兼容,说明他们三者存在版本冲突问题。

发现这个问题后,我开始了漫长的排列组合,最后将所有版本回退,使用如下版本才正常了。

        <spring.cloud-version>Hoxton.SR8</spring.cloud-version>
        <spring.cloud.alibaba-version>2.2.3.RELEASE</spring.cloud.alibaba-version>
        <spring.boot-version>2.3.2.RELEASE</spring.boot-version>

RestTemplate调用正常后,我又用Feign进行远端调用也成功了,且负载均衡策略也正常运行。泪目,这问题是真坑啊。

  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Feign远程调用中,事务控制是一个比较复杂的问题Feign本身并不直接支持事务控制,因为它是一个用于远程服务调用的工具,而事务控制通常是在应用程序的业务逻辑层面进行处理的。 如果你需要在Feign远程调用中实现事务控制,你可以考虑以下几种方式: 1. 分布式事务管理器:使用分布式事务管理器,如Spring Cloud的分布式事务管理器或者Seata等,来管理Feign远程调用中的事务。这样可以确保在跨服务调用时,事务的一致性和隔离性得到保证。 2. 本地事务补偿:在Feign远程调用中,可以通过本地事务补偿的方式来实现事务控制。即在调用方的本地事务中,记录下需要调用的远程服务的操作,如果本地事务成功提交,则再调用远程服务进行相应的操作。如果本地事务失败,则进行相应的事务回滚。 3. 异步消息:使用异步消息的方式来实现事务控制。即在调用方的本地事务中,将需要调用的远程服务的操作发送到消息队列中,然后由消息队列来保证事务的一致性和隔离性。 需要注意的是,以上方法都需要在应用程序的业务逻辑层面进行相应的处理和配置,具体的实现方式会根据你的业务需求和技术栈而有所不同。同时,对于分布式事务的处理,还需要考虑到分布式事务的一致性和性能等方面的问题。 综上所述,Feign本身并不直接支持事务控制,但可以通过使用分布式事务管理器、本地事务补偿或异步消息等方式来实现Feign远程调用的事务控制。具体的实现方式需要根据你的业务需求和技术栈来确定。 #### 引用[.reference_title] - *1* *2* *3* [微服务组件之Feign远程服务调用](https://blog.csdn.net/Wang_Dong_Liang/article/details/127633506)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值