1.今日内容

  • Feign 声明式服务调用
  • Hystrix 熔断器
  • Gateway 网关

2.Feign

2.1-Feign-概述

• Feign 是一个声明式的 REST 客户端,它用了基于接口的注解方式,很方便实现客户端配置。取代了restTemplate类
• Feign 最初由 Netflix 公司提供,但不支持SpringMVC注解,后由 SpringCloud 对其封装,支持了SpringMVC注解,让使用者更易于接受
1587540970425.png

2.2-Feign-快速入门

  1. 在消费端引入 open-feign 依赖
  1. <!--feign-->
  2. <dependency>
  3. <groupId>org.springframework.cloud</groupId>
  4. <artifactId>spring-cloud-starter-openfeign</artifactId>
  5. </dependency>
  1. 编写Feign调用接口
  1. package com.itheima.consumer.feign;
  2. import com.itheima.consumer.config.FeignLogConfig;
  3. import com.itheima.consumer.domain.Goods;
  4. import org.springframework.cloud.openfeign.FeignClient;
  5. import org.springframework.web.bind.annotation.GetMapping;
  6. import org.springframework.web.bind.annotation.PathVariable;
  7. /**
  8. *
  9. * feign声明式接口。发起远程调用的。
  10. *
  11. String url = "http://FEIGN-PROVIDER/goods/findOne/"+id;
  12. Goods goods = restTemplate.getForObject(url, Goods.class);
  13. *
  14. * 1. 定义接口
  15. * 2. 接口上添加注解 @FeignClient,设置value属性为 服务提供者的应用名称
  16. * 3. 编写调用接口,接口的声明规则和提供方接口保持一致。
  17. * 4. 注入该接口对象,调用接口方法完成远程调用
  18. */
  19. @FeignClient(value = "FEIGN-PROVIDER")
  20. public interface GoodsFeignClient {
  21. @GetMapping("/goods/findOne/{id}")
  22. public Goods findGoodsById(@PathVariable("id") int id);
  23. }

OrderController

  1. package com.itheima.consumer.controller;
  2. import com.itheima.consumer.domain.Goods;
  3. import com.itheima.consumer.feign.GoodsFeignClient;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.web.bind.annotation.GetMapping;
  6. import org.springframework.web.bind.annotation.PathVariable;
  7. import org.springframework.web.bind.annotation.RequestMapping;
  8. import org.springframework.web.bind.annotation.RestController;
  9. import org.springframework.web.client.RestTemplate;
  10. @RestController
  11. @RequestMapping("/order")
  12. public class OrderController {
  13. @Autowired
  14. private RestTemplate restTemplate;
  15. //注入feign接口
  16. @Autowired
  17. private GoodsFeignClient goodsFeignClient;
  18. @GetMapping("/goods/{id}")
  19. public Goods findGoodsById(@PathVariable("id") int id){
  20. /*
  21. String url = "http://FEIGN-PROVIDER/goods/findOne/"+id;
  22. // 3. 调用方法
  23. Goods goods = restTemplate.getForObject(url, Goods.class);
  24. return goods;*/
  25. //通过接口调用方法进行远程调用
  26. Goods goods = goodsFeignClient.findGoodsById(id);
  27. return goods;
  28. }
  29. }

goodsFeignClient报红,不影响使用,配置feign底层实现了Javase的动态代理及反射原理
1587541824858.png

  1. 在启动类 添加 @EnableFeignClients 注解,开启Feign功能
  1. package com.itheima.consumer;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
  5. import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
  6. import org.springframework.cloud.openfeign.EnableFeignClients;
  7. @EnableDiscoveryClient // 激活DiscoveryClient
  8. @EnableEurekaClient
  9. @SpringBootApplication
  10. @EnableFeignClients //开启Feign的功能
  11. public class ConsumerApp {
  12. public static void main(String[] args) {
  13. SpringApplication.run(ConsumerApp.class,args);
  14. }
  15. }
  1. 测试调用

2.3-Feign超时配置

• Feign 底层依赖于 Ribbon 实现负载均衡和远程调用。
• Ribbon默认1秒超时。
• 超时配置:

feign-consumer application.yml

  1. # 设置Ribbon的超时时间
  2. ribbon:
  3. ConnectTimeout: 1000 # 连接超时时间 默认1s 默认单位毫秒
  4. ReadTimeout: 3000 # 逻辑处理的超时时间(响应时间超时) 默认1s 默认单位毫秒

