Feign项目报错汇总

近日,在项目中使用到了Feign项目,却出现各种问题,于是将遇到的错误写下来,希望能帮到你。

  spring boot版本为1.5.9 ,cloud版本也不高。

接口无法注入:    

    

遇到这种情况的原因可能是 注解加的不对,或者接口中参数的获取没有绑定具体参数(巨坑)。

接下来详细的说收怎么回事。

  先从主启动类开始找:主启动类上是不是加入了@EnableFeignClients(basePackages= {"com.demo"}),basePackages指定接口所在的位置,注意,basePackages别写错了, 再有是不是加入了@ComponentScan("com.demo")  ,该注解指定扫描的包,如果不加,可能会浏览器访问的时候报404错误。 

如果以上都没有问题,那么就去接口中看看,接口上要指明你的微服务名称,代表去 Eureka注册中心中根据微服务名去找到ip和端口访问服务。   @FeignClient(value="DEMO")  value是指定的微服务名。

  另外还有一个巨坑的地方:  接口中定义的方法中,形如  @RequestParam的这种要绑定参数。 @RequestParam("id")

这个为什么这样,我搜了下没有找到原因,这里没法解释,抱歉。-----  

我想,你不会是 由于pom文件中没有依赖 相关依赖报的错。。。。。。

另外,记一次自己犯的一次特别憨憨的错误(2020-03-15, springcloud版本: Hoxton.SR1):

  Feign调用超时:

背景: 使用Feign进行服务调用,自信代码并没有什么出错的地方,无奈消费者通过feign调用服务提供方一直报超时,我仔细的一遍又一遍的查看了代码,找不到什么问题,直接通过postman调用服务提供方(本机localhost的端口)方法, 却能调通。百思不得其解,我去注册中心看了下服务提供者的情况,一下子找到了问题的原因   .......服务提供者的ip不对

原来是我本机的wifi换了, 然而我的服务提供方并没有重启,在注册中心上的ip地址仍旧是之前wifi1下的ipv4地址,而实际上我换了wifi后 ,服务提供者的ip地址已经变了。。。 重新重启了服务提供者微服务,feign调用正常了。。多么痛的领悟!! 

Feign调用丢失请求头信息

 SpringCloud版本    Greenwich.SR3

1) 单点系统中,接口中的feign远程调用会丢失请求头信息(cookie等),这是由于feign远程调用重新创建了一个新的请求,该请求并未携带老请求的任何请求头信息。解决办法: 新建一个配置类,增加一个feign的拦截器,在拦截器中将老请求的请求头信息设置到新请求中。

/**
     *  解决feign远程调用,丢失请求头信息的问题
     * @return
     */
    @Bean
    public RequestInterceptor requestInterceptor(){
        return requestTemplate -> {
//                requestTemplate
            System.out.println("feign远程调用前先进行RequestInterceptor。。。");
            ServletRequestAttributes attributes =(ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            if(attributes!=null) {
                HttpServletRequest request = attributes.getRequest();// 老请求

                if (request != null) {
                    // 同步请求头数据,Cookie
                    String cookie = request.getHeader("Cookie");
                    // 给新请求设置cookie
                    requestTemplate.header("Cookie", cookie);
                }
            }
        };
    }

2)  异步Feign调用丢失请求头问题

接口中可以同时存在多个feign调用,如果是同步状态,等待每个feign调用结束,那么接口的响应时间比较久。将代码改为异步方式(CompletableFuture.runAsync等),则会大大提高吞吐率。

简易代码如下所示:

public void createOrder(){
   
 // 创建订单需要减库存,发短信、邮件给用户 ,联系快递公司等业务
 // ... 具体业务操作
 CompletableFuture<Void> productTask =CompletableFuture.runAsync(() -> {
           productFeignService.lockProduct(); // 远程调用商品服务锁定商品,减库存
        }, executor);   
 
  
CompletableFuture<Void> smsTask=CompletableFuture.runAsync(() -> {
           smsFeignService.sendMsg(); // 远程调用消息服务给用户发送短信,邮件等
        }, executor);  

CompletableFuture<Void> thridTask=CompletableFuture.runAsync(() -> {
           thridFeignService.createExpressOrder(); // 远程调用三方服务创建快递订单
        }, executor);  
 // .... 业务操作
}

此种情况下, feign调用也会丢失请求头信息,这是由于  CompletableFuture.runAsync开辟了一个新的线程,与主线程数据并不共享。解决办法:  在主线程中通过 RequestContextHolder获取当前主线程的请求参数,然后再CompletableFuture.runAsync 中在通过RequestContextHolder 将请求参数设置到当前的线程中。代码如下所示:

public void createOrder(){

  RequestAttributes attributes = RequestContextHolder.getRequestAttributes();   

 // 创建订单需要减库存,发短信、邮件给用户 ,联系快递公司等业务
 // ... 具体业务操作
 CompletableFuture<Void> productTask =CompletableFuture.runAsync(() -> {
           // 复制主线程的 线程共享数据
            RequestContextHolder.setRequestAttributes(attributes);
           productFeignService.lockProduct(); // 远程调用商品服务锁定商品,减库存
        }, executor);   
 
  
CompletableFuture<Void> smsTask=CompletableFuture.runAsync(() -> {
            // 复制主线程的 线程共享数据
            RequestContextHolder.setRequestAttributes(attributes);
           smsFeignService.sendMsg(); // 远程调用消息服务给用户发送短信,邮件等
        }, executor);  

CompletableFuture<Void> thridTask=CompletableFuture.runAsync(() -> {
            // 复制主线程的 线程共享数据
            RequestContextHolder.setRequestAttributes(attributes);
           thridFeignService.createExpressOrder(); // 远程调用三方服务创建快递订单
        }, executor);  
 // .... 业务操作
}

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值