当前位置:   article > 正文

SpringCloud - Spring Cloud 之 Gateway网关(十三)_spring-cloud-starter-gateway

spring-cloud-starter-gateway

阅读本文前可先参考

​​​​​​SpringCloud - Spring Cloud根/父项目,开发准备(二)_MinggeQingchun的博客-CSDN博客

一、API网关

引自百度百科

API网关,软件术语,两个相互独立的局域网之间通过路由器进行通信,中间的路由被称之为网关

任何一个应用系统如果需要被其他系统调用,就需要暴露 API,这些 API 代表着一个一个的功能点。

如果两个系统中间通信,在系统之间加上一个中介者协助 API 的调用,这个中介者就是 API 网关

API 网关是一个搭建在客户端和微服务之间的服务,我们可以在 API 网关中处理一些非业务功能的逻辑,例如权限验证、监控、缓存、请求路由等。

API 网关就像整个微服务系统的门面一样,是系统对外的唯一入口。有了它,客户端会先将请求发送到 API 网关,然后由 API 网关根据请求的标识信息将请求转发到微服务实例。

对于服务数量众多、复杂度较高、规模比较大的系统来说,使用 API 网关具有以下好处:

  • 客户端通过 API 网关与微服务交互时,客户端只需要知道 API 网关地址即可,而不需要维护大量的服务地址,简化了客户端的开发。
  • 客户端直接与 API 网关通信,能够减少客户端与各个服务的交互次数。
  • 客户端与后端的服务耦合度降低。
  • 节省流量,提高性能,提升用户体验。
  • API 网关还提供了安全、流控、过滤、缓存、计费以及监控等 API 管理功能。

常见的 API 网关实现方案主要有以下 5 种:

  • Spring Cloud Gateway
  • Spring Cloud Netflix Zuul
  • Kong
  • Nginx+Lua
  • Traefik

二、Gateway

Spring Cloud Gateway 是 Spring Cloud 团队基于 Spring 5.0、Spring Boot 2.0 和 Project Reactor 等技术开发的高性能 API 网关组件。

Spring Cloud Gateway 是基于 WebFlux 框架实现的,而 WebFlux 框架底层则使用了高性能的 Reactor 模式通信框架 Netty

Spring Cloud GateWay 最主要的功能就是路由转发,而在定义转发规则时主要涉及了以下三个核心概念

1、Route(路由)

2、Predicate(断言)

3、Filter(过滤)

核心概念描述
Route(路由)网关最基本的模块。它由一个 ID、一个目标 URI、一组断言(Predicate)和一组过滤器(Filter)组成。
Predicate(断言)路由转发的判断条件,我们可以通过 Predicate 对 HTTP 请求进行匹配,例如请求方式、请求路径、请求头、参数等,如果请求与断言匹配成功,则将请求转发到相应的服务。
Filter(过滤器)过滤器,我们可以使用它对请求进行拦截和修改,还可以使用它对上文的响应进行再处理。

注:其中 Route 和 Predicate 必须同时声明

Spring Cloud Gateway 工作流程

 1、客户端将请求发送到 Spring Cloud Gateway 上

 2、Spring Cloud Gateway 通过 Gateway Handler Mapping 找到与请求相匹配的路由,将其发送给 Gateway Web Handler。

 3、Gateway Web Handler 通过指定的过滤器链(Filter Chain),将请求转发到实际的服务节点中,执行业务逻辑返回响应结果。

 4、过滤器之间用虚线分开是因为过滤器可能会在转发请求之前(pre)或之后(post)执行业务逻辑。

 5、过滤器(Filter)可以在请求被转发到服务端前,对请求进行拦截和修改,例如参数校验、权限校验、流量监控、日志输出以及协议转换等。

 6、过滤器可以在响应返回客户端之前,对响应进行拦截和再处理,例如修改响应内容或响应头、日志输出、流量监控等。

 7、响应原路返回给客户端

三、Gateway应用

1、新建一个springboot Module(springcloud-7-service-eureka-gateway)

2、添加 spring-cloud-starter-gateway;spring-cloud-starter-netflix-eureka-client等 依赖

注:

在 gateway 网关服务中不能引入 spring-boot-starter-web 的依赖,否则会报错