2.4-Feign-日志记录

• Feign 只能记录 debug 级别的日志信息。

feign-consumer application.yml

  1. # 设置当前的日志级别 debug,feign只支持记录debug级别的日志
  2. logging:
  3. level:
  4. com.itheima: debug

• 定义Feign日志级别Bean

FeignLogConfig

  1. package com.itheima.consumer.config;
  2. import feign.Logger;
  3. import org.springframework.context.annotation.Bean;
  4. import org.springframework.context.annotation.Configuration;
  5. @Configuration
  6. public class FeignLogConfig {
  7. /*
  8. NONE,不记录
  9. BASIC,记录基本的请求行,响应状态码数据
  10. HEADERS,记录基本的请求行,响应状态码数据,记录响应头信息
  11. FULL;记录完成的请求 响应数据
  12. */
  13. @Bean
  14. public Logger.Level level(){
  15. return Logger.Level.FULL;
  16. }
  17. }

• 启用该Bean:

  1. package com.itheima.consumer.feign;
  2. import com.itheima.consumer.config.FeignLogConfig;
  3. import com.itheima.consumer.domain.Goods;
  4. import org.springframework.cloud.openfeign.FeignClient;
  5. import org.springframework.web.bind.annotation.GetMapping;
  6. import org.springframework.web.bind.annotation.PathVariable;
  7. /**
  8. *
  9. * feign声明式接口。发起远程调用的。
  10. *
  11. String url = "http://FEIGN-PROVIDER/goods/findOne/"+id;
  12. Goods goods = restTemplate.getForObject(url, Goods.class);
  13. *
  14. * 1. 定义接口
  15. * 2. 接口上添加注解 @FeignClient,设置value属性为 服务提供者的 应用名称
  16. * 3. 编写调用接口,接口的声明规则 和 提供方接口保持一致。
  17. * 4. 注入该接口对象,调用接口方法完成远程调用
  18. */
  19. @FeignClient(value = "FEIGN-PROVIDER",configuration = FeignLogConfig.class)
  20. public interface GoodsFeignClient {
  21. @GetMapping("/goods/findOne/{id}")
  22. public Goods findGoodsById(@PathVariable("id") int id);
  23. }

3.Hystrix

3.1-Hystrix-概述

• Hystix 是 Netflix 开源的一个延迟和容错库,用于隔离访问远程服务、第三方库,防止出现级联失败(雪崩)。
• 雪崩:一个服务失败,导致整条链路的服务都失败的情形

Hystix 主要功能
• 隔离

  • 线程池隔离
  • 信号量隔离

• 降级:异常,超时
• 熔断
• 限流
1587542720216.png
1587542762104.png

3.2-Hystrix-降级

3.2.1-提供方降级

Hystix 降级:当服务发生异常或调用超时,返回默认数据

服务提供方降级

  1. 在服务提供方,引入 hystrix 依赖```xml
    1. <!-- hystrix -->
    2. <dependency>
    3. <groupId>org.springframework.cloud</groupId>
    4. <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
    5. </dependency>
    ```
  1. 服务者提供方法启动类 : 类上标注@EnableCircuitBreaker注解

    1. @EnableEurekaClient
    2. @SpringBootApplication
    3. @EnableCircuitBreaker
    4. public class ProviderApp{
    5. public static void main(String[]args){
    6. SpringApplication.run(ProviderApp.class,args);
    7. }
    8. }
  2. 在服务者提供方的controller中定义降级方法

  1. /**
  2. * 定义降级方法:
  3. * 1. 方法的返回值需要和原方法一样
  4. * 2. 方法的参数需要和原方法一样
  5. */
  6. public Goods findOne_fallback(int id){
  7. Goods goods = new Goods();
  8. goods.setTitle("降级了~~~");
  9. return goods;
  10. }
  1. 在服务者提供方的controller中的业务方法上 使用 @HystrixCommand 注解配置降级方法 (该注解的实现原理:基于AOP(动态代理),参见: https://www.wangshouyu.com/archives/hystrix-javanica-source)
  1. /**
  2. * 降级:
  3. * 1. 出现异常
  4. * 2. 服务调用超时
  5. * * 默认1s超时
  6. *
  7. * @HystrixCommand(fallbackMethod = "findOne_fallback")
  8. * fallbackMethod:指定降级后调用的方法名称
  9. */
  10. @GetMapping("/findOne/{id}")
  11. @HystrixCommand(fallbackMethod = "findOne_fallback",commandProperties = {
  12. //设置Hystrix的超时时间,默认1s
  13. @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value = "3000")
  14. })
  15. public Goods findOne(@PathVariable("id") int id){
  16. //1.造个异常
  17. int i = 3/0;
  18. try {
  19. //2. 休眠2秒
  20. Thread.sleep(2000);
  21. } catch (InterruptedException e) {
  22. e.printStackTrace();
  23. }
  24. Goods goods = goodsService.findOne(id);
  25. goods.setTitle(goods.getTitle() + ":" + port);//将端口号,设置到了 商品标题上
  26. return goods;
  27. }
  1. 在启动类上开启Hystrix功能:@EnableCircuitBreaker
  1. package com.itheima.provider;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
  5. import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
  6. /**
  7. * 启动类
  8. */
  9. @EnableEurekaClient //该注解 在新版本中可以省略
  10. @SpringBootApplication
  11. @EnableCircuitBreaker // 开启Hystrix功能
  12. public class ProviderApp {
  13. public static void main(String[] args) {
  14. SpringApplication.run(ProviderApp.class,args);
  15. }
  16. }

