1.SpringCloud Gateway 介绍
Spring Cloud Gateway 是 Spring Cloud 的一个全新项目,该项目是基于 Spring 5.0,Spring Boot 2.0 和 Project Reactor 等技术开发的网关,它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式。
Spring Cloud Gateway 作为 Spring Cloud 生态系统中的网关,目标是替代 Netflix Zuul,其不仅提供统一的路由方式,并且基于 Filter 链的方式提供了网关基本的功能,例如:安全,监控/指标,和限流。
**对比zuul:**
-
功能
Gateway内部实现了限流、负载均衡等,扩展性更强
-
异步支持
zuul仅支持同步,gateway支持异步
-
性能
Zuul1.X是阻塞的,Gateway是非阻塞的,Gateway性能更好
-
选型建议
Spring Cloud Gateway 作为 Spring Cloud 生态系统中的网关,目标是替代 Netflix Zuul
新项目建议采用Gateway,但老项目已采用Zuul不建议替换
**相关概念:**
-
Route(路由):这是网关的基本构建块。它由一个 ID,一个目标 URI,一组断言和一组过滤器定义。如果断言为真,则路由匹配。
-
Predicate(断言):这是一个 Java 8 的 Predicate。输入类型是一个 ServerWebExchange。我们可以使用它来匹配来自 HTTP 请求的任何内容,例如 headers 或参数。
-
Filter(过滤器):这是
org.springframework.cloud.gateway.filter.GatewayFilter
的实例,我们可以使用它修改请求和响应。
2. 搭建Gateway
2.1 创建Maven Module
2.2 pom
==gateway基于webflux,注意不要引入web依赖==
<dependencies>
<!-- gateway依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!-- eureka客户端依赖 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
<!-- 如果springboot是1.5.X版本 <artifactId>spring-cloud-starter-eureka</artifactId> -->
</dependency>
</dependencies>
2.3 yml
server:
port: 8111
spring:
cloud:
gateway:
routes:
- id: emall-emp-consumer
uri: lb://emall-emp-consumer # lb代表从注册中心获取服务
predicates:
- Path=/emall-emp/**
filters:
- StripPrefix=1 # 如果去除掉前面两个前缀,则值为2,类推
eureka:
client:
register-with-eureka: false
service-url:
defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka
2.4 启动类
@SpringBootApplication
@EnableEurekaClient
public class GatewayApp {
public static void main(String[] args) {
SpringApplication.run(KmallGatewayApp.class, args);
}
}
3. 微服务名称转发
spring:
cloud:
gateway:
discovery:
locator:
enabled: true
lower-case-service-id: true
4. 全局过滤
@Component
public class MyGatewayFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
System.out.println("进入过滤器...");
// 判断请求token
// 获取请求对象request
ServerHttpRequest request = exchange.getRequest();
/*List<String> tokens = request.getHeaders().get("kgc-token");
System.out.println("tokens: " + tokens);
if(tokens == null || tokens.size()==0){
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete();
}*/
String token = request.getHeaders().getFirst("kgc-token");
if(token == null){
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
// 直接返回
//return exchange.getResponse().setComplete();
// 返回json
Result result = new Result(20001,"token无效,请重新登录",null);
DataBuffer buffer = exchange.getResponse().bufferFactory().wrap(JSONObject.toJSON(result).toString().getBytes());
ServerHttpResponse response = exchange.getResponse();
response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
return response.writeWith(Mono.just(buffer));
}
return chain.filter(exchange);
}
@Override
public int getOrder() {
return 0;
}
}