SPRING CLOUD微服务实战笔记--声明式服务调用:Spring Cloud Feign

骑猪看日落 2022-02-27 05:54 335阅读 0赞

Spring Cloud Feign

  • 快速入门
  • 参数绑定
  • 继承特性
  • Ribbon配置
    • 全局配置
    • 指定服务配置
  • Hystrix配置
    • 全局配置
    • 禁用Hystrix
  • 其他配置
    • 请求压缩
    • 日志配置

快速入门

通过Spring Cloud Feign提供的声明式服务绑定功能来实现对该服务接口的调用

  • 创建Spring Boot工程,在pom.xml中引入依赖


    org.springframework.cloud
    spring-cloud-starter-feign
    1.4.6.RELEASE
  • 创建应用主类,并通过@EnableFeignClients注解开启Spring Cloud Feign的支持功能

    @EnableFeignClients
    @EnableEurekaClient
    @SpringBootApplication
    public class HelloApplication {

    1. public static void main(String[] args) {
    2. SpringApplication.run(HelloApplication.class, args);
    3. }

    }

  • 定义HelloService接口,通过@FeignClient注解指定服务名来绑定服务,然后再使用SpringMVC的注解绑定具体该服务提供的REST接口

    @FeignClient(“hello-service”)
    public interface HelloService {

    1. @RequestMapping("/hello")
    2. String hello();

    }

  • 创建一个ConsumerController来实现Feign客户端的调用

    @RestController
    public class ConsumerController {

    1. @Autowired
    2. HelloService helloService;
    3. @RequestMapping(value = "/feign-consumer" , method = RequestMethod.GET)
    4. public String helloConsumer(){
    5. return helloService.hello();
    6. }

    }

  • 在application.properties中指定服务注册中心

    spring.application.name=feign-consumer
    server.port=9003
    eureka.client.service-url.defaultZone=http://localhost:1111/eureka/

测试验证
访问http://localhost:9003/feign-consumer,页面如下:
在这里插入图片描述

参数绑定

第一步:改造服务提供方的服务
服务提供方修改服务,增加接口定义,分别带有Request参数的请求,带有Header信息的请求,带有RequestBody的请求

  1. @RequestMapping(value = "/hello1",method = RequestMethod.GET)
  2. public String hello(@RequestParam String name){
  3. return "Hello " + name;
  4. }
  5. @RequestMapping(value = "/hello2",method = RequestMethod.GET)
  6. public User hello(@RequestHeader String name,@RequestHeader Integer age){
  7. return new User(name,age);
  8. }
  9. @RequestMapping(value = "/hello3" , method = RequestMethod.POST)
  10. public String hello(@RequestBody User user){
  11. return "Hello " + user.getName() + ", " + user.getAge();
  12. }

User对象定义如下:

  1. public class User {
  2. private String name;
  3. private Integer age;
  4. public User(){ }
  5. public User(String name,Integer age){
  6. this.name = name;
  7. this.age = age;
  8. }
  9. //省略getter和setter方法
  10. @Override
  11. public String toString(){
  12. return "name=" + name + ",age=" + age;
  13. }
  14. }

第二步:改造服务消费端的请求绑定

  • 在feign-consumer中添加和上面一样的User类
  • 在HelloService中增加三个新增接口的绑定声明

    @FeignClient(“hello-service”)
    public interface HelloService {

    1. @RequestMapping("/hello")
    2. String hello();
    3. @RequestMapping(value="/hello1",method = RequestMethod.GET)
    4. String hello(@RequestParam("name") String name);
    5. @RequestMapping(value = "/hello2",method = RequestMethod.GET)
    6. User hello(@RequestHeader("name") String name,@RequestHeader("age") Integer age);
    7. @RequestMapping(value = "/hello3",method = RequestMethod.POST)
    8. String hello(@RequestBody User user);

    }

  • 在ConsumerController中新增一个/feign-consumer2接口,对新增接口进行调用

    @RequestMapping(value = “/feign-consumer2”,method = RequestMethod.GET)

    1. public String helloConsumer2(){
    2. StringBuilder sb = new StringBuilder();
    3. sb.append(helloService.hello()).append("\n");
    4. sb.append(helloService.hello("DIDI")).append("\n");
    5. sb.append(helloService.hello("DIDI",30)).append("\n");
    6. sb.append(helloService.hello(new User("DIDI",30))).append("\n");
    7. return sb.toString();
    8. }