3.2.2-消费方降级

  1. feign 组件已经集成了 hystrix 组件。
  2. 定义feign 调用接口实现类,重写方法,即降级方法
  • 编写实现类GoodsFeignClientFallback
  1. package com.itheima.consumer.feign;
  2. import com.itheima.consumer.domain.Goods;
  3. import org.springframework.stereotype.Component;
  4. /**
  5. * Feign 客户端的降级处理类
  6. * 1. 定义类 实现 Feign 客户端接口
  7. * 2. 使用@Component注解将该类的Bean加入SpringIOC容器
  8. */
  9. @Component
  10. public class GoodsFeignClientFallback implements GoodsFeignClient {
  11. @Override
  12. public Goods findGoodsById(int id) {
  13. Goods goods = new Goods();
  14. goods.setTitle("又被降级了~~~");
  15. return goods;
  16. }
  17. }
  1. @FeignClient 注解中使用 fallback 属性设置降级处理类。
    编写接口GoodsFeignClient
  1. package com.itheima.consumer.feign;
  2. import com.itheima.consumer.domain.Goods;
  3. import org.springframework.cloud.openfeign.FeignClient;
  4. import org.springframework.web.bind.annotation.GetMapping;
  5. import org.springframework.web.bind.annotation.PathVariable;
  6. //value值指定的是服务提供者应用名称,fallback的值指定的是降级的类它实现了该接口
  7. @FeignClient(value = "HYSTRIX-PROVIDER",fallback = GoodsFeignClientFallback.class)
  8. public interface GoodsFeignClient {
  9. @GetMapping("/goods/findOne/{id}")
  10. public Goods findGoodsById(@PathVariable("id") int id);
  11. }
  1. 配置开启 feign.hystrix.enabled = true
    application.yml
  1. # 开启feign对hystrix的支持
  2. feign:
  3. hystrix:
  4. enabled: true

3.3-Hystrix-熔断

3.3.1-熔断-概念

• Hystrix 熔断机制,用于监控微服务调用情况,当失败的情况达到预定的阈值(5秒失败20次),会打开
断路器,拒绝所有请求,直到服务恢复正常为止。

断路器三种状态:打开、半开、关闭。
详细的熔断器的工作原理:hystrix基于微服务调用监控数据,当调用失败率达到设定的值,就打开断路器(针对目标服务),之后,调用方会拒绝发起该服务所有的请求调用(因为就算调用也大概率上不会有好的结果,白白浪费资源而已),一段时间后,断路器会处于半开状态,会有少量的请求尝试调用,会根据调用的结果判断,断路器是继续打开(服务依旧不可用)还是关闭(目标服务恢复正常)。
1587543649656.png

3.3.2-熔断-代码演示

修改服务提供方的方法,演示熔断机制

熔断配置

• circuitBreaker.sleepWindowInMilliseconds:监控时间
• circuitBreaker.requestVolumeThreshold:失败次数
• circuitBreaker.errorThresholdPercentage:失败率

