文章目录
一、前言
至此微服务网关系列文章已出:
聊了以下问题:
- 为什么要有网关?网关的作用是什么?
- 网关的分类?
- 网关的技术选型?
- 使用网关时常用的灰度发布方式有哪些?
本文接着聊SpringCloud生态中的SpringCloudGateway是什么?并给出详细使用案例?
二、Spring Cloud Gateway
官方文档:https://docs.spring.io/spring-cloud-gateway/docs/3.0.1/reference/html/。
Spring Cloud Gateway 是Spring Cloud的第二代网关,用于替换Zuul;基于Netty、Reactor以及WebFlux构建。
1> 优点:
- 性能强劲:Gateway基于netty和reactive模型构建,所以它的性能是Zuul的1.6倍左右。
- 功能强大:内置了很多实用功能,比如转发、监控、限流等。
- 注册到Nacos,自动检测nacos上其他的服务
- 集成Ribbon、
- 限流/容错(默认Hystrix,也可以用Sentinel)
- 设计优雅、易扩展
2> 缺点:
- 依赖Netty与WebFlux,不是Servlet编程模型,有一定的学习、适应成本。
- 不能在Servlet容器下工作,只能打成jar包,不能构建成war包。
- 不支持Spring Boot 1.X。
核心概念
-
路由(Route):路由是⽹关最基础的部分,路由信息由⼀个ID、⼀个目标URL、⼀组断⾔
Predicate
和⼀组Filter组成。如果断⾔路由为真,则说明请求的URL和配置匹配;也可以吧路由理解为一条请求转发规则。- ID:编号,路由的唯⼀标识;
- URI:路由指向的⽬标 URI,即请求最终被转发的⽬的地。
- Predicate:断言 / 谓语,作为路由的匹配条件。
- Filter:过滤器,对请求和响应进⾏拦截,实现⾃定义的功能。
-
断⾔/谓词(Predicate):Spring Cloud Gateway使用
Predicate
作为路由的匹配条件;Gateway 内置了多种 Predicate 的实现,提供了多种请求的匹配条件,⽐如说基于请求的 Path、Method 等等。即java.util.function.Predicate
-
过滤器(Filter):过滤器Filter会对请求和响应进行拦截处理,实现自定义的功能;Gateway 内置了多种 Filter 的实现,提供了多种请求的处理逻辑,⽐如说限流、熔断等等。
此外,Spring Cloud Gateway启动时基于Netty Server 监听一个指定的端口(可以通过server.port属性自定义),Client的请求都会先打到Netty Server,然后再走到Predicates、Filters,最后走一层Netty proxy将请求转发到指定的微服务。
三、Gateway使用案例
整体项目目录包括两个Module,分别为:gateway-center、simple-service。
其中gateway-center作为路由网关、simple-service作为一个普通的微服务被整合到Gateway中。
0、最上层父项目spring-cloud-alibaba-center
spring-cloud-alibaba-center项目下只保留一个跟pom,用于做整体项目的maven依赖管理
1)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>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-cloud-alibaba-center</artifactId>
<groupId>com.saint</groupId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-cloud-alibaba-center</name>
<packaging>pom</packaging>
<modules>
<module>gateway-center</module>
<module>simple-service</module>
</modules>
<properties>
<java.version>1.8</java.version>
<!-- 稳定老版本-->
<!-- <spring-boot.version>2.3.7.RELEASE</spring-boot.version>-->
<!-- <spring-cloud.version>Hoxton.SR9</spring-cloud.version>-->
<!-- <spring-cloud-alibaba.version>2.2.6.RELEASE</spring-cloud-alibaba.version>-->
<spring-boot.version>2.4.2</spring-boot.version>
<spring-cloud.version>2020.0.1</spring-cloud.version>
<spring-cloud-alibaba.version>2021.1</spring-cloud-alibaba.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--整合spring cloud-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--整合spring cloud alibaba-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<!-- java编译插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
1、普通服务simple-service
simple-service项目整体代码结构目录如下:
其整体很简单、仅仅包含一个pom.xml文件、一个application.yml配置文件、一个启动类、一个Controller。
1、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>spring-cloud-alibaba-center</artifactId>
<groupId>com.saint</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>simple-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<description>gateway-simple-service</description>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>
2、application.yml
这里仅仅是设置服务的端口和程序名称。
server:
port: 9001
spring:
application:
name: simple-service
3、启动类SimpleServiceApplication
package com.saint.simple;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @author Saint
*/
@SpringBootApplication
public class SimpleServiceApplication {
public static void main(String[] args) {
SpringApplication.run(SimpleServiceApplication.class, args);
}
}
就一个很普通的启动类。
4、启动simple-service
启动成功后,控制台输出如下:
2、搭建Gateway
Gateway-center整体代码结构目录如下:
其中包含一个pom.xml文件、一个application.yml配置文件、一个启动类;
1、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>spring-cloud-alibaba-center</artifactId>
<groupId>com.saint</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>gateway-center</artifactId>
<version>0.0.1-SNAPSHOT</version>
<description>gateway-center</description>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</project>
2、application.yml
server:
port: 9999
spring:
application:
name: gateway-center
cloud:
gateway:
routes:
- id: simple_service_route
uri: http://127.0.0.1:9001
predicates:
# 路径匹配规则,向http://localhost:9999/gateway/simple-service/路径发送请求时,将会被转发到http://localhost:9001
- Path=/gateway/simple-service/**
filters:
# StripPrefix参数表示在将请求发送到下游之前从请求中剥离的路径个数。
# 如果设置StripPrefix=2,则当通过网关向/gateway/simple-service/hello发出请求时,对simple-service的请求将类似于/hello。
- StripPrefix=2
application.yml配置文件中配置了一个Filter(StripPrefix
),其表示在将请求发送到下游之前从请求路径(Predicate中的配置的Path)中剥离的路径个数;
以当前配置为例,Predicate中配置的Path为/gateway/simple-service/**
,StripePrefix的值为2,当我们要通过gateway接收一个请求时,请求为:http://127.0.0.1:9999/gateway/simple-service/hello/sayHello
,则转发到http://127.0.0.1:9001
上的请求地址为:http://127.0.0.1:9001/hello/sayHello
。
3、启动类GatewayApplication
package com.saint.gateway;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @author Saint
*/
@SpringBootApplication
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args);
}
}
4、启动gateway-center
启动成功后,控制台输出如下:
可以看到Gateway对外提供服务的Netty Server端口号为我们自定义的9999;
3、路由效果验证
上述步骤中,我们已经依次启动了simple-service、gateway-center;有两种方式可以访问到simple-service。
1> 直接访问simple-service:
2> 通过Gateway访问simple-service:
四、总结
目前一般SpringCloud生态都会选择使用Spring Cloud Gateway,当然也存在一些老项目至今仍在使用Zuul;Spring Cloud Gateway由WebFlux + Netty + Reactor组成,旨在为微服务架构提供⼀种简单且有效的API路由管理⽅式,并基于Filter的⽅式提供⽹关的基本功能,例如说安全认证、监控、限流。
另外:Spring Cloud Gateway是一个基于响应式的API业务⽹关。
后续博文我们继续聊Spring Cloud Gateway Predicate的使用