(第一次刷到本文的小伙伴可移至微服务案例,通过结合案例可以更快理解Gateway)
Gateway 网关简介
Spring Cloud Gateway 是 Spring Cloud 生态系统中的一个API网关,它是基于Spring 5、Project Reactor和Spring Boot 2.0构建的。Gateway旨在为微服务架构提供一种简单而有效的统一入口点。
可以将Gateway看作是微服务系统的"大门",它负责将所有外部请求路由到相应的微服务,并在路由过程中可以添加各种功能,如身份验证、限流、监控等。
为什么使用 Gateway?
又是通俗易懂的比喻环节,现在你住在一栋有很多住户的大楼里,如果没有门卫和前台,任何人都可以直接进入大楼,这会带来安全隐患。而有了门卫和前台,所有访客都需要通过前台登记,然后由前台决定是否允许进入以及应该去哪一栋楼。
Gateway就像这栋大楼的"前台",它能够:
- 路由转发:将请求根据规则路由到正确的微服务
- 统一入口:为所有微服务提供统一的访问入口
- 权限控制:在网关层统一进行身份验证和权限校验
- 限流保护:防止系统因突发流量而崩溃
- 监控统计:集中监控所有请求的处理情况
Gateway 核心功能
路由转发(Routing)
Gateway 可以根据预设的路由规则将请求转发到相应的微服务。路由规则可以基于路径、请求参数、请求头等多种条件。
在项目中,通过配置文件或代码方式定义路由规则:
spring:
cloud:
gateway:
routes:
- id: product_route
uri: lb://product
predicates:
- Path=/p/**
filters:
- StripPrefix=1
- id: order_route
uri: lb://order
predicates:
- Path=/o/**
filters:
- StripPrefix=1
过滤器(Filter)
Gateway 提供了强大的过滤器功能,可以在请求转发前后对请求和响应进行处理。
全局过滤器
@Component
public class ShopAuthFilter implements GlobalFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
String token = request.getQueryParams().getFirst("token");
if (StringUtils.isBlank(token)){
ServerHttpResponse response = exchange.getResponse();
response.setStatusCode(HttpStatus.UNAUTHORIZED);
return response.setComplete();
}
return chain.filter(exchange);
}
}
局部过滤器
public class TimeGatewayFilterFactory extends AbstractGatewayFilterFactory<TimeGatewayFilterFactory.MyConfig> {
@Override
public GatewayFilter apply(MyConfig config) {
return new GatewayFilter() {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
if (!config.show){
return chain.filter(exchange);
}
long begin = System.currentTimeMillis();
return chain.filter(exchange).then(Mono.fromRunnable(()->{
long end = System.currentTimeMillis();
String ip = exchange.getRequest().getRemoteAddress().getHostName();
String path = exchange.getRequest().getURI().getPath();
System.err.println(ip + "访问接口" + path + "耗时" + (end-begin) + "毫秒");
}));
}
};
}
}
熔断与限流
Gateway 可以与 Sentinel 等组件集成,实现网关层的限流和熔断功能。
@Configuration
public class ShopGatewayConfig {
@PostConstruct
public void ShopGratewayExceptionHandler() {
BlockRequestHandler blockRequestHandler = new BlockRequestHandler() {
@Override
public Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) {
Map<String,Object> map = new HashMap<>();
map.put("code",-100);
map.put("message","网关路由被限流");
return ServerResponse.status(HttpStatus.OK)
.contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(map));
}
};
GatewayCallbackManager.setBlockHandler(blockRequestHandler);
}
}
Gateway 在项目中的配置
从项目代码可以看出,Gateway 的配置主要分为以下几个部分:
1.Maven 依赖配置
在 shop-api-gateway/pom.xml 文件中添加了 Gateway 相关依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-spring-cloud-gateway-adapter</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency>
2.路由配置
在 shop-api-gateway/src/main/resources/application.yml 中配置了路由规则:
spring:
cloud:
gateway:
discovery:
locator:
enabled: true
routes:
- id: product_route
uri: lb://product
predicates:
- Path=/p/**
filters:
- StripPrefix=1
- id: order_route
uri: lb://order
predicates:
- Path=/o/**
filters:
- StripPrefix=1
3.全局过滤配置
在项目中实现了全局过滤器用于权限验证
@Component
public class ShopAuthFilter implements GlobalFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
System.err.println("全局路由器执行了");
ServerHttpRequest request = exchange.getRequest();
String token = request.getQueryParams().getFirst("token");
if (StringUtils.isBlank(token)){
System.err.println("Token为空,拒绝访问");
ServerHttpResponse response = exchange.getResponse();
response.setStatusCode(HttpStatus.UNAUTHORIZED);
return response.setComplete();
}else{
System.out.println("Token验证通过");
}
return chain.filter(exchange);
}
}
4. 网关限流配置
与 Sentinel 集成实现网关层限流:
@Configuration
public class ShopGatewayConfig {
@PostConstruct
public void ShopGratewayExceptionHandler() {
BlockRequestHandler blockRequestHandler = new BlockRequestHandler() {
@Override
public Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) {
Map<String,Object> map = new HashMap<>();
map.put("code",-100);
map.put("message","网关路由被限流");
return ServerResponse.status(HttpStatus.OK)
.contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(map));
}
};
GatewayCallbackManager.setBlockHandler(blockRequestHandler);
}
}
5.自定义过滤器工厂
项目中还实现了自定义过滤器工厂,用于统计接口访问耗时
public class TimeGatewayFilterFactory extends AbstractGatewayFilterFactory<TimeGatewayFilterFactory.MyConfig> {
@Override
public GatewayFilter apply(MyConfig config) {
return new GatewayFilter() {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
if (!config.show){
return chain.filter(exchange);
}
long begin = System.currentTimeMillis();
return chain.filter(exchange).then(Mono.fromRunnable(()->{
long end = System.currentTimeMillis();
String ip = exchange.getRequest().getRemoteAddress().getHostName();
String path = exchange.getRequest().getURI().getPath();
System.err.println(ip + "访问接口" + path + "耗时" + (end-begin) + "毫秒");
}));
}
};
}
}
Gateway 在项目中的作用
在本项目中,Gateway 扮演了以下几个重要角色:
- 统一入口:所有外部请求都通过网关进入系统,而不是直接访问各个微服务
- 权限验证:在网关层统一验证 token,确保只有合法请求才能进入系统
- 路由转发:根据请求路径将请求转发到相应的微服务
- 限流保护:与 Sentinel 集成,在网关层实现限流保护
- 监控统计:通过自定义过滤器统计接口访问耗时等信息
通过这些配置和功能,Gateway 成为了整个微服务架构的重要组成部分,为系统的稳定性、安全性和可维护性提供了保障。