服务提供者的GoodsController

  1. package com.itheima.provider.controller;
  2. import com.itheima.provider.domain.Goods;
  3. import com.itheima.provider.service.GoodsService;
  4. import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
  5. import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
  6. import org.springframework.beans.factory.annotation.Autowired;
  7. import org.springframework.beans.factory.annotation.Value;
  8. import org.springframework.web.bind.annotation.GetMapping;
  9. import org.springframework.web.bind.annotation.PathVariable;
  10. import org.springframework.web.bind.annotation.RequestMapping;
  11. import org.springframework.web.bind.annotation.RestController;
  12. import java.util.Date;
  13. /**
  14. * Goods Controller 服务提供方
  15. */
  16. @RestController
  17. @RequestMapping("/goods")
  18. public class GoodsController {
  19. @Autowired
  20. private GoodsService goodsService;
  21. @Value("${server.port}")
  22. private int port;
  23. /**
  24. * 降级:
  25. * 1. 出现异常
  26. * 2. 服务调用超时
  27. * * 默认1s超时
  28. *
  29. * @HystrixCommand(fallbackMethod = "findOne_fallback")
  30. * fallbackMethod:指定降级后调用的方法名称
  31. */
  32. @GetMapping("/findOne/{id}")
  33. @HystrixCommand(fallbackMethod = "findOne_fallback",commandProperties = {
  34. //设置Hystrix的超时时间,默认1s
  35. @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value = "3000"),
  36. //监控时间 默认5000 毫秒
  37. @HystrixProperty(name="circuitBreaker.sleepWindowInMilliseconds",value = "5000"),
  38. //失败次数。默认20次
  39. @HystrixProperty(name="circuitBreaker.requestVolumeThreshold",value = "20"),
  40. //失败率 默认50%
  41. @HystrixProperty(name="circuitBreaker.errorThresholdPercentage",value = "50") })
  42. public Goods findOne(@PathVariable("id") int id){
  43. //如果id == 1 ,则出现异常,id != 1 则正常访问
  44. if(id == 1){
  45. //1.造个异常
  46. int i = 3/0;
  47. }
  48. /*try {
  49. //2. 休眠2秒
  50. Thread.sleep(2000);
  51. } catch (InterruptedException e) {
  52. e.printStackTrace();
  53. }*/
  54. Goods goods = goodsService.findOne(id);
  55. goods.setTitle(goods.getTitle() + ":" + port);//将端口号,设置到了 商品标题上
  56. return goods;
  57. }
  58. /**
  59. * 定义降级方法:
  60. * 1. 方法的返回值需要和原方法一样
  61. * 2. 方法的参数需要和原方法一样
  62. */
  63. public Goods findOne_fallback(int id){
  64. Goods goods = new Goods();
  65. goods.setTitle("降级了~~~");
  66. return goods;
  67. }
  68. }

3.3.3-熔断监控

• Hystrix 提供了 Hystrix-dashboard 功能,用于实时监控微服务运行状态。
• 但是Hystrix-dashboard只能监控一个微服务。
• Netflix 还提供了 Turbine ,进行聚合监控。
1587544649322.png

