声明式服务调用SpringCloud Feign

约定不等于承诺〃 2022-05-08 01:12 430阅读 0赞

声明式服务调用SpringCloud Feign

文章目录

  • 声明式服务调用SpringCloud Feign
      • 快速入门
      • 参数绑定
      • 继承特性
      • Ribbon 配置
        • 全局配置
        • 指定服务配置
        • 重试机制
      • Hystrix 配置
        • 全局配置
        • 禁用 Hystrix
        • 指定命令配置
        • 服务降级配置
      • 其他配置
        • 请求压缩
      • 日志配置

快速入门

创建项目 feign-consumer 9010

pom 依赖

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  3. <modelVersion>4.0.0</modelVersion>
  4. <groupId>com.zk.springcloud.feign</groupId>
  5. <artifactId>springcloud-feign</artifactId>
  6. <version>0.0.1-SNAPSHOT</version>
  7. <packaging>jar</packaging>
  8. <name>springcloud-feign</name>
  9. <description>Demo project for Spring Boot</description>
  10. <parent>
  11. <groupId>org.springframework.boot</groupId>
  12. <artifactId>spring-boot-starter-parent</artifactId>
  13. <version>2.0.5.RELEASE</version>
  14. <relativePath/> <!-- lookup parent from repository -->
  15. </parent>
  16. <properties>
  17. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  18. <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
  19. <java.version>1.8</java.version>
  20. <spring-cloud.version>Finchley.SR1</spring-cloud.version>
  21. </properties>
  22. <dependencies>
  23. <dependency>
  24. <groupId>org.springframework.boot</groupId>
  25. <artifactId>spring-boot-starter-web</artifactId>
  26. </dependency>
  27. <dependency>
  28. <groupId>org.springframework.cloud</groupId>
  29. <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
  30. </dependency>
  31. <dependency>
  32. <groupId>org.springframework.cloud</groupId>
  33. <artifactId>spring-cloud-starter-openfeign</artifactId>
  34. </dependency>
  35. <dependency>
  36. <groupId>org.springframework.boot</groupId>
  37. <artifactId>spring-boot-starter-test</artifactId>
  38. <scope>test</scope>
  39. </dependency>
  40. </dependencies>
  41. <dependencyManagement>
  42. <dependencies>
  43. <dependency>
  44. <groupId>org.springframework.cloud</groupId>
  45. <artifactId>spring-cloud-dependencies</artifactId>
  46. <version>${spring-cloud.version}</version>
  47. <type>pom</type>
  48. <scope>import</scope>
  49. </dependency>
  50. </dependencies>
  51. </dependencyManagement>
  52. <build>
  53. <plugins>
  54. <plugin>
  55. <groupId>org.springframework.boot</groupId>
  56. <artifactId>spring-boot-maven-plugin</artifactId>
  57. </plugin>
  58. </plugins>
  59. </build>
  60. </project>

创建应用启动类,并通过 @EnableFeignClients 注解开启 Spring Cloud Feign 的支持功能

  1. @SpringBootApplication @EnableFeignClients @EnableDiscoveryClient public class SpringcloudFeignApplication { public static void main(String[] args) { SpringApplication.run(SpringcloudFeignApplication.class, args); } }

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

这里服务名不区分大小写,所以使用 SERIVCE-USER 和 service-user 都是可以的

  1. @FeignClient("SERIVCE-USER") @Service public interface HelloService { @RequestMapping("/hello") String hello(); }

方法调用

  1. @RestController public class ConsumerController { @Autowired HelloService helloService; @GetMapping(value = "/feign-consumer") public String helloConsumer(){ return helloService.hello(); } }

配置文件

  1. spring.application.name=feign-consumer
  2. server.port=9010
  3. eureka.client.service-url.defaultZone=http://localhost:9001/eureka/,http://localhost:9004/eureka/

