spring cloud feign组件简单使用

springcloud是使用rest协议(RestTemplate)进行信息传递,同时在netfix的项目中实现了一个feign组件来简化编写代码的麻烦,并且有自动负载均衡

不需要配置类中加上

@LoadBalanced 注解了

不过想修改负载均衡策略,你还是需要在application.yml中配置 


调用的原理:

通过动态代理,产生了一个代理类交给了spring容器。然后通过反射获取接口的注解以及里面的配置,获取路径,获取参数名,参数值,获取返回的类型。然后封装到RestTemolate中,然后模拟浏览器请求。


简单使用:

1,加入起步依赖,在调用者模块中加入

<dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

2,启动类添加@EnableFeignClients注解

@SpringBootApplication
@EnableEurekaClient
@EnableCircuitBreaker//开启熔断机制
@EnableFeignClients//
public class UserConsumerApplication {
    public static void main(String[] args) {
        SpringApplication.run(UserConsumerApplication.class,args);
    }

   /* @Bean
    @LoadBalanced //启动负载均衡
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }*/
}

3,创建一个接口,接口里面的方法名,参数名,以及返回值要和controller类一致

package org.example.feign;

import org.example.pojo.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
//声明feign组件,name是指定服务名,
//@FeignClient(name = "${feign.name}", url = "${feign.url}")
@FeignClient(name = "user-provider")
public interface UserFeign {
    /**
      * 这个路径和对应请求微服务的路径一至
      */
    @GetMapping("/user/{id}")
    public User findById(@PathVariable(name = "id") Integer id);
}

4,controller类,直接注入接口,然后调用接口的方法即可

package org.example.controller;

import org.example.feign.UserFeign;
import org.example.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/feign")
public class TestFeignController {

    @Autowired
    private UserFeign userFeign;

    @GetMapping("/{id}")
    public User findByid(@PathVariable(name = "id") Integer id){
        //接受浏览器请求
        //调用feign
        User user = userFeign.findById(id);
        return user;
    }
}

负载均衡配置

1,通过Ribbon来配置

# 修改服务地址轮询策略,默认是轮询,配置之后变随机
# WeightedResponseTimeRule 根据服务响应时间权重值策略
# RoundRobinRule 轮询策略
# RandomRule 随机策略
# Zone Avoidance Rule 区域避免规则。
# 配置负载均衡
user-provider:
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #默认是轮询,配置为随机
    ConnectTimeout: 1000 # 连接超时时间
    ReadTimeout: 2000 # 数据读取超时时间,连接之后,数据传输过程
    MaxAutoRetries: 0 # 最大重试次数(第一个服务)
    MaxAutoRetriesNextServer: 0 # 最大重试下一个服务次数(集群的情况才会用到)
    OkToRetryOnAllOperations: false # 是否对所有的请求都重试

2,或者通过fegin来配置

feign:
  client:
    config:
      feignName:
        connectTimeout: 5000
        readTimeout: 5000
        loggerLevel: full
        errorDecoder: com.example.SimpleErrorDecoder
        retryer: com.example.SimpleRetryer
       defaultQueryParameters:
          query: queryValue
        defaultRequestHeaders:
          header: headerValue
        requestInterceptors:
          - com.example.FooRequestInterceptor
          - com.example.BarRequestInterceptor
        decode404: false
        encoder: com.example.SimpleEncoder
        decoder: com.example.SimpleDecoder
        contract: com.example.SimpleContract

熔断器支持(默认没有开启)

# To disable Hystrix in Feign
feign:
  hystrix:
    enabled: true

开启后如果你发现下游微服务正常,但是一直进入熔断,可以看看我发的下面的这两个连接来解决

第一个连接配置config类后,注意得把配置文件中的配置注释掉

Feign开启HyStrix后如何配置线程隔离及熔断策略_问题不太大的博客-CSDN博客_feign hystrix自定义隔离 开启hystrix:feign.hystrix.enabled=true时, RequestContextHolder.getRequestAttributes()为空_aresdata的博客-CSDN博客_feign.hystrix.enabled

使用:

创建一个对应的Feign类的实现类

package org.example.feign.impl;

import org.example.feign.UserFeign;
import org.example.pojo.User;
@Component
public class UserFeignImpl implements UserFeign {

    //降级方法
    @Override
    public User findById(Integer id) {
        User user = new User();
        user.setId(0);
        user.setUsername("默认名称");
        return user;
    }
}

然后在@FeignClient注解加上一个参数fallback

package org.example.feign;