(1)熔断器监控安装

  • 在父工程下面搭建hystrix-monitor模块,使用Turbine聚合监控多个hystrix-dashboard功能 ```xml

    <?xml version=”1.0” encoding=”UTF-8”?> <project xmlns=”http://maven.apache.org/POM/4.0.0

    1. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    2. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

    1. <artifactId>hystrix-parent</artifactId>
    2. <groupId>com.itheima</groupId>
    3. <version>1.0-SNAPSHOT</version>

    4.0.0

    hystrix-monitor

    UTF-8 UTF-8 1.8

    1. <dependency>
    2. <groupId>org.springframework.cloud</groupId>
    3. <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
    4. </dependency>
    5. <dependency>
    6. <groupId>org.springframework.cloud</groupId>
    7. <artifactId>spring-cloud-starter-netflix-turbine</artifactId>
    8. </dependency>
    9. <dependency>
    10. <groupId>org.springframework.boot</groupId>
    11. <artifactId>spring-boot-starter-actuator</artifactId>
    12. </dependency>
    13. <dependency>
    14. <groupId>org.springframework.cloud</groupId>
    15. <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    16. </dependency>
  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-test</artifactId>
  4. <scope>test</scope>
  5. </dependency>
  6. </dependencies>
  7. <build>
  8. <plugins>
  9. <plugin>
  10. <groupId>org.springframework.boot</groupId>
  11. <artifactId>spring-boot-maven-plugin</artifactId>
  12. </plugin>
  13. </plugins>
  14. </build>

  1. - 修改hystrix-montior模块下的application.yml文件
  2. ```yaml
  3. spring:
  4. application.name: hystrix-monitor
  5. server:
  6. port: 8769
  7. turbine:
  8. combine-host-port: true
  9. # 配置需要监控的服务名称列表
  10. app-config: hystrix-provider,hystrix-consumer
  11. cluster-name-expression: "'default'"
  12. aggregator:
  13. cluster-config: default
  14. #instanceUrlSuffix: /actuator/hystrix.stream
  15. eureka:
  16. client:
  17. serviceUrl:
  18. defaultZone: http://localhost:8761/eureka/ # eureka服务的地址
  • 创建启动类 ```java

@SpringBootApplication @EnableEurekaClient //指定eureka的客户端

@EnableTurbine //开启Turbine 很聚合监控功能 @EnableHystrixDashboard //开启Hystrix仪表盘监控功能 public class HystrixMonitorApp {

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

}

  1. - 修改被监控的模块(分别修改provider模块和consumer模块)
  2. - 导入依赖
  3. ```xml
  4. <dependency>
  5. <groupId>org.springframework.boot</groupId>
  6. <artifactId>spring-boot-starter-actuator</artifactId>
  7. </dependency>
  8. <dependency>
  9. <groupId>org.springframework.cloud</groupId>
  10. <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
  11. </dependency>
  12. <dependency>
  13. <groupId>org.springframework.cloud</groupId>
  14. <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
  15. </dependency>
  • 分别在服务提供方和服务消费方配置bean(为了方便配置在启动类中)并在启动类上添加@EnableHystrixDashboard注解 ```java @EnableDiscoveryClient @EnableEurekaClient @SpringBootApplication @EnableFeignClients @EnableHystrixDashboard // 开启Hystrix仪表盘监控功能 public class ConsumerApp {
  1. public static void main(String[] args) {
  2. SpringApplication.run(ConsumerApp.class,args);
  3. }

@Bean public ServletRegistrationBean getServlet() { HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet(); ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet); registrationBean.setLoadOnStartup(1); registrationBean.addUrlMappings(“/actuator/hystrix.stream”); registrationBean.setName(“HystrixMetricsStreamServlet”); return registrationBean; }

  1. 2)启动测试
  2. - 启动模块的顺序
  3. - eureka-server
  4. - hystrix-provider
  5. - hystrix-consumer
  6. - hystrix-monitor
  7. - 访问:
  8. - 在浏览器访问[http://localhost:8769/hystrix/](http://localhost:8769/hystrix/) 进入Hystrix Dashboard界面
  9. ![1585421193757.png](https://cdn.nlark.com/yuque/0/2021/png/12492094/1614853826398-54e606b3-41c3-477e-b575-8e1d0ef837d8.png#align=left&display=inline&height=576&margin=%5Bobject%20Object%5D&name=1585421193757.png&originHeight=576&originWidth=1197&size=112531&status=done&style=none&width=1197)![1585421278837.png](https://cdn.nlark.com/yuque/0/2021/png/12492094/1614853871803-9a28fc7c-ea30-43ef-b5a0-f3604c2d4bf0.png#align=left&display=inline&height=417&margin=%5Bobject%20Object%5D&name=1585421278837.png&originHeight=417&originWidth=1169&size=54043&status=done&style=none&width=1169)
  10. - 实心圆:它有颜色和大小之分,分别代表实例的监控程度和流量大小。如上图所示,它的健康度从绿色、黄色、橙色、红色递减。通过该实心圆的展示,我们就可以在大量的实例中快速的发现故障实例和高压力实例。
  11. - 曲线:用来记录 2 分钟内流量的相对变化,我们可以通过它来观察到流量的上升和下降趋势。![1167856120180.png](https://cdn.nlark.com/yuque/0/2021/png/12492094/1614854013954-cc3ee19b-db6d-4eff-83a1-aeb6e40073f1.png#align=left&display=inline&height=274&margin=%5Bobject%20Object%5D&name=1167856120180.png&originHeight=274&originWidth=585&size=182877&status=done&style=none&width=585)
  12. <br />
  13. ![1587544516031.png](https://cdn.nlark.com/yuque/0/2021/png/12492094/1614854998560-444bacd3-7ed0-42c2-a51e-e10393db9db1.png#align=left&display=inline&height=776&margin=%5Bobject%20Object%5D&name=1587544516031.png&originHeight=776&originWidth=1908&size=403687&status=done&style=none&width=1908)
  14. <a name="4.Gateway"></a>
  15. # 4.Gateway
  16. <a name="6ad14751"></a>
  17. ## 4.1-Gateway-概述
  18. - 网关旨在为微服务架构提供一种简单而有效的统一的API路由管理方式。
  19. - 在微服务架构中,不同的微服务可以有不同的网络地址,各个微服务之间通过互相调用完成用户请求,客户端可能通过调用N个微服务的接口完成一个用户请求。
  20. - 存在的问题:
  21. ```yaml
  22. 1.客户端多次请求不同的微服务,增加客户端的复杂性
  23. 2.认证复杂,每个服务都要进行认证
  24. 3.http请求不同服务次数增加,性能不高
  • 网关就是系统的入口,封装了应用程序的内部结构,为客户端提供统一服务调用入口(外网只需要暴露网关端口即可),降低客户端访问的复杂性(网关参与进来形成微服务闭环),一些与业务本身功能无关的公共逻辑可以在这里实现,诸如网关统一身份认证校验、鉴权、缓存、流量管控、路由转发、结合注册中心服务发现实现负载均衡、统一接口日志及监控等。
  • 在目前的网关解决方案里,有Nginx+ Lua、Netflix Zuul 、Spring Cloud Gateway等等