spring-cloud-starter-gateway 使用的Netty服务器,而 spring-boot-starter-web 使用 的Tomcat服务器;Spring Cloud Gateway使用是基于WebFlux和Netty开发的,和传统的Tomcat服务器方式不同

  1. <dependencies>
  2. <!--spring-cloud-starter-netflix-eureka-client-->
  3. <dependency>
  4. <groupId>org.springframework.cloud</groupId>
  5. <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
  6. </dependency>
  7. <!-- Spring cloud gateway 网关依赖
  8. 特别注意:在 gateway 网关服务中不能引入 spring-boot-starter-web 的依赖,否则会报错
  9. Spring Cloud Gateway使用是基于WebFlux和Netty开发的,和传统的Tomcat服务器方式不同
  10. -->
  11. <dependency>
  12. <groupId>org.springframework.cloud</groupId>
  13. <artifactId>spring-cloud-starter-gateway</artifactId>
  14. </dependency>
  15. </dependencies>
  1. <!--继承统一的父项目-->
  2. <parent>
  3. <groupId>com.company</groupId>
  4. <artifactId>springcloud-demo</artifactId>
  5. <version>1.0.0</version>
  6. </parent>
  7. <groupId>com.company</groupId>
  8. <artifactId>springcloud-7-service-eureka-gateway</artifactId>
  9. <version>1.0.0</version>
  10. <name>springcloud-7-service-eureka-gateway</name>
  11. <description>Demo project for Spring Boot</description>
  12. <properties>
  13. <java.version>1.8</java.version>
  14. </properties>
  15. <dependencies>
  16. <!--spring-cloud-starter-netflix-eureka-client-->
  17. <dependency>
  18. <groupId>org.springframework.cloud</groupId>
  19. <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
  20. </dependency>
  21. <!-- Spring cloud gateway 网关依赖
  22. 特别注意:在 gateway 网关服务中不能引入 spring-boot-starter-web 的依赖,否则会报错
  23. Spring Cloud Gateway使用是基于WebFlux和Netty开发的,和传统的Tomcat服务器方式不同
  24. -->
  25. <dependency>
  26. <groupId>org.springframework.cloud</groupId>
  27. <artifactId>spring-cloud-starter-gateway</artifactId>
  28. </dependency>
  29. </dependencies>
  30. <build>
  31. <plugins>
  32. <plugin>
  33. <groupId>org.springframework.boot</groupId>
  34. <artifactId>spring-boot-maven-plugin</artifactId>
  35. </plugin>
  36. </plugins>
  37. </build>

3、application.properties配置文件

  1. server.port=81
  2. #eureka注册中心首页的Application这一栏
  3. spring.application.name=springcloud-7-service-eureka-gateway
  4. #每间隔5s,向Eureka服务注册中心发送一次心跳,证明服务是否依然“存活”
  5. eureka.instance.lease-renewal-interval-in-seconds=2
  6. #告诉服务端,如果10s之内没有发送心跳,就代表故障,将本服务踢出
  7. eureka.instance.lease-expiration-duration-in-seconds=10
  8. #告诉服务端,服务实例以IP作为链接,不是取机器名
  9. eureka.instance.prefer-ip-address=false
  10. #注册服务实例ID,,服务ID必须唯一 springcloud-7-service-eureka-gateway
  11. eureka.instance.instance-id=${spring.application.name}:${server.port}
  12. #注册中心的链接地址 http://eureka8761:8761/eureka,http://eureka8762:8762/eureka,http://eureka8763:8763/eureka
  13. eureka.client.service-url.defaultZone=http://localhost:8761/eureka
  14. #网关路由配置
  15. #开启网关,默认开启
  16. spring.cloud.gateway.enabled=true
  17. #节点 routes 是一个List 对象,其中 routes 集合中中又包含多个对象,每个对象有三个属性(一个 索引[0]代表一个对象)
  18. #路由 id,没有固定规则,但唯一
  19. spring.cloud.gateway.routes[0].id=login-service-route
  20. #匹配后提供服务的路由地址;uri统一资源定位符 url 统一资源标识符
  21. spring.cloud.gateway.routes[0].uri=http://localhost:9001
  22. #以下是断言条件,必选全部符合条件;断言是给某一个路由来设定的一种匹配规则 默认不能作用在动态路由上
  23. #断言,路径匹配,只要Path匹配上了/doLogin 就往 uri 转发 并且将路径带上 注意:Path 中 P 为大写
  24. #也可以全局匹配,如 /service/**
  25. spring.cloud.gateway.routes[0].predicates[0]=Path=/doLogin
  26. #只能是 GET 请求时,才能访问
  27. spring.cloud.gateway.routes[0].predicates[0]=Method=GET

application.yml写法

  1. server:
  2. port: 81
  3. #eureka注册中心首页的Application这一栏
  4. spring:
  5. application:
  6. name: springcloud-7-service-eureka-gateway
  7. #网关路由配置
  8. cloud:
  9. gateway:
  10. #开启网关,默认开启
  11. enabled: true
  12. #节点 routes 是一个List 对象,其中 routes 集合中中又包含多个对象,每个对象有三个属性(一个 索引[0]代表一个对象)
  13. routes:
  14. #路由 id,没有固定规则,但唯一
  15. - id: login-service-route
  16. #匹配后提供服务的路由地址;uri统一资源定位符 url 统一资源标识符
  17. uri: http://localhost:9001
  18. #以下是断言条件,必选全部符合条件;断言是给某一个路由来设定的一种匹配规则 默认不能作用在动态路由上
  19. predicates:
  20. #断言,路径匹配,只要Path匹配上了/doLogin 就往 uri 转发 并且将路径带上 注意:Path 中 P 为大写
  21. #也可以全局匹配,如 /service/**
  22. - Path=/doLogin
  23. #只能是 GET,POST 请求时,才能访问
  24. - Method=GET,POST
  25. eureka:
  26. instance:
  27. #每间隔5s,向Eureka服务注册中心发送一次心跳,证明服务是否依然“存活”
  28. lease-renewal-interval-in-seconds: 2
  29. #告诉服务端,如果10s之内没有发送心跳,就代表故障,将本服务踢出
  30. lease-expiration-duration-in-seconds: 10
  31. #告诉服务端,服务实例以IP作为链接,不是取机器名
  32. prefer-ip-address: false
  33. #注册服务实例ID,,服务ID必须唯一 springcloud-7-service-eureka-gateway
  34. instance-id: ${spring.application.name}:${server.port}
  35. #注册中心的链接地址 http://eureka8761:8761/eureka,http://eureka8762:8762/eureka,http://eureka8763:8763/eureka
  36. client:
  37. service-url:
  38. defaultZone: http://localhost:8761/eureka

