-
OpenFeign属性配置列表文档: https://cloud.spring.io/spring-cloud-static/spring-cloud-openfeign/2.2.2.RELEASE/reference/html/appendix.html
-
OpenFeign官方教程文档: https://cloud.spring.io/spring-cloud-static/spring-cloud-openfeign/2.2.2.RELEASE/reference/html/#configuration-properties
一、前言
Feign
是一个声明式的web service
客户端,它使得编写web service客户端更为容易。创建接口,为接口添加注解,即可使用Feign。Feign可以使用Feign注解或者JAX-RS注解,还支持热插拔的编码器和解码器。
Spring Cloud为Feign添加了Spring MVC的注解支持,并整合了Ribbon和Eureka来为使用Feign时提供负载均衡。使用@EnableFeignClients即可开启Feign。
简而言之:
Feign
采用的是基于接口的注解Feign
默认整合了ribbon
,具有负载均衡的能力Feign
默认整合了Hystrix
,具有熔断的能力
二、初探Feign
微服务间的通讯是基于HTTP
的,而Feign
就是一个伪HTTP
请求客户端,通过声明式的Feign
客户端可以调用远程微服务,在实现远程微服务调用的过程中,多个实例存在的时候,Ribbon
负载均衡器会默认的进行本地负载均衡,默认通过轮询机制进行微服务的调用,Feign
默认则是集成了并且支持Ribbon
负载均衡。
下面以订单服务(Order)
调用商品服务(Product)
为例,搭建环境使用Feign
远程调用消费服务
三、父工程
- pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>springcloud-ribbon-hystrix</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<modules>
<module>springcloud-product</module>
<module>springcloud-order</module>
</modules>
<properties>
<project.build.sourceEncoding> UTF-8 </project.build.sourceEncoding>
<project.reporting.outputEncoding> UTF-8 </project.reporting.outputEncoding>
<java.version> 1.8 </java.version>
</properties>
<dependencyManagement>
<dependencies>
<!--cloud -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Greenwich.SR2</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- SpringBoot的依赖配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.1.6.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- Alibaba-Cloud -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.1.1.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
四、商品(Product)工程
- pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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">
<parent>
<artifactId>springcloud-ribbon-hystrix</artifactId>
<groupId>org.example</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>springcloud-product</artifactId>
<properties>
<project.build.sourceEncoding> UTF-8 </project.build.sourceEncoding>
<project.reporting.outputEncoding> UTF-8 </project.reporting.outputEncoding>
<java.version> 1.8 </java.version>
</properties>
<dependencies>
<!-- web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- actuator -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- Alibaba-nacos服务发现-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- nacos-client -->
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
<version>1.2.0</version>
</dependency>
<!-- hystrix断路器 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<!-- openfeign客户端 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
</project>
- application.yml
server:
port: 8013
spring:
application:
name: nacos-product
cloud:
nacos:
discovery:
#开启服务注册与发现功能
enabled: true
#服务注册与发现地址
server-addr: 130.252.102.241:8848
- 商品服务接口ProviderController
package com.thinkingcao.product.controller;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
/**
* @desc: 生产者-商品服务
* @author: cao_wencao
* @date: 2020-04-29 19:48
*/
@RestController
@Slf4j
public class ProviderController {
@GetMapping(value = "/getProductInfo/{productId}")
public String getProductInfo(@PathVariable("productId") String productId) {
log.info("请求进来啦");
return "Hello Nacos Discovery " + productId;
}
}
- 启动类ProductProviderApp
package com.thinkingcao.product;
import org.springframework.boot.SpringApplication;
import org.springframework.cloud.client.SpringCloudApplication;
/**
* @desc: 商品服务-提供者
* @author: cao_wencao
* @date: 2020-04-29 17:48
*/
@SpringCloudApplication
public class ProductProviderApp {
public static void main(String[] args) {
SpringApplication.run(ProductProviderApp.class, args);
}
}
五、订单(Order)工程
- pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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">
<parent>
<artifactId>springcloud-ribbon-hystrix</artifactId>
<groupId>org.example</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>springcloud-order</artifactId>
<properties>
<project.build.sourceEncoding> UTF-8 </project.build.sourceEncoding>
<project.reporting.outputEncoding> UTF-8 </project.reporting.outputEncoding>
<java.version> 1.8 </java.version>
</properties>
<dependencies>
<!-- web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- actuator -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- Alibaba-nacos服务发现-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<exclusions>
<exclusion>
<artifactId>nacos-client</artifactId>
<groupId>com.alibaba.nacos</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- nacos-client -->
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId>
<version>1.2.0</version>
</dependency>
<!-- hystrix断路器 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<!-- openfeign客户端 ,默认集成并开启了ribbon负载均衡-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
</project>
- application.yml
server:
port: 8012
spring:
application:
name: nacos-order
cloud:
nacos:
discovery:
enabled: true
server-addr: 130.252.102.241:8848
register-enabled: true
- 定义
Feign
客户端OrderFeign
OrderFeign 中引入了Hystrix熔断器组件起到服务的保护降级作用,@FeignClient注解当中使用断路器支持的有两种方式fallback 和fallbackFactory
关于Feign Hystrix Fallbacks:
第一种:Hystrix
支持回退的概念:当它们的电路断开或出现错误时,将执行默认代码路径。要为给定@FeignClient
集启用后备,该fallback
属性应为实现后备的类名称。您还需要将实现声明为Spring bean
。
package com.thinkingcao.order.feign;
import com.thinkingcao.order.feign.callback.OrderFeignFallbackFactory;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
/**
* @desc: 订单调用商品服务
* @author: cao_wencao
* @date: 2020-04-29 20:19
*/
@FeignClient(name = "nacos-product",fallback = HystrixClientFallback.class)
public interface OrderFeign {
@GetMapping(value = "/getProductInfo/{productId}")
public String getProductInfo(@PathVariable("productId") String productId);
static class HystrixClientFallback implements OrderFeign {
@Override
public String getProductInfo(String productId) {
return "fallback; reason was: 服务忙,稍后重试" ;
}
}
}
第二种: 如果需要访问引起后备触发器的原因,则可以使用fallbackFactory inside
的属性@FeignClient
。说白了就是如果你想知道服务调用为什么失败了,可以使用下面这种断路器方式。
package com.thinkingcao.order.feign;
import com.thinkingcao.order.feign.callback.OrderFeignFallbackFactory;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
/**
* @desc: 订单调用商品服务
* @author: cao_wencao
* @date: 2020-04-29 20:19
*/
@FeignClient(name = "nacos-product",fallbackFactory = OrderFeignFallbackFactory.class)
public interface OrderFeign {
@GetMapping(value = "/getProductInfo/{productId}")
public String getProductInfo(@PathVariable("productId") String productId);
@Component
@Slf4j
static class OrderFeignFallbackFactory implements FallbackFactory<OrderFeign> {
@Override
public OrderFeign create(Throwable throwable) {
log.error("调用异常:"+ throwable.toString());
return new OrderFeign() {
@Override
public String getProductInfo(String string) {
return "开启断路-fallback; reason was: "+ throwable;
}
};
}
}
- 服务消费
OrderController
package com.thinkingcao.order.controller;
import com.thinkingcao.order.feign.OrderFeign;
import lombok.extern.slf4j.Slf4j;
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.RestController;
/**
* @desc: 消费者-订单服务
* @author: cao_wencao
* @date: 2020-04-29 19:50
*/
@RestController
@Slf4j
public class OrderController {
@Autowired(required = false)
private OrderFeign orderFeign;
@GetMapping("/getProduct/{productId}")
public String getProduct(@PathVariable("productId") String id){
String response = orderFeign.getProductInfo(id);
log.info("调用服务结束: "+ response);
return response;
}
}
- 启动类OrderConsumerApp
1.@SpringCloudApplication
: 组合注解:
@SpringBootApplication(启动SPringBoot程序)
、@EnableDiscoveryClient(开启服务注册与发现)
、@EnableCircuitBreaker(开启断路器)
2.@EnableFeignClients
: 开启Feign
客户端
package com.thinkingcao.order;
import org.springframework.boot.SpringApplication;
import org.springframework.cloud.client.SpringCloudApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
/**
* @desc: 订单服务-消费者
* @author: cao_wencao
* @date: 2020-04-29 17:50
*/
@SpringCloudApplication
@EnableFeignClients
public class OrderConsumerApp {
public static void main(String[] args) {
SpringApplication.run(OrderConsumerApp.class, args);
}
}
五、测试
地址: http://130.252.102.241:8012/getProduct/1010110
访问结果: Hello Nacos Discovery 1010110
六、源码
https://github.com/Thinkingcao/SpringCloudLearning/tree/master/springcloud-ribbon-hystrix
七、Spring Cloud Alibaba教程
1. 下一篇: 《Spring Cloud Alibaba教程五》- 使用Nacos实现分布式配置中心
2. Nacos官方文档: https://nacos.io/zh-cn/docs/what-is-nacos.html