1587544847831.png

  • 网关在微服务架构中的图解

微服务架构图.png

4.2-Gateway-快速入门

  1. 搭建网关模块
    创建api-gateway-server模块
  2. 引入依赖:starter-gateway```xml

    1. <!--引入gateway 网关-->
    2. <dependency>
    3. <groupId>org.springframework.cloud</groupId>
    4. <artifactId>spring-cloud-starter-gateway</artifactId>
    5. </dependency>
    6. <!-- eureka-client -->
    7. <dependency>
    8. <groupId>org.springframework.cloud</groupId>
    9. <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    10. </dependency>

    ```

  3. 编写启动类```java package com.itheima.gateway;

import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

@SpringBootApplication @EnableEurekaClient public class ApiGatewayApp {

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

}

  1. 4. 编写配置文件<br />application.yml```yaml
  2. server:
  3. port: 80
  4. spring:
  5. application:
  6. name: api-gateway-server
  7. cloud:
  8. # 网关配置
  9. gateway:
  10. # 路由配置:转发规则
  11. routes: #集合。
  12. # id: 唯一标识。默认是一个UUID
  13. # uri: 转发路径
  14. # predicates: 条件,用于请求网关路径的匹配规则
  15. - id: gateway-provider
  16. uri: http://localhost:8001/
  17. predicates:
  18. - Path=/goods/**
  1. 启动测试

4.3-Gateway-静态路由

application.yml 中的uri是写死的,就是静态路由

  1. server:
  2. port: 80
  3. spring:
  4. application:
  5. name: api-gateway-server
  6. cloud:
  7. # 网关配置
  8. gateway:
  9. # 路由配置:转发规则
  10. routes: #集合。
  11. # id: 唯一标识。默认是一个UUID
  12. # uri: 转发路径
  13. # predicates: 条件,用于请求网关路径的匹配规则
  14. # filters:配置局部过滤器的
  15. - id: gateway-provider
  16. # 静态路由
  17. uri: http://localhost:8001/
  18. predicates:
  19. - Path=/goods/**

4.4-Gateway-动态路由

启动类添加@EnableEurekaClient(新版本不加也可以)

  1. package com.itheima.gateway;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
  5. @SpringBootApplication
  6. @EnableEurekaClient
  7. public class ApiGatewayApp {
  8. public static void main(String[] args) {
  9. SpringApplication.run(ApiGatewayApp.class,args);
  10. }
  11. }

引入eureka-client配置

application.yml 中修改uri属性:uri: lb://服务名称

  1. server:
  2. port: 80
  3. spring:
  4. application:
  5. name: api-gateway-server
  6. cloud:
  7. # 网关配置
  8. gateway:
  9. # 路由配置:转发规则
  10. routes: #集合。
  11. # id: 唯一标识。默认是一个UUID
  12. # uri: 转发路径
  13. # predicates: 条件,用于请求网关路径的匹配规则
  14. # filters:配置局部过滤器的
  15. - id: gateway-provider
  16. # 静态路由
  17. # uri: http://localhost:8001/
  18. # 动态路由
  19. uri: lb://GATEWAY-PROVIDER
  20. predicates:
  21. - Path=/goods/**

4.5-Gateway-微服务名称配置

1587545848975.png

application.yml中配置微服务名称配置

  1. # 微服务名称配置
  2. discovery:
  3. locator:
  4. enabled: true # 设置为true 请求路径前可以添加微服务名称
  5. lower-case-service-id: true # 允许为小写

4.6-Gateway-过滤器

4.6.1-过滤器-概述

  • Gateway 支持过滤器功能,对请求或响应进行拦截,完成一些通用操作。
  • Gateway 提供两种过滤器方式:“pre”和“post”
    pre 过滤器,在转发之前执行,可以做参数校验、权限校验、流量监控、日志输出、协议转换等。
    post 过滤器,在响应之前执行,可以做响应内容、响应头的修改,日志的输出,流量监控等。
  • Gateway 还提供了两种类型过滤器
    GatewayFilter:局部过滤器,针对单个路由
    GlobalFilter :全局过滤器,针对所有路由

1587546321584.png

4.6.2-局部过滤器

  • GatewayFilter 局部过滤器,是针对单个路由的过滤器。
  • 在Spring Cloud Gateway 组件中提供了大量内置的局部过滤器,对请求和响应做过滤操作。
  • 遵循约定大于配置的思想,只需要在配置文件配置局部过滤器名称,并为其指定对应的值,就可以让其生效。

具体配置参见gateway内置过滤器工厂.md

测试配置

api-gateway-server application.yml

  1. server:
  2. port: 80
  3. spring:
  4. application:
  5. name: api-gateway-server
  6. cloud:
  7. # 网关配置
  8. gateway:
  9. # 路由配置:转发规则
  10. routes: #集合。
  11. # id: 唯一标识。默认是一个UUID
  12. # uri: 转发路径
  13. # predicates: 条件,用于请求网关路径的匹配规则
  14. # filters:配置局部过滤器的
  15. - id: gateway-provider
  16. # 静态路由
  17. # uri: http://localhost:8001/
  18. # 动态路由
  19. uri: lb://GATEWAY-PROVIDER
  20. predicates:
  21. - Path=/goods/**
  22. filters:
  23. - AddRequestParameter=username,zhangsan

gateway-provider模块中GoodsController中的findOne添加username参数

  1. public Goods findOne(@PathVariable("id") int id,String username){
  2. System.out.println(username);
  3. //如果id == 1 ,则出现异常,id != 1 则正常访问
  4. if(id == 1){
  5. //1.造个异常
  6. int i = 3/0;
  7. }
  8. /*try {
  9. //2. 休眠2秒
  10. Thread.sleep(2000);
  11. } catch (InterruptedException e) {
  12. e.printStackTrace();
  13. }*/
  14. Goods goods = goodsService.findOne(id);
  15. goods.setTitle(goods.getTitle() + ":" + port);//将端口号,设置到了 商品标题上
  16. return goods;
  17. }

