From 5cb814a58c88607e1c813c3a53b8948df8efd73e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BD=97=E7=A5=A5?= <1366971433@qq.com> Date: Sat, 19 Jan 2019 15:43:37 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20README.md=20=E7=94=A8?= =?UTF-8?q?=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 23 +- spring-cloud/spring-cloud-feign/README.md | 378 ++++++++++++++++++ .../heibaiying/common/feign/ProductFeign.java | 2 +- .../feign/impl/CProductFeignImpl.java | 3 +- 4 files changed, 392 insertions(+), 14 deletions(-) create mode 100644 spring-cloud/spring-cloud-feign/README.md diff --git a/README.md b/README.md index 1c5b991..5788d48 100644 --- a/README.md +++ b/README.md @@ -66,18 +66,17 @@ spring-cloud:Finchley.SR2 ## 3. spring-cloud samples -| samples | 描述 | 官方文档 | -| ------------------------------------------------------------ | ----------------------------------- | ------------------------------------------------------------ | -| spring-cloud | 微服务简介与用例说明 | | -| [spring-cloud-Eureka](https://github.com/heibaiying/spring-samples-for-all/tree/master/spring-cloud/spring-cloud-eureka) | 服务的注册和发现 | [Service Discovery: Eureka Server](https://cloud.spring.io/spring-cloud-static/Finchley.SR2/multi/multi_spring-cloud-eureka-server.html) | -| [spring-cloud-Eureka-cluster](https://github.com/heibaiying/spring-samples-for-all/tree/master/spring-cloud/spring-cloud-eureka-cluster) | eureka 高可用集群搭建 | [Service Discovery: Eureka Server](https://cloud.spring.io/spring-cloud-static/Finchley.SR2/multi/multi_spring-cloud-eureka-server.html) | -| [spring-cloud-Ribbon](https://github.com/heibaiying/spring-samples-for-all/tree/master/spring-cloud/spring-cloud-ribbon) | RestTemplate的使用、客户端负载均衡 | [Client Side Load Balancer: Ribbon](https://cloud.spring.io/spring-cloud-static/Finchley.SR2/multi/multi_spring-cloud-ribbon.html) | -| [spring-cloud-OpenFeign](https://github.com/heibaiying/spring-samples-for-all/tree/master/spring-cloud/spring-cloud-feign) | 声明式服务调用 | [Declarative REST Client: Feign](https://cloud.spring.io/spring-cloud-static/Finchley.SR2/multi/multi_spring-cloud-feign.html) | -| [spring-cloud-Hystrix](https://github.com/heibaiying/spring-samples-for-all/tree/master/spring-cloud/spring-cloud-hystrix) | 熔断器、熔断器监控、turbine聚合监控 | [Circuit Breaker: Hystrix Clients](https://cloud.spring.io/spring-cloud-static/Finchley.SR2/multi/multi__circuit_breaker_hystrix_clients.html)
[Hystrix metrics aggregation with Turbine](https://cloud.spring.io/spring-cloud-static/Finchley.SR2/multi/multi_spring-cloud-consul-turbine.html) | -| [spring-cloud-zuul](https://github.com/heibaiying/spring-samples-for-all/tree/master/spring-cloud/spring-cloud-zuul) | 网关服务 | [Router and Filter: Zuul](https://cloud.spring.io/spring-cloud-static/Finchley.SR2/multi/multi__router_and_filter_zuul.html) | -| [spring-cloud-sleuth-Zipkin](https://github.com/heibaiying/spring-samples-for-all/tree/master/spring-cloud/spring-cloud-sleuth-zipkin) | 分布式系统服务追踪 | [Spring Cloud Sleuth](https://cloud.spring.io/spring-cloud-static/Finchley.SR2/multi/multi__introduction.html#sleuth-adding-project) | -| [spring-cloud-config-bus](https://github.com/heibaiying/spring-samples-for-all/tree/master/spring-cloud/spring-cloud-config) | 配置中心 + 消息总线实现配置热更新 | [Spring Cloud Config Client](https://cloud.spring.io/spring-cloud-static/Finchley.SR2/multi/multi__spring_cloud_config_client.html) | -| [spring-cloud-stream](https://github.com/heibaiying/spring-samples-for-all/tree/master/spring-cloud/spring-cloud-stream) | spring cloud 对消息服务的抽象整合 | [spring-cloud-stream](http://cloud.spring.io/spring-cloud-stream/single/spring-cloud-stream.html) | +| samples | 描述 | 官方文档 | +| ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | +| [spring-cloud-Eureka](https://github.com/heibaiying/spring-samples-for-all/tree/master/spring-cloud/spring-cloud-eureka) | eureka 服务的注册和发现 | [Service Discovery: Eureka Server](https://cloud.spring.io/spring-cloud-static/Finchley.SR2/multi/multi_spring-cloud-eureka-server.html) | +| [spring-cloud-Eureka-cluster](https://github.com/heibaiying/spring-samples-for-all/tree/master/spring-cloud/spring-cloud-eureka-cluster) | eureka 高可用集群搭建 | [Service Discovery: Eureka Server](https://cloud.spring.io/spring-cloud-static/Finchley.SR2/multi/multi_spring-cloud-eureka-server.html) | +| [spring-cloud-Ribbon](https://github.com/heibaiying/spring-samples-for-all/tree/master/spring-cloud/spring-cloud-ribbon) | ribbon客户端负载均衡 | [Client Side Load Balancer: Ribbon](https://cloud.spring.io/spring-cloud-static/Finchley.SR2/multi/multi_spring-cloud-ribbon.html) | +| [spring-cloud-OpenFeign](https://github.com/heibaiying/spring-samples-for-all/tree/master/spring-cloud/spring-cloud-feign) | openfeign 声明式服务调用 | [Declarative REST Client: Feign](https://cloud.spring.io/spring-cloud-static/Finchley.SR2/multi/multi_spring-cloud-feign.html) | +| [spring-cloud-Hystrix](https://github.com/heibaiying/spring-samples-for-all/tree/master/spring-cloud/spring-cloud-hystrix) | hystix 服务容错保护
hystrix dashboard 断路器监控
turbine 断路器聚合监控 | [Circuit Breaker: Hystrix Clients](https://cloud.spring.io/spring-cloud-static/Finchley.SR2/multi/multi__circuit_breaker_hystrix_clients.html)
[Hystrix metrics aggregation with Turbine ](https://cloud.spring.io/spring-cloud-static/Finchley.SR2/multi/multi_spring-cloud-consul-turbine.html) | +| [spring-cloud-zuul](https://github.com/heibaiying/spring-samples-for-all/tree/master/spring-cloud/spring-cloud-zuul) | zuul 网关服务 | [Router and Filter: Zuul](https://cloud.spring.io/spring-cloud-static/Finchley.SR2/multi/multi__router_and_filter_zuul.html) | +| [spring-cloud-sleuth-Zipkin](https://github.com/heibaiying/spring-samples-for-all/tree/master/spring-cloud/spring-cloud-sleuth-zipkin) | sleuth 分布式系统服务追踪 | [Spring Cloud Sleuth](https://cloud.spring.io/spring-cloud-static/Finchley.SR2/multi/multi__introduction.html#sleuth-adding-project) | +| [spring-cloud-config-bus](https://github.com/heibaiying/spring-samples-for-all/tree/master/spring-cloud/spring-cloud-config) | config 分布式配置中心
bus消息总线 实现配置热更新 | [Spring Cloud Config Client](https://cloud.spring.io/spring-cloud-static/Finchley.SR2/multi/multi__spring_cloud_config_client.html) | +| [spring-cloud-stream](https://github.com/heibaiying/spring-samples-for-all/tree/master/spring-cloud/spring-cloud-stream) | stream 对消息服务的抽象整合 | [spring-cloud-stream](http://cloud.spring.io/spring-cloud-stream/single/spring-cloud-stream.html) |
diff --git a/spring-cloud/spring-cloud-feign/README.md b/spring-cloud/spring-cloud-feign/README.md new file mode 100644 index 0000000..a43a738 --- /dev/null +++ b/spring-cloud/spring-cloud-feign/README.md @@ -0,0 +1,378 @@ +# spring-cloud-feign + +## 一、feign 简介 + +在上一个用例中,我们使用ribbon+restTemplate 实现服务之间的远程调用,实际上每一个调用都是模板化的内容,所以spring cloud Feign 在此基础上进行了进一步的封装。我们只需要定义一个接口并使用feign注解的方式来进行配置,同时采用springMvc 注解进行参数绑定就可以完成服务的调用。feign同时还内置实现了负载均衡、服务容错等功能。 + + + +## 二、项目结构 + ++ common: 公共的接口和实体类; ++ consumer: 服务的消费者,采用feign调用产品服务; ++ producer:服务的提供者; ++ eureka: 注册中心。 + +
+ + + + + +## 三、服务提供者的实现 + +
+ +#### 3.1 产品服务由`ProductService`提供,并通过`ProducerController`将服务暴露给外部调用。 + +ProductService.java: + +```java +/** + * @author : heibaiying + * @description : 产品提供接口实现类 + */ +@Service +public class ProductService implements IProductService, ApplicationListener { + + private static List productList = new ArrayList<>(); + + public Product queryProductById(int id) { + return productList.stream().filter(p->p.getId()==id).collect(Collectors.toList()).get(0); + } + + + public List queryAllProducts() { + return productList; + } + + @Override + public void saveProduct(Product product) { + productList.add(product); + } + + @Override + public void onApplicationEvent(WebServerInitializedEvent event) { + int port = event.getWebServer().getPort(); + for (long i = 0; i < 20; i++) { + productList.add(new Product(i, port + "产品" + i, i / 2 == 0, new Date(), 66.66f * i)); + } + } +} +``` + +ProducerController.java: + +```java +@RestController +public class ProducerController implements ProductFeign { + + @Autowired + private IProductService productService; + + @GetMapping("products") + public List productList() { + return productService.queryAllProducts(); + } + + @GetMapping("product/{id}") + public Product productDetail(@PathVariable int id) { + return productService.queryProductById(id); + } + + @PostMapping("product") + public void save(@RequestBody Product product) { + productService.saveProduct(product); + } +} +``` + +#### 3.2 指定注册中心地址,并在启动类上开启自动注册@EnableDiscoveryClient + +```java +server: + port: 8020 +# 指定服务命名 +spring: + application: + name: producer +# 指定注册中心地址 +eureka: + client: + serviceUrl: + defaultZone: http://localhost:8010/eureka/ +``` + +```java +@SpringBootApplication +@EnableDiscoveryClient +public class ProducerApplication { + + public static void main(String[] args) { + SpringApplication.run(ProducerApplication.class, args); + } + +} + +``` + + + +## 四、服务消费者的实现 + +
+ +#### 4.1 导入openfeign依赖 + +```xml + + + org.springframework.cloud + spring-cloud-starter-openfeign + +``` + +#### 4.2 指定注册中心地址,并在启动类上添加注解@EnableDiscoveryClient和@EnableFeignClients + +@EnableFeignClients 会去扫描工程中所有用 @FeignClient 声明的 feign 客户端。 + +```java +server: + port: 8080 +# 指定服务命名 +spring: + application: + name: consumer +# 指定注册中心地址 +eureka: + client: + serviceUrl: + defaultZone: http://localhost:8010/eureka/ +``` + +```java +@SpringBootApplication +@EnableDiscoveryClient +@EnableFeignClients +public class ConsumerApplication { + + public static void main(String[] args) { + SpringApplication.run(ConsumerApplication.class, args); + } + +} +``` + +#### 4.3 创建服务调用公共接口 + +```java +/** + * @author : heibaiying + * @description : 声明式服务调用 + */ +public interface ProductFeign { + + @GetMapping("products") + List productList(); + + /** + * 这是需要强调的是使用feign时候@PathVariable一定要用value指明参数, + * 不然会抛出.IllegalStateException: PathVariable annotation was empty on param 异常 + */ + @GetMapping("product/{id}") + Product productDetail(@PathVariable(value = "id") int id); + + + @PostMapping("product") + void save(@RequestBody Product product); +} + +``` + +按照官方对于服务最佳化的推荐,这里我们的服务调用接口放在公共模块中,因为在实际的开发中,同一个服务调用接口可能被多个模块所使用。 + +
+ + + +#### 4.4 继承公共接口,创建CProductFeign, 用@FeignClient声明为feign客户端 + +```java +/** + * @author : heibaiying + * @description : 声明式接口调用 + */ +@FeignClient(value = "producer",configuration = FeignConfig.class) +public interface CProductFeign extends ProductFeign { + +} +``` + +#### 4.5 注入使用 feign 服务调用接口 + +```java +@Controller +@RequestMapping("sell") +public class SellController { + + @Autowired + private CProductFeign cproductFeign; + + @GetMapping("products") + public String productList(Model model) { + List products = cproductFeign.productList(); + model.addAttribute("products", products); + return "products"; + } + + @GetMapping("product/{id}") + public String productDetail(@PathVariable int id, Model model) { + Product product = cproductFeign.productDetail(id); + model.addAttribute("product", product); + return "product"; + } + + + @PostMapping("product") + public String save(@RequestParam String productName) { + long id = Math.round(Math.random() * 100); + Product product = new Product(id, productName, false, new Date(), 88); + cproductFeign.save(product); + return "redirect:products"; + } +} +``` + + + +## 五、启动测试 + +#### 5.1 启动一个Eureka服务、三个producer服务(注意区分端口)、和一个消费者服务 + +feign 的依赖中导入了spring-cloud-starter-netflix-ribbon依赖,并且在内部实现了基于ribbon的客户端负载均衡,所以我们这里启动三个producer实例来观察负载均衡的情况。 + +
+ +**服务注册中心:** + +
+ +#### 5.2 访问http://localhost:8080/sell/products 查看负载均衡的调用结果 + +
+ +
+ +
+ + + + + +## 六、 feign 的服务容错 + +#### 6.1 feign 的依赖中默认导入了hystrix 的相关依赖,我们不需要额外导入,只需要开启相关配置即可 + +
+ + + +#### 6.2 在application.yml 中开启hystrix + +```yml +feign: + hystrix: + # 如果为true,则OpenFign客户端将使用Hystrix断路器进行封装 默认为false + enabled: true +``` + +#### 6.3 创建`CProductFeignImpl`,继承feign接口(CProductFeign),定义熔断时候的回退处理 + +```java +/** + * @author : heibaiying + * @description : 定义发生熔断时候的回退处理。除了继承自CProductFeign,还需要用@Component声明为spring的组件 + */ +@Component +public class CProductFeignImpl implements CProductFeign { + + // 发生熔断时候,返回空集合,前端页面会做容错显示 + @Override + public List productList() { + return new ArrayList<>(); + } + + @Override + public Product productDetail(int id) { + return null; + } + + @Override + public void save(Product product) { + + } +} +``` + +页面的简单容错处理: + +```html + + + + 产品列表 + + +

产品列表:点击查看详情

+
+ + +
+
    + <#if (products?size>0) > + <#list products as product> +
  • + ${product.name} +
  • + + <#else> +

    当前排队人数过多,请之后再购买!

    + +
+ + +``` + +#### 6.4 在 @FeignClient 注解中,用fallback参数指定熔断时候的回退处理 + +```java +/** + * @author : heibaiying + * @description : 声明式接口调用 + */ +@FeignClient(value = "producer",configuration = FeignConfig.class,fallback = CProductFeignImpl.class) +public interface CProductFeign extends ProductFeign { + +} +``` + +#### 6.5 测试熔断处理 + +hystrix 默认调用超时时间为2s ,这里我们使用线程休眠的方式来模拟超时熔断。 + +```java +public List queryAllProducts() { + /*用于测试 hystrix 超时熔断 + try { + int i = new Random().nextInt(2500); + Thread.sleep(i); + } catch (InterruptedException e) { + e.printStackTrace(); + }*/ + return productList; +} +``` + +测试结果: + +
\ No newline at end of file diff --git a/spring-cloud/spring-cloud-feign/common/src/main/java/com/heibaiying/common/feign/ProductFeign.java b/spring-cloud/spring-cloud-feign/common/src/main/java/com/heibaiying/common/feign/ProductFeign.java index ddcb2e3..02a328b 100644 --- a/spring-cloud/spring-cloud-feign/common/src/main/java/com/heibaiying/common/feign/ProductFeign.java +++ b/spring-cloud/spring-cloud-feign/common/src/main/java/com/heibaiying/common/feign/ProductFeign.java @@ -7,7 +7,7 @@ import java.util.List; /** * @author : heibaiying - * @description : 声明式接口调用 + * @description : 声明式服务调用 */ public interface ProductFeign { diff --git a/spring-cloud/spring-cloud-feign/consumer/src/main/java/com/heibaiying/consumer/feign/impl/CProductFeignImpl.java b/spring-cloud/spring-cloud-feign/consumer/src/main/java/com/heibaiying/consumer/feign/impl/CProductFeignImpl.java index 8196a8e..6060bbc 100644 --- a/spring-cloud/spring-cloud-feign/consumer/src/main/java/com/heibaiying/consumer/feign/impl/CProductFeignImpl.java +++ b/spring-cloud/spring-cloud-feign/consumer/src/main/java/com/heibaiying/consumer/feign/impl/CProductFeignImpl.java @@ -9,11 +9,12 @@ import java.util.List; /** * @author : heibaiying - * @description : 定义发生错误时候的熔断处理。除了继承自CProductFeign,还需要用@Component声明为spring的组件 + * @description : 定义发生熔断时候的回退处理。除了继承自CProductFeign,还需要用@Component声明为spring的组件 */ @Component public class CProductFeignImpl implements CProductFeign { + // 发生熔断时候,返回空集合,前端页面会做容错显示 @Override public List productList() { return new ArrayList<>();