测试验证
访问http://localhost:9003/feign-consumer2,返回如下:

  1. Hello World! Hello DIDI name=DIDI,age=30 Hello DIDI, 30

继承特性

通过Spring Cloud Feign的继承特性来实现REST接口定义的复用
先新建一个Maven工程:

  • 创建一个Maven工程,命名为hello-service-api
  • 修改工程的pom,引入依赖

    4.0.0

    1. <groupId>com.didispace</groupId>
    2. <artifactId>hello-service-api</artifactId>
    3. <packaging>jar</packaging>
    4. <version>0.0.1-SNAPSHOT</version>
    5. <name>hello-service-api</name>
    6. <description>Demo project for Spring Boot</description>
    7. <parent>
    8. <groupId>org.springframework.boot</groupId>
    9. <artifactId>spring-boot-starter-parent</artifactId>
    10. <version>1.3.7.RELEASE</version>
    11. <relativePath></relativePath>
    12. </parent>
    13. <properties>
    14. <java.version>1.8</java.version>
    15. </properties>
    16. <dependencies>
    17. <dependency>
    18. <groupId>org.springframework.boot</groupId>
    19. <artifactId>spring-boot-starter-web</artifactId>
    20. </dependency>
    21. </dependencies>
  • 将上一节实现的User对象复制到hello-service-api工程中

  • 在Maven工程中添加HelloService

    @RequestMapping(“/refactor”)
    public interface HelloService {

    1. @RequestMapping(value = "/hello4",method = RequestMethod.GET)
    2. public String hello(@RequestParam String name);
    3. @RequestMapping(value = "/hello5",method = RequestMethod.GET)
    4. public User hello(@RequestHeader String name, @RequestHeader Integer age);
    5. @RequestMapping(value = "/hello6" , method = RequestMethod.POST)
    6. public String hello(@RequestBody User user);

    }

再修改服务提供方,对其进行重构

  • 修改pom.xml,新增对hello-service-api的依赖


    com.didispace
    hello-service-api
    0.0.1-SNAPSHOT
  • 创建RefactorHelloController类继承hello-service-api中定义HelloService接口,并实现这个接口中的方法

    @RestController
    public class RefactorHelloController implements HelloService {

    1. @Override
    2. public String hello(@RequestParam("name") String name) {
    3. return "Hello " + name;
    4. }
    5. @Override
    6. public User hello(@RequestHeader("name") String name,@RequestHeader("age") Integer age) {
    7. return new User(name,age);
    8. }
    9. @Override
    10. public String hello(@RequestBody User user) {
    11. return "Hello " + user.getName() + ", " + user.getAge();
    12. }

    }

最后修改服务消费者

  • 修改pom.xml,新增对hello-service-api的依赖


    com.didispace
    hello-service-api
    0.0.1-SNAPSHOT
  • 创建RefactorHelloService接口,并继承hello-service-api包中的HelloService接口,然后添加@FeignClient注解来绑定服务

    @FeignClient(value = “HELLO-SERVICE”)
    public interface RefactorHelloService extends com.didispace.service.HelloService{
    }

  • 在ConsumerController中,注入RefactorHelloService的实例,并新增一个请求/feign-consumer3来触发RefactorHelloService的实例

    @RequestMapping(value = “/feign-consumer3”,method = RequestMethod.GET)

    1. public String helloConsumer3(){
    2. StringBuilder sb = new StringBuilder();
    3. sb.append(refactorHelloService.hello("MIMI")).append("\n");
    4. sb.append(refactorHelloService.hello("MIMI",30)).append("\n");
    5. sb.append(refactorHelloService.hello(new com.didispace.User.User("MIMI",20))).append("\n");
    6. return sb.toString();
    7. }