import org.example.feign.impl.UserFeignImpl;
import org.example.pojo.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
//声明feign组件,name是指定服务名,
//@FeignClient(name = "${feign.name}", url = "${feign.url}")
@FeignClient(name = "user-provider",fallback = UserFeignImpl.class)
public interface UserFeign {
    @GetMapping("/user/{id}")
    public User findById(@PathVariable(name = "id") Integer id);
}

注意项:

如果你需要使用Hystrix那么就不要把@RequestMapping注解写到类上,因为实现类实现了接口,而@RequestMapping加在接口上,那么实现类也会生成两个动态代理类和一个同样的路径,导致url路径不唯一,所以会报错

解决方法:

1,直接不在类上加@RequestMapping注解

2,或者在@FeignClient加入一个参数:path即可

package org.example.feign;

import org.example.feign.impl.UserFeignImpl;
import org.example.pojo.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
//声明feign组件,name是指定服务名,
//@FeignClient(name = "${feign.name}", url = "${feign.url}")
@FeignClient(name = "user-provider",fallback = UserFeignImpl.class,path="/user")
public interface UserFeign {
    @GetMapping("/{id}")
    public User findById(@PathVariable(name = "id") Integer id);
}

另外还可以了解一下请求压缩,响应压缩,和日志级别配置

(15条消息) SpringCloud Feign 优化_xjune的专栏-CSDN博客


超时配置

在OpenFeign中设置超时时间是一个重要的配置,因为它决定了Feign客户端在等待服务响应时的等待时长。以下是如何在OpenFeign中设置超时时间的步骤:

1. **全局超时设置**:
   你可以在`application.yml`或`application.properties`文件中为所有Feign客户端设置默认的超时时间。例如,以下配置设置了连接超时为2000毫秒(2秒),读取超时为60000毫秒(60秒):

feign:
     client:
       config:
         default:
           connectTimeout: 2000
           readTimeout: 60000

2. **单个服务超时设置**:
   如果需要为特定的Feign客户端设置不同的超时时间,可以在配置前缀中指定客户端的名称。例如,为名为`serviceA`的服务设置超时时间:

feign:
     client:
       config:
         serviceA:
           connectTimeout: 2000
           readTimeout: 60000

3. **方法级别的超时设置**:
   对于单个Feign接口中的方法,你可以使用`@FeignClient`注解的`path`属性来指定特定的路径,并通过`Request.Options`来设置该方法的超时时间。例如:

  @FeignClient(name = "serviceA", path = "/api/v1", configuration = FeignConfig.class)
   public interface ServiceAClient {
       @GetMapping("/resource")
       String getResource(@Request.Options(Request.Options options) String resourceId);
   }

   在`FeignConfig`类中,你可以定义`Request.Options`来设置特定的超时时间:

 @Configuration
   public class FeignConfig {
       @Bean
       public Request.Options requestOptions() {
           return new Request.Options(2000, 60000);
       }
   }

多个方法

@Configuration
public class ServiceAClientConfig {
    @Bean
    public Request.Options serviceAResourceOptions() {
        // 为特定请求设置更长的读取超时:连接超时2秒,读取超时10秒
        return new Request.Options(2000, 10000);
    }
}

 在Feign客户端接口上,你可以使用 configuration 属性来指定配置类,该配置类包含了方法级别的 Request.Options Bean。

@FeignClient(name = "serviceA", configuration = ServiceAClientConfig.class)
public interface ServiceAClient {
    @GetMapping("/resource")
    String getResource(@Request.Options(ServiceAClientConfig.serviceAResourceOptions()) String resourceId);
}

4. **使用Hystrix进行熔断保护**:
   如果你的Feign客户端启用了Hystrix,你还需要配置Hystrix的超时时间,以确保它大于Feign的超时时间。例如:

hystrix:
     command:
       default:
         execution:
           isolation:
             thread:
               timeoutInMilliseconds: 65000

5. **启用Feign日志**:
   为了更好地调试和监控Feign客户端的调用,你可以启用Feign的日志记录。例如,设置日志级别为`full`:

feign:
     client:
       config:
         serviceA:
           loggerLevel: full

6. **处理超时异常**:
   当Feign客户端请求超时时,它会抛出`FeignException`。你可以在你的服务中捕获这个异常并进行相应的处理。

请注意,超时时间的设置应该根据你的业务需求和后端服务的性能来调整。如果你的服务响应时间较长,可能需要增加超时时间。同时,确保你的服务能够快速失败,以避免不必要的等待。
 

posted @ 2021-09-03 23:47  在线电影制作人  阅读(3)  评论(0)    收藏  举报  来源