网关是流量的入口 用来转发、权限校验、限流等
网关的作用 一个微服务项目 如果不使用网关 那么就意味着 权限校验、拦截黑名单请求等这种功能都需要在每个微服务中一一实现 10个微服务需要权限校验就需要写10次 如果把权限校验功能单独放到公共服务中 每个微服务也都要写同样的权限校验代码 后续升级也是问题 所以就有了网关 首先请求来了先去网关 在网关中权限校验等功能 满足了条件网关去调用微服务
gateway给我们实现了网关的功能
核心概念
路由(route) 路由就是我们想让gateway去调用哪个微服务 断言(predicates) 用户给服务端发送了一个请求 会来到网关 然后网关会根据这样请求地址进行判断要去调用那个微服务 这个断言就是用来写条件的 过滤器(filter) 过滤器 可以做权限校验的功能跟Spring mvc过滤器差不多
gateway使用
引入依赖
org.springframework.cloud spring-cloud-starter-gatewaycom.alibaba.cloud spring-cloud-starter-alibaba-nacos-discovery
编写yml配置文件
server:
port: 8888
spring:
application:
name: mall-gateway
#配置nacos注册中心地址
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
gateway:
discovery:
locator:
# 默认为false,设为true开启通过微服务创建路由的功能,即可以通过微服务名访问服务
# http://localhost:8888/mall-order/order/findOrderByUserId/1
enabled: true
# 是否开启网关
enabled: true
路由断言工厂(Route Predicate Factories)配置
官方文档 很详细
https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gateway-request-predicates-factories
自定义断言工厂
@Component @Slf4j public class CheckAuthRoutePredicateFactory extends AbstractRoutePredicateFactory{ public CheckAuthRoutePredicateFactory() { super(Config.class); } @Override public Predicate apply(Config config) { return new GatewayPredicate() { @Override public boolean test(ServerWebExchange serverWebExchange) { log.info("调用CheckAuthRoutePredicateFactory" + config.getName()); if(config.getName().equals("11")){ return true; } return false; } }; } @Override public List shortcutFieldOrder() { return Collections.singletonList("name"); } public static class Config { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } } }
当yml文件配置了这个断言会进入这个apply方法 config可以得到请求中的信息 test方法返回false就不会去调用微服务
断言实现类名字 CheckAuthRoutePredicateFactory 前面是CheckAuth 后面是RoutePredicateFactory 前面的CheckAuth是自定义 后面RoutePredicateFactory必须这样写 这是一个规定
使用自定义断言工厂
yml中配置
spring:
cloud:
gateway:
#设置路由:路由id、路由到微服务的uri、断言
routes:
- id: order_route #路由ID,全局唯一
uri: http://localhost:8020 #目标微服务的请求地址和端口
predicates:
# 测试:http://localhost:8888/order/findOrderByUserId/1
- Path=/order
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {
// Register the block exception handler for Spring Cloud Gateway.
return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);
}
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public GlobalFilter sentinelGatewayFilter() {
return new SentinelGatewayFilter();
}
}
手动设置限流规则 如果这个类被ioc管理了 在sentinel管理界面 会跟官网地址中显示的界面不一样 导入官网给的依赖也会不一样
用户可以通过 GatewayRuleManager.loadRules(rules) 手动加载网关规则
GatewayConfiguration中添加
@PostConstruct
public void doInit() {
//初始化自定义的API
initCustomizedApis();
//初始化网关限流规则
initGatewayRules();
//自定义限流异常处理器
initBlockRequestHandler();
}
private void initCustomizedApis() {
Set definitions = new HashSet<>();
ApiDefinition api = new ApiDefinition("user_service_api")
.setPredicateItems(new HashSet() {{
add(new ApiPathPredicateItem().setPattern("/user/**")
.setMatchStrategy(SentinelGatewayConstants.URL_MATCH_STRATEGY_PREFIX));
}});
definitions.add(api);
GatewayApiDefinitionManager.loadApiDefinitions(definitions);
}
private void initGatewayRules() {
Set rules = new HashSet<>();
//resource:资源名称,可以是网关中的 route 名称或者用户自定义的 API 分组名称。
//count:限流阈值
//intervalSec:统计时间窗口,单位是秒,默认是 1 秒。
rules.add(new GatewayFlowRule("order_route")
.setCount(2)
.setIntervalSec(1)
);
rules.add(new GatewayFlowRule("user_service_api")
.setCount(2)
.setIntervalSec(1)
);
// 加载网关规则
GatewayRuleManager.loadRules(rules);
}
private void initBlockRequestHandler() {
BlockRequestHandler blockRequestHandler = new BlockRequestHandler() {
@Override
public Mono handleRequest(ServerWebExchange exchange, Throwable t) {
HashMap result = new HashMap<>();
result.put("code",String.valueOf(HttpStatus.TOO_MANY_REQUESTS.value()));
result.put("msg", HttpStatus.TOO_MANY_REQUESTS.getReasonPhrase());
return ServerResponse.status(HttpStatus.TOO_MANY_REQUESTS)
.contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(result));
}
};
//设置自定义异常处理器
GatewayCallbackManager.setBlockHandler(blockRequestHandler);
}
gateway高可用 启动多个gateway实例 使用Nginx这种负载均衡框架进行负载实现