遇到的问题:
将项目引入到maven私服库的时候,项目中调用接口不能识别,原来之前为了打包将pom中的编译插件换了,导致执行mvn install命令时编译有问题

  1. <build>
  2. <plugins>
  3. <plugin>
  4. <groupId>org.springframework.boot</groupId>
  5. <artifactId>spring-boot-maven-plugin</artifactId>
  6. <version>2.0.3.RELEASE</version>
  7. <executions>
  8. <execution>
  9. <goals>
  10. <goal>repackage</goal>
  11. </goals>
  12. </execution>
  13. </executions>
  14. </plugin>
  15. </plugins>
  16. </build>

将上面这段从pom中删除,重新执行mvn install后成功

Ribbon配置

全局配置

通过使用ribbon.=方式来设置ribbon的各项默认参数,比如修改默认的客户端调用超时时间:

  1. ribbon.ConnectTimeout = 500
  2. ribbon.ReadTimeout=5000

指定服务配置

有时需要个性化配置,采用.ribbon.key=value的格式进行设置
使用@FeignClient(value = “HELLO-SERVICE”)来创建Feign客户端的时候,同时也创建了一个名为HELLO-SERVICE的Ribbon客户端

  1. HELLO-SERVICE.ribbon.ConnectTimeout=500
  2. HELLO-SERVICE.ribbon.ReadTimeout=2000

Hystrix配置

全局配置

Hystrix的全局配置采用默认配置前缀hystrix.command.default就可以设置,比如设置全局的超时时间:

  1. hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=5000

通过feign.hystrix.enabled=false来全局关闭Hystrix功能
通过feign.command.default.execution.timeout.enabled=false来关闭熔断功能

禁用Hystrix

@Scope(“prototype”)注解为指定的客户端配置Feign.Builder实例

  • 构建一个Hystrix配置类

    @Configuration
    public class DisableHystrixConfiguration{

    1. @Bean
    2. @Scope("prototype")
    3. public Feign.Builder feignBuilder(){
    4. return Feign.builder();
    5. }

    }

  • 在HelloService的@FeignClient注解中,通过configuration参数引入上面实现的配置

    @FeignClient(name=”HELLO-SERVICE”,configuration =DisableHystrixConfiguration.class)
    public interface HelloService{
    }

其他配置

请求压缩

SpringCloudFeign支持对请求与响应进行GZIP压缩,以减少通信过程中的性能损耗

  1. feign.compression.request.enabled=true
  2. feign.compression.response.enabled=true

同时还可以进行更加细化的配置

  1. feign.compression.request.enabled=true;
  2. //指定压缩请求数据类型
  3. feign.comresstion.request.mime-types=text/xml,application/xml,application/json
  4. //请求压缩的大小下限,只有查过这个大小的请求才会对其进行压缩
  5. feign.compression.request.min-request-size=2048

日志配置

可以在application.properties文件中使用logging.level.<FeignClient>的参数配置格式来开启指定Feign客户端的DEBUG日志,其中<FeignClient>为Feign客户端定义接口的完整路径,比如:

  1. logging.level.com.didispace.web.HelloService=DEBUG

同时调整全局的日志级别,可以在应用主类中直接加入Logger.Level的Bean创建,具体如下:

  1. @EnableFeignClients
  2. @EnableEurekaClient
  3. @SpringBootApplication
  4. public class HelloApplication {
  5. @Bean
  6. Logger.Level feignLoggerLevel(){
  7. return Logger.Level.FULL;
  8. }
  9. public static void main(String[] args) {
  10. SpringApplication.run(HelloApplication.class, args);
  11. }
  12. }

对于Feign的Logger级别主要有如下4类,可以根据实际需要进行调整使用

  • NONE:不记录任何信息
  • BASIC:仅记录请求方法,URL以及响应状态码和执行时间
  • HEADERS:除了记录BASIC级别的信息之外,还会记录请求和响应的头信息
  • FULL:记录所有请求与响应的明细,包括头信息,请求体和元数据等

发表评论

表情:
评论列表 (有 0 条评论,335人围观)

还没有评论,来说两句吧...

相关阅读