- 客户端多次请求不同的微服务,增加客户端代码或配置编写的复杂性
- 认证复杂,每个服务都需要独立认证。
- 微服务做集群的情况下,客户端并没有负责均衡的功能
上面的这些问题可以借助API网关来解决。
所谓的API网关,就是指系统的统一入口,它封装了应用程序的内部结构,为客户端提供统一服
务,一些与业务本身功能无关的公共逻辑可以在这里实现,诸如认证、鉴权、监控、路由转发等等。
Gateway快速入门导入相关依赖
org.springframework.cloud
spring-cloud-starter-gateway
com.alibaba.cloud
spring-cloud-starter-alibaba-nacos-discovery
org.projectlombok
lombok
编写启动类
@SpringBootApplication
@EnableDiscoveryClient
public class ApiGatewayServer {
public static void main(String[] args) {
SpringApplication.run(ApiGatewayServer.class,args);
}
}
编写配置文件
server:
port: 9000
spring:
application:
name: api-gateway
cloud:
nacos:
discovery:
server-addr: localhost:8848
gateway:
discovery:
locator:
enabled: true # 让gateway可以发现nacos中的微服务
自定义路由规则
默认根据服务名匹配
在application.yml中添加新的路由规则
spring:
application:
gateway:
routes:
- id: product_route 自定义路由名称
uri: lb://product-service 改路由将请求转发到哪个服务中 lb://表示需要对服务进行负载均衡
predicates: 断言,当以下断言都满足时,使用该路由进行转发
- Path=/product-serv/** 路径断言,请求路径需要满足该路径规则
filters: 该路由的局部过滤器
- StripPrefix=1 路径截取过滤器,去掉匹配路径中的服务名,将地址与后面的映射方法,参数拼接访问服务
- id: order_route
uri: lb://order-service
predicates:
- Path=/order-serv/**
filters:
- StripPrefix=1
Gateway概念
路由(Route) 是 gateway 中最基本的组件之一,表示一个具体的路由信息载体。主要定义了下面的几个
信息:
- id,路由标识符,区别于其他 Route。
- uri,路由指向的目的地 uri,即客户端请求最终被转发到的微服务。
- order,用于多个 Route 之间的排序,数值越小排序越靠前,匹配优先级越高。
- predicate,断言的作用是进行条件判断,只有断言都返回真,才会真正的执行路由。
- filter,过滤器用于修改请求和响应信息。
执行流程图:
过滤器就是在请求的传递过程中,对请求和响应做一些手脚.
在Gateway中, Filter的生命周期只有两个:“pre” 和 “post”。
- PRE: 这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身份验证、在集群中选择
请求的微服务、记录调试信息等。
- POST:这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的HTTP
Header、收集统计信息和指标、将响应从微服务发送给客户端等。
在Gateway中,Filter的作用范围两种:
- GatewayFilter:应用到单个路由或者一个分组的路由上。
- GlobalFilter:应用到所有的路由上
编写Filter类,注意名称是有固定格式xxxGatewayFilterFactory
@Component public class TimeGatewayFilterFactory extends AbstractGatewayFilterFactory{ private static final String BEGIN_TIME = "beginTime"; //构造函数,将配置类字节码给父类构造器初始化对象 public TimeGatewayFilterFactory() { super(TimeGatewayFilterFactory.Config.class); } //读取配置文件中的参数按名称反射赋值到 配置类中的字段 @Override public List shortcutFieldOrder() { return Arrays.asList("show"); } @Override public GatewayFilter apply(Config config) { return new GatewayFilter() { @Override public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) { //前置逻辑 return chain.filter(exchange).then(Mono.fromRunnable(()->{ //后置逻辑 })); } }; } @Setter@Getter static class Config{ private boolean show; } }
在指定的路由中添加路由规则
server:
port: 9000
spring:
application:
name: api-gateway
cloud:
nacos:
discovery:
server-addr: localhost:8848
gateway:
discovery:
locator:
enabled: true
routes:
- id: product_route
uri: lb://product-service
predicates:
- Path=/product-serv/**
filters:
- StripPrefix=1
- id: order_route
uri: lb://order-service
predicates:
- Path=/order-serv/**
filters:
- StripPrefix=1
- Time=true
全局路由过滤器
全局过滤器作用于所有路由, 无需配置。通过全局过滤器可以实现对权限的统一校验,安全性验证等功
能。
SpringCloud Gateway内部也是通过一系列的内置全局过滤器对整个路由转发进行处理如下:
编写全局过滤类
@Component
public class AuthGlobalFilter implements GlobalFilter {
@Override
public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
String token = exchange.getRequest().getQueryParams().getFirst("token");
if (StringUtils.isBlank(token)) {
System.out.println("鉴权失败");
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().setComplete(); //设置响应结束
}
return chain.filter(exchange);
}
}
网关集成Sentinel实现网关限流
网关是所有请求的公共入口,所以可以在网关进行限流,而且限流的方式也很多,我们本次采用前
面学过的Sentinel组件来实现网关的限流。Sentinel支持对SpringCloud Gateway、Zuul等主流网关进
行限流。
从1.6.0版本开始,Sentinel提供了SpringCloud Gateway的适配模块,可以提供两种资源维度的限流:
- route维度:即在Spring配置文件中配置的路由条目,资源名为对应的routeId
- 自定义API维度:用户可以利用Sentinel提供的API来自定义一些API分组
添加依赖
com.alibaba.csp sentinel-spring-cloud-gateway-adaptercom.alibaba.cloud spring-cloud-starter-alibaba-sentinelcom.alibaba.cloud spring-cloud-alibaba-sentinel-gateway
添加配置
spring:
cloud:
sentinel:
transport:
port: 9999
dashboard: localhost:8080
API分组
Sentinel中支持按照API分组进行限流,就是我们可以按照特定规则进行限流.
在管控台页面中提供了三种方式的API分组管理
- 精准匹配
- 前缀匹配
- 正则匹配
精准匹配
1.在API管理中新建API分组,匹配模式选择精准匹配,匹配串写请求URL地址
前缀匹配
1.在API管理中新建API分组,匹配模式选择前缀匹配,匹配串写请求URL地址
注意: 如果路径为/*表示匹配一级路径,如果路径为/**表示多级路径
正则匹配
1.在API管理中新建API分组,匹配模式选择正则匹配,匹配串写请求URL地址
路径/(.*)此时所有路径都会被限流
修改限流默认返回格式在配置类中添加如下配置
@PostConstruct
public void initBlockHandlers() {
BlockRequestHandler blockRequestHandler = new BlockRequestHandler() {
public Mono handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) {
Map map = new HashMap<>();
map.put("code", 0);
map.put("message", "接口被限流了");
return ServerResponse.status(HttpStatus.OK).
contentType(MediaType.APPLICATION_JSON).
body(BodyInserters.fromValue(map));
}
};
GatewayCallbackManager.setBlockHandler(blockRequestHandler);
}