测试验证,如之前验证 Ribbon 客户端负载均衡一样,先启动注册中心以及两个 SERVICE-USER ,然后启动 FEIGN-CONSUMER ,多次调用 http://localhost:9010/feign-consumer , 结果与之前 Ribbon 实现时一样的效果 Hello World 9006 和 Hello World 9003 切换显示。依然是利用 Ribbon 维护对 SERVICE-USER 的服务列表信息,并且通过轮询实现了客户端负载均衡。

参数绑定

feign-consumer 9010 , HelloService 添加方法

  1. @GetMapping(value = "/hello1")
  2. String hello(@RequestParam("name") String name);
  3. @GetMapping(value = "/hello2")
  4. User hello(@RequestHeader("name") String name,@RequestHeader("password") String password);
  5. @PostMapping(value = "/hello3")
  6. String hello(@RequestBody User user);

User 对象如下, 这里必须要有 User 的默认构造函数,不然 Spring Cloud Feign 根据 JSON 字符串转换 User 对象会抛出异常

  1. public class User { String name; String password; public User() { } public User(String name, String password) { this.name = name; this.password = password; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", password='" + password + '\'' + '}'; } }

对 UserService 9003 项目改造

  1. @FeignClient("SERIVCE-USER") @Service public interface HelloService { @RequestMapping("/hello") String hello(); @GetMapping(value = "/hello1") String hello(@RequestParam("name") String name); @GetMapping(value = "/hello2") User hello(@RequestHeader("name") String name,@RequestHeader("password") String password); @PostMapping(value = "/hello3") String hello(@RequestBody User user); }

在 feign-consumer 9010 项目添加调用

  1. @GetMapping(value = "/feign-consumer2") public String helloConsumer2(){ StringBuilder sb = new StringBuilder(); sb.append(helloService.hello()).append("\n"); sb.append(helloService.hello("DIDI")).append("\n"); sb.append(helloService.hello("DIDI","123456")).append("\n"); sb.append(helloService.hello(new User("DIDI","admin"))).append("\n"); return sb.toString(); }

访问 http://localhost:9010/feign-consumer2 可获取 Hello World 9003 Hello DIDI User{name=‘DIDI’, password=‘123456’} Hello DIDI, admin

继承特性

创建名为 user-service-api 的 maven 项目

pom 依赖

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  3. <modelVersion/>
  4. <groupId>com.zk.springcloud</groupId>
  5. <artifactId>springcloud-user-service-api</artifactId>
  6. <version>0.0.1-SNAPSHOT</version>
  7. <packaging>jar</packaging>
  8. <parent>
  9. <groupId>org.springframework.boot</groupId>
  10. <artifactId>spring-boot-starter-parent</artifactId>
  11. <version>2.0.5.RELEASE</version>
  12. <relativePath/> <!-- lookup parent from repository -->
  13. </parent>
  14. <properties>
  15. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  16. <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
  17. <java.version>1.8</java.version>
  18. <spring-cloud.version>Finchley.SR1</spring-cloud.version>
  19. </properties>
  20. <dependencies>
  21. <dependency>
  22. <groupId>org.springframework.boot</groupId>
  23. <artifactId>spring-boot-starter-web</artifactId>
  24. </dependency>
  25. </dependencies>
  26. </project>

复制上节中的 User 对象到 user-service-api 工程

创建 HelloService 接口

  1. package com.zk.springcloud; import org.springframework.web.bind.annotation.*; @RequestMapping("/refactor") public interface HelloService { @GetMapping(value = "/hello4") String hello(@RequestParam("name") String name); @GetMapping(value = "/hello5") User hello(@RequestHeader("name") String name,@RequestHeader("password") String password); @PostMapping(value = "/hello6") String hello(@RequestBody User user); }

对 user-service 和 feign-consumer 重构

对 user-service 重构