注:

(1)Gateway 网关建议 使用 yml 文件格式配置,以properties配置比较繁琐,一般公司项目也建议采取 yml格式

(2)不管 application.properties 还是 application.yml 写法,都要注意 断言 predicates 处的 Path=/doLogin 和  Method=GET,POST写法,不然报如下错误

  1. ***************************
  2. APPLICATION FAILED TO START
  3. ***************************
  4. Description:
  5. Binding to target [Bindable@4a6facb0 type = java.util.List<org.springframework.cloud.gateway.handler.predicate.PredicateDefinition>, value = 'provided', annotations = array<Annotation>[@javax.validation.constraints.NotEmpty(message={javax.validation.constraints.NotEmpty.message}, groups=[], payload=[]), @javax.validation.Valid()]] failed:
  6. Property: spring.cloud.gateway.routes[0].predicates[0].path
  7. Value: /doLogin
  8. Origin: class path resource [application.yml]:23:21
  9. Reason: The elements [spring.cloud.gateway.routes[0].predicates[0].path,spring.cloud.gateway.routes[0].predicates[1].method] were left unbound.
  10. Property: spring.cloud.gateway.routes[0].predicates[1].method
  11. Value: GET,POST
  12. Origin: class path resource [application.yml]:25:23
  13. Reason: The elements [spring.cloud.gateway.routes[0].predicates[0].path,spring.cloud.gateway.routes[0].predicates[1].method] were left unbound.

  

4、在 Spring Boot 的启动类中,添加 @EnableEurekaClient 注解开启 Eureka 客户端功能(Gateway网关也是eureka的客户端)

  1. @EnableEurekaClient //Gateway网关也是eureka的客户端
  2. @SpringBootApplication
  3. public class EurekaGateway7Application {
  4. public static void main(String[] args) {
  5. SpringApplication.run(EurekaGateway7Application.class, args);
  6. }
  7. }

5、创建一个服务提供者  springcloud-7-service-eureka-gateway-login

依赖

  1. <dependencies>
  2. <dependency>
  3. <groupId>org.springframework.boot</groupId>
  4. <artifactId>spring-boot-starter-web</artifactId>
  5. </dependency>
  6. <!--spring-cloud-starter-netflix-eureka-client-->
  7. <dependency>
  8. <groupId>org.springframework.cloud</groupId>
  9. <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
  10. </dependency>
  11. </dependencies>

application.properties

  1. server.port=9001
  2. #设置应用名称,对应Eureka控制台下 DS Replicas 的 Application(集群部署服务提供者,Application一致,对应多个eureka.instance.instance-id)
  3. spring.application.name=springcloud-7-service-eureka-gateway-login
  4. #每间隔5s,向Eureka服务注册中心发送一次心跳,证明服务是否依然“存活”
  5. eureka.instance.lease-renewal-interval-in-seconds=5
  6. #告诉服务端,如果10s之内没有发送心跳,就代表故障,将本服务踢出
  7. eureka.instance.lease-expiration-duration-in-seconds=10
  8. #告诉服务端,服务实例以IP作为链接,不是取机器名
  9. eureka.instance.prefer-ip-address=false
  10. #注册服务实例ID,,服务ID必须唯一
  11. eureka.instance.instance-id=springcloud-7-service-eureka-gateway-login
  12. #注册中心的链接地址 http://localhost:8761/eureka
  13. eureka.client.service-url.defaultZone=http://localhost:8761/eureka

 controller测试类

  1. @RestController
  2. public class LoginController {
  3. @GetMapping("/doLogin")
  4. public String doLogin(String name, String pwd) {
  5. System.out.println(name);
  6. System.out.println(pwd);
  7. // token
  8. String token = UUID.randomUUID().toString();
  9. return token;
  10. }
  11. }

6、分别启动本地 eureka,gateway,login-service ,输入访问 http://localhost:81/doLogin

注:

这里启动 Gateway网关模块,会明显的在控制台下方看到输出:

 Netty started on port(s):81

服务者自己的端口 9001 访问 自然无问题 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/301491
推荐阅读
相关标签
  

闽ICP备14008679号