文章目录
网关的概念
网关是微服务最边缘的服务,直接暴露给用户,用来做用户和微服务的桥梁。
有网关和没有网关有什么区别呢?
- 无网关:客户端直接访问微服务,需要在客户端配置很多的 ip: port,如果service的并发量大,则很难完成负载均衡。
- 有网关:客户端访问网关,再由网关访问微服务(网关可以和注册中心整合,就可通过服务名找到对应的 ip:port),这样就只需要使用服务名称即可访问微服务,另外还可实现负载均衡,可以实现token拦截、权限验证、限流等操作。
Spring Cloud Gateway简介
关于gateway的简介,我们首先通过官方文档来看看:
This project provides an API Gateway built on top of the Spring Ecosystem, including: Spring 6, Spring Boot 3 and Project Reactor. Spring Cloud Gateway aims to provide a simple, yet effective way to route to APIs and provide cross cutting concerns to them such as: security, monitoring/metrics, and resiliency.
该项目提供了一个建立在Spring生态系统之上的API网关,包括:Spring 6、Spring Boot 3和project Reactor。Spring Cloud Gateway旨在提供一种简单而有效的方法来路由到API,并为它们提供跨领域的关注点,例如:安全性、监控/度量和弹性。
Spring Cloud Gateway工作流程
客户端向Spring Cloud Gateway发出请求。如果网关处理程序映射确定请求与路由匹配,则会将其发送到网关Web处理程序。此处理程序通过特定于请求的筛选器链来运行请求。过滤器被虚线分隔的原因是过滤器可以在发送代理请求之前和之后运行逻辑。执行所有“预”过滤器逻辑。然后进行代理请求。在发出代理请求后,将运行过滤器的后置逻辑。
gateway的核心逻辑:路由转发 + 执行过滤器链。
Spring Cloud Gateway三大核心概念
Route(和Eureka结合做动态路由)
路由信息的组成:一个ID、一个目的URL、一组断言工厂、一组Filter。如果路由断言为真,说明请求路由URL和配置路由匹配。
Predicate(断言)
就是返回一个布尔表达式。Spring Cloud Gateway的断言函数的输入类型是Spring 5.0框架中的ServerWebExchange。断言函数允许开发者去定义匹配来自于Http Request中的任何信息。
Filter(过滤)
一个标准的Spring Webfilter。
Spring Cloud Gateway中的Filter分为两种类型:
- Gateway Filter:针对某一个路由的Filter;
- Global Filter:针对全局的Filter。
Nginx与Gateway的区别
- 级别不同。Nginx通常是服务器级别的,每台服务器有一个Nginx服务;Gateway是项目级别的,一个微服务项目中存在Gateway。假如服务器上存在多个项目,那么可以先通过Nginx进行代理,然后请求到达某一个项目后再由Gateway进行路由;
- Nginx在做路由、负载均衡、限流前,都要修改nginx.conf文件,把需要路由、负载均衡、限流的规则加载里面;但是Gateway不同,Gateway是自动的负载均衡与路由,Gateway与Eureka高度集成,实现自动路由,和Ribbon实现负载均衡,也能轻易实现限流和权限验证。
Gateway路由转发(静态)使用入门
简单的使用gateway转发功能只需要进行简单的配置即可。
user-login-service模块
首先,新建一个模块user-login-service用于模仿我们的一个微服务。
其pom文件如下:
<?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>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.12.RELEASE</version>
<relativePath />
</parent>
<groupId>com.luozheng</groupId>
<artifactId>user-login</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring-cloud.version>Hoxton.SR12</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<scope>import</scope>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>
</project>
简单配置下:
server:
port: 8081
spring:
application:
name: user-login-service
新增一个测试接口:
启动服务。
gateway-route-server模块
新建一个gateway-route-server模块用来作为gateway网关服务。
其pom文件如下:
<?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>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.12.RELEASE</version>
</parent>
<groupId>com.luozheng</groupId>
<artifactId>gateway-route</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring-cloud.version>Hoxton.SR12</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
需要注意的是,在使用gateway的模块中不要引入spring-boot-starter-web依赖,因为其中自带tomcat服务器,会影响gateway
方式一:通过配置文件设置gateway参数
我们只需要对gateway进行配置即可,配置内容与说明如下:
server:
port: 80 # 网关一般设置80端口
spring:
application:
name: gateway-route-server
cloud:
gateway:
enable: true # 这个是默认开启
routes:
- id: user-login-service # 路由的 id, 需要保持唯一
uri: http://localhost:8081 # 设置路由的 uri
predicates:
- Path=/doLogin # 匹配规则,只要path匹配上了 /doLogin 就往uri转发,并且会将该 path 拼接在 uri 后面
gateway的有哪些配置内容,我们可以通过其配置类GatewayProperties
查看。
最后启动服务。当我们访问80端口的/doLogin
接口时,成功的返回数据,说明gateway已将我们的请求路由到了user-login-service中。
方式二:通过配置类设置gateway参数
除了配置文件外,我们也可以通过配置类对gateway进行配置,与配置文件中的配置互不影响。
我们可以新建一个配置类,如下:
启动服务,可以看到和配置文件中配置结果一样,成功进行了路由。
Gateway路由转发(动态)使用入门
在我们的实际项目中,很有可能我们是集群部署的情况,这个时候静态路由使用起来将会变得麻烦。而gateway与eureka结合使用后能够非常方便的实现动态路由的功能。
在上面的静态路由示例中,做些改变。首先,在gateway-route-server
模块和user-login-service
模块中引入eureka依赖并在启动类上加上eureka的启动注解。
user-login-service
增加eureka配置:
eureka:
client:
service-url:
defaultZone: http://192.168.13.14:8761/eureka
register-with-eureka: true
fetch-registry: true
instance:
instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port}
hostname: localhost
相较于提供服务的模块,gateway模块实现动态路由的配置方式有两种。
方式一:通过动态路由配置开关直接开启动态路由
可以通过直接打开geteway的动态路由配置即可,如下:
通过本方式打开动态路由后,我们每次访问服务时,只需要在url前面加上服务名就可以完成负载均衡。效果如下:
方式二:通过配置uri开启动态路由
除了通过gateway提供的动态路由开关的方式打开动态路由功能,我们还可以在之前的配置文件通过修改uri配置的方式来设置动态路由。
通过这种方式配置的动态路由,在访问服务时,无需在url前面添加服务名。