添加 user-serivce-api的依赖

  1. <dependency>
  2. <groupId>com.zk.springcloud</groupId>
  3. <artifactId>springcloud-user-service-api</artifactId>
  4. <version>0.0.1-SNAPSHOT</version>
  5. </dependency>

创建 RefactorHelloController 类继承 user-service-api 中定义的 HelloService 接口

  1. package com.zk.springcloud.service; import com.zk.springcloud.HelloService; import com.zk.springcloud.User; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController public class RefactorHelloController implements HelloService { @Override public String hello(@RequestParam("name") String name) { return "Hello " + name; } @Override public User hello(@RequestHeader("name") String name,@RequestHeader("password") String password) { return new User(name,password); } @Override public String hello(@RequestBody User user) { return "Hello " + user.getName() + ", " + user.getPassword(); } }

对 feign-consumer 重构

创建 RefactorHelloService 接口

  1. import org.springframework.stereotype.Service; @FeignClient(value = "SERIVCE-USER") @Service public interface RefactorHelloService extends HelloService { }

添加调用

  1. @GetMapping(value = "/feign-consumer3") public String helloConsumer3(){ StringBuilder sb = new StringBuilder(); sb.append(refactorHelloService.hello("MIMI")).append("\n"); sb.append(refactorHelloService.hello("MIMI","123456")).append("\n"); sb.append(refactorHelloService.hello(new com.zk.springcloud.User("MIMI","123456"))).append("\n"); return sb.toString(); }

访问 http://localhost:9010/feign-consumer3 获得如下结果

  1. Hello MIMI User{name='MIMI', password='123456'} Hello MIMI, 123456

Ribbon 配置

全局配置

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

指定服务配置

  1. serivce-user.ribbon.ConnectTimeout=500
  2. serivce-user.ribbon.ReadTimeout=2000
  3. serivce-user.ribbon.okToRetryOnAllOperations=true
  4. serivce-user.ribbon.MaxAutoRetriesNextServer=2
  5. serivce-user.ribbon.MaxAutoRetries=1

重试机制

feign-consumer 添加上述指定服务配置

user-service 修改如下超时

  1. @GetMapping(value = "/hello") public String hello() throws InterruptedException { int sleepTime = new Random().nextInt(3000); log.info("sleepTime: " + sleepTime); Thread.sleep(sleepTime); return "Hello World 9003"; }

访问 http://localhost:9010/feign-consumer

在 user-service 可以看到重试日志

Hystrix 配置

全局配置

  1. hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=5000
  2. #关闭 Hystrix 功能
  3. #feign.hystrix.enabled=false
  4. #关闭熔断功能
  5. #hystrix.command.default.execution.timeout.enabled=false

禁用 Hystrix

全局关闭 Hystrix

  1. #关闭 Hystrix 功能
  2. feign.hystrix.enabled=false

针对某个客户端关闭 Hystrix ,通过使用 @Scope(“prototype”) 注解为指定的客户端配置 Feign.Builder 实例

构建一个关闭 Hystrix 的配置类

  1. @Configuration public class DisableHystrixConfiguration { @Bean @Scope("prototype") public Feign.Builder feignBuilder(){ return Feign.builder(); } }

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

  1. @FeignClient(value = "SERIVCE-USER",configuration = DisableHystrixConfiguration.class) @Service public interface HelloService { ··· }

指定命令配置

针对尝试机制中对 /hello 接口的熔断时间的配置可通过如下配置

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

服务降级配置

对 feign-consumer 工程进行改造

  1. package com.zk.springcloud.feign; import org.springframework.stereotype.Component; import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.RequestParam; @Component public class HelloServiceFallBack implements HelloService { @Override public String hello() { return "error"; } @Override public String hello(@RequestParam("name") String name) { return "error"; } @Override public User hello(@RequestHeader("name") String name,@RequestHeader("password") String password) { return new User("未知","0"); } @Override public String hello(User user) { return "error"; } }