4.6.3-全局过滤器

  • GlobalFilter 全局过滤器,不需要在配置文件中配置,系统初始化时加载,并作用在每个路由上。
  • Spring Cloud Gateway 核心的功能也是通过内置的全局过滤器来完成。
  • 自定义全局过滤器步骤:
    1. 定义类实现 GlobalFilter 和 Ordered接口
    2. 复写方法
    3. 完成逻辑处理

1587546455139.png

MyFilter
1587546455139.png

  1. package com.itheima.gateway.filter;
  2. import org.springframework.cloud.gateway.filter.GatewayFilterChain;
  3. import org.springframework.cloud.gateway.filter.GlobalFilter;
  4. import org.springframework.core.Ordered;
  5. import org.springframework.stereotype.Component;
  6. import org.springframework.web.server.ServerWebExchange;
  7. import reactor.core.publisher.Mono;
  8. @Component
  9. public class MyFilter implements GlobalFilter, Ordered {
  10. @Override
  11. public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
  12. System.out.println("自定义全局过滤器执行了~~~");
  13. return chain.filter(exchange);//放行
  14. }
  15. /**
  16. * 过滤器排序
  17. * @return 数值越小 越先执行
  18. */
  19. @Override
  20. public int getOrder() {
  21. return 0;
  22. }
  23. }