SpringCloud Gateway网关
# 前言
在分布式开发中,需要一个API网关,它扮演着至关重要的角色,具有路由,过滤,限流,监控,日志输出等等作用。
假设我们需要对商品的增删改查,就需要发布请求到商品服务的端口,当存在多个机器上线商品服务,只有1号机器上线时,我们需要发送请求到1号机器的端口,只有2号机器上线时,我们需要发送请求到2号机器端口,当商品服务有十几个机器上线时,某一个用不了,还需要动态切换到可用的机器端口,我们不可能去后台管理系统去修改发送的端口。
当所有请求经过网关,网关实时感知哪个端口可用,转发到真实端口。
# 简介
Gateway是在Spring生态系统之上构建的API网关服务,基于Spring 5,Spring Boot 2和 Project Reactor等技术。Gateway旨在提供一种简单而有效的方式来对API进行路由,以及提供一些强大的过滤器功能, 例如:熔断、限流、重试等。
Spring Cloud Gateway 具有如下特性:
- 基于Spring Framework 5, Project Reactor 和 Spring Boot 2.0 进行构建;
- 动态路由:能够匹配任何请求属性;
- 可以对路由指定 Predicate(断言)和 Filter(过滤器);
- 集成Hystrix的断路器功能;
- 集成 Spring Cloud 服务发现功能;
- 易于编写的 Predicate(断言)和 Filter(过滤器);
- 请求限流功能;
- 支持路径重写。
网关作为流量的入口,常用功能包括路由转发、权限校验、限流控制等。而SpringCloud Gateway作为SpringCloud官方推出的第二代网关框架,取代了Zuul网关。
在网上有简单的性能测试性能:
组件 | RPS(request per second) |
---|---|
SpringCloud Gateway | Requests/sec:32213.38 |
Zuul | Requests/sec:20800.13 |
Linkerd | Requests/sec:28050.76 |
SpringCloud Gateway 每秒能处理三万多请求,比其他2个强多了。
# 学习文档
官方文档
https://spring.io/projects/spring-cloud-gateway
CURRENT
GA
就是稳定发布的版本,点击Reference Doc就可以查看详细文档。
# 相关概念
# 2. Glossary (opens new window)
- Route: The basic building block of the gateway. It is defined by an ID, a destination URI, a collection of predicates, and a collection of filters. A route is matched if the aggregate predicate is true.
- Predicate: This is a Java 8 Function Predicate (opens new window). The input type is a Spring Framework
ServerWebExchange
(opens new window). This lets you match on anything from the HTTP request, such as headers or parameters.- Filter: These are instances of Spring Framework
GatewayFilter
(opens new window) that have been constructed with a specific factory. Here, you can modify requests and responses before or after sending the downstream request.
Route(路由):路由是构建网关的基本模块,它由ID,目标URI,一系列的断言和过滤器组成,如果断言为true则匹配该路由;
Predicate(断言):指的是Java 8 的 Function Predicate。 输入类型是Spring框架中的ServerWebExchange。 这使开发人员可以匹配HTTP请求中的所有内容,例如请求头或请求参数。如果请求与断言相匹配,则进行路由;
Filter(过滤器):指的是Spring框架中GatewayFilter的实例,使用过滤器,可以在请求被路由前后对请求进行修改。
# 工作流程
客户端想要发请求到目标服务端,中间会经过网关
请求
- 客户端发请求
- 请求到达API网关(Spring Cloud Gateway)
- Gateway Handler Mapping处理,映射信息将会被检查,能否被路由或者被处理
- 如果能处理,就会交给Handler处理器处理
- 处理器处理这些请求,就会经过一系列的filter
- filter过滤结束后,就会把这个请求路由给指定的服务
返回
服务端处理完毕后,也会经过上面的一系列过滤,返回给客户端
# 新建网关微服务
# 新建模块
root项目>>new Moudle>>Spring Initializr
- 搜索gateway,选中依赖,点击下一步,完成
# 依赖common模块
<dependency>
<groupId>com.elite.mall</groupId>
<artifactId>elitemall-common</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
2
3
4
5
# 把网关服务注册到注册中心
- 设置应用名字application.properties
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
spring.application.name=elitemall-gateway
server.port=88
2
3
# 为网关新建nacos命名空间
# 在网关命名空间新建配置
- Data Id:elitemall-gateway.yml
# 将网关微服务使用刚才创建的命名空间
- bootstrap.properties
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
spring.cloud.nacos.config.namespace=9512e348-2216-4b9d-99e1-e230fed7faf8
2
# 验证
启动网关微服务,看看能否正常注册到注册中心。
发现报错
ction:
Consider the following:
If you want an embedded database (H2, HSQL or Derby), please put it on the classpath.
If you have database settings to be loaded from a particular profile you may need to activate it (no profiles are currently active).
2
3
4
5
6
因为网关微服务暂时还用不到数据源,所以启动时要排除掉。
package com.elite.mall.gateway;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@EnableDiscoveryClient
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
public class ElitemallGatewayApplication {
public static void main(String[] args) {
SpringApplication.run(ElitemallGatewayApplication.class, args);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
重新启动微服务,访问88接口,已经能够访问。
# 两种不同的配置路由方式
Gateway 提供了两种不同的方式用于配置路由,一种是通过yml文件来配置,另一种是通过Java Bean来配置,
参考资料:https://juejin.im/post/6844903982599684103
# The Query
route predicate factory 测试
The preceding route matches if the request contained a
red
query parameter whose value matched thegree.
regexp, sogreen
andgreet
would match.
application.yml
spring:
cloud:
gateway:
routes:
- id: test_route
uri: https://translate.google.cn/
predicates:
- Query=url,translate
- id: qq_route
uri: https://www.qq.com/
predicates:
- Query=url,qq
- id: baidu_route
uri: http://www.baidu.com/
predicates:
- Query=url,baidu
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
重启网关微服务,分别测试
- http://localhost:88/hello?url=translate
- http://localhost:88/hello?url=qq
- http://localhost:88/hello?url=baidu
会发现全部跳转到404,但是实际上已经成功了,因为相当于范围qq.com/hello,所以就跳转到404
# 总结
当请求到达网关,网关先利用断言(Predicate)来判定这次请求是否符合某个路由规则,如果符合,则按路由(Route)规则路由到指定地方,但要去这些指定地方,要经过一系列的过滤(Filter)