在服务绑定接口 HelloService 中,通过 @FeignClient 注解的 fallback 属性来指定对应的服务降级实现类

  1. @FeignClient(value = "SERIVCE-USER",fallback = HelloServiceFallBack.class) @Service public interface HelloService { @RequestMapping("/hello") String hello(); @GetMapping(value = "/hello1") String hello(@RequestParam("name") String name); @GetMapping(value = "/hello2") User hello(@RequestHeader("name") String name,@RequestHeader("password") String password); @PostMapping(value = "/hello3") String hello(@RequestBody User user); }

配置文件开启 feign.hystrix

  1. feign.hystrix.enabled=true

将类 DisableHystrixConfiguration 注释

将 user-service 服务关闭,访问 http://localhost:9010/feign-consumer2 获得如下结果:

  1. error error User{name='未知', password='0'} error

其他配置

请求压缩

  1. feign.compression.request.enabled=true
  2. feign.compression.response.enabled=true
  3. #设置压缩的大小下限,超过的才进行压缩,以下配置为默认值
  4. feign.compression.request.mime-types=text/xml,application/xml,application/json
  5. feign.compression.request.min-request-size=2048

日志配置

  1. logging.level.com.zk.springcloud.feign.HelloService=DEBUG

feign-consumer 启动类配置

  1. @SpringBootApplication @EnableFeignClients @EnableDiscoveryClient public class SpringcloudFeignApplication { @Bean Logger.Level feignLoggerLevel(){ return Logger.Level.FULL; } public static void main(String[] args) { SpringApplication.run(SpringcloudFeignApplication.class, args); } }

也可以通过实现配置类,然后在具体的Feign 客户端来指定配置类以实现是否要调整不同的日志界别

  1. @Configuration public class FullLogConfiguration { @Bean Logger.Level feignLoggerLevel(){ return Logger.Level.FULL; } }

调用 http://localhost:9010/feign-consumer

请求详细日志

  1. 2018-10-08 14:49:34.051 DEBUG 21632 --- [-SERIVCE-USER-5] com.zk.springcloud.feign.HelloService : [HelloService#hello] ---> GET http://SERIVCE-USER/hello HTTP/1.1
  2. 2018-10-08 14:49:34.051 DEBUG 21632 --- [-SERIVCE-USER-5] com.zk.springcloud.feign.HelloService : [HelloService#hello] ---> END HTTP (0-byte body)
  3. 2018-10-08 14:49:34.872 DEBUG 21632 --- [-SERIVCE-USER-5] com.zk.springcloud.feign.HelloService : [HelloService#hello] <--- HTTP/1.1 200 (821ms)
  4. 2018-10-08 14:49:34.872 DEBUG 21632 --- [-SERIVCE-USER-5] com.zk.springcloud.feign.HelloService : [HelloService#hello] content-length: 16
  5. 2018-10-08 14:49:34.873 DEBUG 21632 --- [-SERIVCE-USER-5] com.zk.springcloud.feign.HelloService : [HelloService#hello] content-type: text/plain;charset=UTF-8
  6. 2018-10-08 14:49:34.873 DEBUG 21632 --- [-SERIVCE-USER-5] com.zk.springcloud.feign.HelloService : [HelloService#hello] date: Mon, 08 Oct 2018 06:49:34 GMT
  7. 2018-10-08 14:49:34.873 DEBUG 21632 --- [-SERIVCE-USER-5] com.zk.springcloud.feign.HelloService : [HelloService#hello]
  8. 2018-10-08 14:49:34.873 DEBUG 21632 --- [-SERIVCE-USER-5] com.zk.springcloud.feign.HelloService : [HelloService#hello] Hello World 9003
  9. 2018-10-08 14:49:34.873 DEBUG 21632 --- [-SERIVCE-USER-5] com.zk.springcloud.feign.HelloService : [HelloService#hello] <--- END HTTP (16-byte body)

发表评论

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

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

相关阅读