Spring Cloud Alibaba系列(四)使用gateway作为服务网关
什么是网关
在微服务架构里,服务的粒度被进一步细分,各个业务服务可以被独立的设计、开发、测试、部署和管理。这时,各个独立部署单元可以用不同的开发测试团队维护,可以使用不同的编程语言和技术平台进行设计,这就要求必须使用一种语言和平台无关的服务协议作为各个单元间的通讯方式。
换句话说就是网关为所有的请求提供了统一的入口,方便我们对服务请求和响应做统一管理。
为什么要用网关
API 网关是一个处于应用程序或服务(提供 REST API 接口服务)之前的系统,用来管理授权、访问控制和流量限制等,这样 REST API 接口服务就被 API 网关保护起来,对所有的调用者透明。
什么是gateway
Spring Cloud Gateway是Spring官方基于Spring 5.0,Spring Boot 2.0和Project Reactor等技术开发的网关,Spring Cloud Gateway旨在为微服务架构提供一种简单而有效的统一的API路由管理方式。Spring Cloud Gateway作为Spring Cloud生态系中的网关,目标是替代ZUUL,其不仅提供统一的路由方式,并且基于Filter链的方式提供了网关基本的功能,例如:安全,监控/埋点,和限流等。
gateway工作原理
客户端向Spring Cloud网关发出请求。如果网关处理程序映射确定请求与路由匹配,则将其发送到网关Web处理程序。该处理程序运行通过特定于请求的过滤器链发送请求。过滤器由虚线分隔的原因是,过滤器可以在发送代理请求之前或之后执行逻辑。执行所有“前置”过滤器逻辑,然后发出代理请求。发出代理请求后,将执行“后”过滤器逻辑。
路由规则
路由和过滤器是gateway中非常重要的两个概念,gateway本身提供了非常丰富的路由规则和多种过滤器来适配我们的需求。gateway提供了11种路由规则,分别是:
后置路由谓词工厂
该谓词匹配在当前日期时间之后发生的请求。参数名为 After
前置路由谓词工厂
该谓词匹配当前日期时间之前发生的请求。参数名为 Before
时间段路由谓词工厂
该谓词匹配在datetime1之后和datetime2之前发生的请求。参数名为 Between
cookie路由谓词工厂
该谓词匹配具有给定名称的cookie,并且值匹配正则表达式。参数名为 Cookie
标头路由谓词工厂
该谓词与具有给定名称的标头匹配,并且值与正则表达式匹配。参数名为 Header
主机路由谓词工厂
该谓词是指由路由进行匹配,匹配多个路由时用,隔开。参数名为 Host
方法路由谓词工厂
该参数是一个或多个要匹配的HTTP方法。参数名为 Method
路径路由谓词工厂
该谓词是指在请求路径上加一个前缀,以此来匹配。参数名为 Path
查询路由谓词工厂
RemoteAddr路由谓词工厂
重量路线谓词工厂
其中,我们比较常用的就是路径路由谓词工厂,配合StripPrefix GatewayFilter工厂,实现我们的路由匹配转发。
路径路由谓词工厂配置如下:
spring:
cloud:
gateway:
discovery:
locator:
enabled: true # 开启从注册中心动态创建路由的功能,利用微服务名称进行路由
routes:
# 路由id,建议配合服务名
- id: demo_route
#匹配路由名
uri: lb://demo-provider
predicates:
# 断言,路径相匹配的进行路由
- Path=/demo/**
配置的含义就是,如果请求路径中是/demo/**,则转发到demo-provider服务。
网关过滤器
在spring cloud gateway 2.2.2.RELEASE版本中,已经默认实现了30种过滤器。
序号 | 过滤器工厂 | 作用 | 参数 |
---|---|---|---|
1 | AddRequestHeader | 为原始请求添加Header | Header的名称及值 |
2 | AddRequestParameter | 为原始请求添加请求参数 | 参数名称及值 |
3 | AddResponseHeader | 为原始响应添加Header | Header的名称及值 |
4 | DedupeResponseHeader | 剔除响应头中重复的值 | 需要去重的Header名称及去重策略 |
5 | Hystrix | 为路由引入Hystrix的断路器保护 | HystrixCommand的名称 |
6 | CircuitBreaker | 为路由引入Resilience4J断路器保护 | CircuitBreaker的名称 |
7 | FallbackHeaders | 为fallbackUri的请求头中添加具体的异常信息 | Header的名称 |
MapRequestHeader | 更新原始请求中的Header | Header的值 | |
9 | PrefixPath | 为原始请求头添加前缀 | 前缀路径 |
10 | PreserveHostHeader | 为请求添加preserverHostHeader=true的属性,路由过滤器会检查该属性以决定是否要发送原始的host | 无 |
11 | RequestRateLimiter | 用于对请求限流,限流算法为令牌桶 | keyResolver、rateLimiter、statusCode、denyEmptyKey、emptyKeyStatus |
12 | RedirectTo | 将原始请求重定向到指定的url | http状态码及重定向的url |
13 | RemoveHopByHopHeadersFilter | 为原始请求删除IETF组织规定的一系列Header | 默认就会启用,可以通过配置指定仅删除哪些Header |
14 | RemoveRequestHeader | 为原始请求删除某个Header | Header名称 |
15 | RemoveResponseHeader | 为原始响应删除某个Header | Header名称 |
16 | RewritePath | 重写原始的请求路径 | 原始路径正则表达式以及重写后路径的正则表达式 |
RewriteLocationResponseHeader | 重写响应头的Location 的值 |
||
18 | RewriteResponseHeader | 重写原始响应中的某个Header | Header名称,值的正则表达式,重写后的值 |
19 | SaveSession | 在转发请求之前,强制执行WebSession::save 操作 |
无 |
20 | SecureHeaders | 为原始响应添加一系列起安全作用的响应头 | 无,支持修改这些安全响应头的值 |
21 | SetPath | 修改原始的请求路径 | 修改后的值 |
22 | SetRequestHeader | 修改原始请求中的某个Header的值 | Header名称,修改后的值 |
23 | SetResponseHeader | 修改原始响应中某个Header的值 | Header名称,修改后的值 |
24 | SetStatus | 修改原始响应的状态码 | HTTP 状态码,可以是数字,也可以是字符串 |
25 | StripPrefix | 用于截断原始请求的路径 | 使用数字表示要截断的路径的数量 |
26 | Retry | 针对不同的响应进行重试 | retries、statuses、methods、series |
27 | RequestSize | 设置允许接收最大请求包的大小。如果请求包大小超过设置的值,则返回 413 Payload Too Large 设置允许接收最大请求包的大小。如果请求包大小超过设置的值,则返回 413 Payload Too Large |
请求包大小,单位为字节,默认值为5M |
28 | ModifyRequestBody | 在转发请求之前修改原始请求体内容 | 修改后的请求体内容 |
29 | ModifyResponseBody | 修改原始响应体的内容 | 修改后的响应体内容 |
30 | Default | 为所有路由添加过滤器 | 过滤器工厂名称及值 |
这里比较常用的如第25种,配置如下:
spring:
cloud:
gateway:
discovery:
locator:
enabled: true # 开启从注册中心动态创建路由的功能,利用微服务名称进行路由
routes:
# 路由id,建议配合服务名
- id: demo_route
#匹配路由名
uri: lb://demo-provider
predicates:
# 断言,路径相匹配的进行路由
- Path=/demo/**
filters:
- StripPrefix=1
一般情况下我们配合path路由使用,这里的意思是假如,我们的demo-provider服务种有一个/test的接口,实际上我们的请求路径经过网关时应该时/demo/test,这样就能把这个路由分发到demo-provider服务中,但是分发过去的路由是/demo/test,和我们实际的/test接口不一样。这时候我们用StripPrefix=1,来截取掉一级路由,这样转发过去的路由就是/test了。
自定义网关过滤器
除了上面提供的30种过滤器外,我们还可以实现自定义的过滤器。
1. 实现GatewayFilter接口和Ordered接口
gatewayFilter接口是为了实现请求过滤,ordered接口是为了给过滤器设定优先级,值越大级别越低。
想要实现一个自定义的过滤器,无非就是两个步骤:1.实现过滤器,2.将过滤器添加到具体路由上。
public class TokenGatewayFilter implements GatewayFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
System.out.println("这里处理自身逻辑");
return chain.filter(exchange);
}
@Override
public int getOrder() {
return 0;
}
}
@Configuration
class RouteConfiguration{
@Bean
public RouteLocator routeLocator(RouteLocatorBuilder builder){
return builder.routes().route( r->
r.path("/demo/**")
.uri("lb://demo-provider ")
.filter(new TokenGatewayFilter())
.id("demo_route "))
.build();
}
}
2.继承AbstractGatewayFilterFactory类
@Component
public class TokenCheckGatewayFilterFactory extends AbstractGatewayFilterFactory<TokenCheckGatewayFilterFactory.Config> {
public TokenCheckGatewayFilterFactory() {
super(Config.class);
}
@Override
public List<String> shortcutFieldOrder() {
return Arrays.asList("enabled");
}
@Override
public GatewayFilter apply(Config config) {
return (exchange, chain) -> {
system.out.println("这里处理自身逻辑")
return chain.filter(exchange);
};
}
public static class Config {
// 控制是否开启认证
private boolean enabled = true;
public Config() {}
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
}
}
这里我们可以直接在application.yml中为需要过滤的路由添加这个过滤器。
spring:
cloud:
gateway:
routes:
- id: demo_route # 路由id,建议配合服务名
uri: lb://demo-provider #匹配路由名
predicates:
- Path=/demo/** # 断言,路径相匹配的进行路由
filters:
- TokenCheck=true
需要注意的是,这个地方自定义的过滤器名称必须是XXGatewayFilterFactory,并且配置文件中配置过滤器时名字必须时这个XX。
当然,我们也可以为每个路由都添加这个过滤器,可以直接这样写配置,而不用在每个路由上都去写。
spring:
cloud:
gateway:
default-filters:
- TokenCheck=true
3.实现GlobalFilter和ordered
这个GlobalFilter从名字中就可以看出,是一个全局过滤器,也就是说实现这个接口后,所有的请求都会被过滤,我们就不需要在去找往某个路由中加过滤器了。
@Component
public class TokenGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
System.out.println("这里处理自身逻辑");
return chain.filter(exchange);
}
@Override
public int getOrder() {
return 0;
}
}
以上就是实现自定义网关过滤器的三种方式了。实际开发中根据需求来实现合适的过滤器就可以了。
Spring Cloud Alibaba系列(四)使用gateway作为服务网关的更多相关文章
- Spring Cloud Alibaba(四)实现Dubbo服务消费
本项目演示如何使用 Spring Cloud Alibaba 完成 Dubbo 的RPC调用. Spring Cloud与Dubbo Spring Cloud是一套完整的微服务架构方案 Dubbo是国 ...
- Spring Cloud Alibaba系列之分布式服务组件Dubbo
本博客的例子代码可以在github找到下载链接:代码下载 SpringBoot.SpringCloud Alibaba系列博客专栏:链接 1.分布式理论 1.1.分布式基本定义 <分布式系统原理 ...
- spring cloud 入门系列四:使用Hystrix 实现断路器进行服务容错保护
在微服务中,我们将系统拆分为很多个服务单元,各单元之间通过服务注册和订阅消费的方式进行相互依赖.但是如果有一些服务出现问题了会怎么样? 比如说有三个服务(ABC),A调用B,B调用C.由于网络延迟或C ...
- Spring Cloud Alibaba系列(一)nacos作为服务注册中心
Spring Cloud Alibaba各组件版本关系 Spring Cloud Alibaba Version Sentinel Version Nacos Version RocketMQ Ver ...
- Spring Cloud Alibaba系列(二)nacos作为服务配置中心
Nacos 提供用于存储配置和其他元数据的 key/value 存储,为分布式系统中的外部化配置提供服务器端和客户端支持.使用 Spring Cloud Alibaba Nacos Config,您可 ...
- Spring Cloud Alibaba系列(六)sentinel的实际应用
一.sentinel的持久化配置 上一章中我们通过Dashboard来为Sentinel客户端设置各种各样的规则,但是这些规则默认是存放在内存中,极不稳定,无法用于生成环境,所以需要将其持久化. Da ...
- Spring Cloud Alibaba系列(五)sentinel实现服务限流降级
一.sentinel是什么 sentinel的官方名称叫分布式系统的流量防卫兵.Sentinel 以流量为切入点,从流量控制.熔断降级.系统负载保护等多个维度保护服务的稳定性.在Spring Clou ...
- Spring Cloud Alibaba系列(三)使用feign进行服务调用
什么是Feign Feign是spring cloud提供的一个声明式的伪http客户端,它使得调用远程服务就像调用本地服务一样简单,只需要创建一个接口并添加一天注解即可. Nacos很好的兼容了Fe ...
- springcloud(十五):Spring Cloud 终于按捺不住推出了自己的服务网关 Gateway
Spring 官方最终还是按捺不住推出了自己的网关组件:Spring Cloud Gateway ,相比之前我们使用的 Zuul(1.x) 它有哪些优势呢?Zuul(1.x) 基于 Servlet,使 ...
随机推荐
- springboot连接数据源,配置数据库
Spring官方DriverManagerDataSource的配置 修改yml #配置数据源的属性 spring: datasource: driver-class-name: com.mysql. ...
- vue端口号被占用
今天在启动一个Vue项目的时候,遇到了一个问题. 得知是Vue项目端口号占用的问题. 解决方法: 换一个端口号. 在调用 npm run dev 的时候,实际上是在调用根目录下的 package ...
- Life In Changsha College- 第三次冲刺
第三次冲刺任务 设计登录注册功能. 用户故事 用户打开“生活在长大”的界面,选择登录 已注册过则输入用户名和密码直接登录 未注册用户则可选择注册功能,注册成功后登录 登录成功则弹出提示框 系统结构图环 ...
- [Objective-C] Xcode中常用的快捷键操作与插件
古人云“工欲善其事必先利其器”,打造和熟悉一个强大的开发环境,是每个程序员必须的! 在Xcode 6中有许多快捷键的设定可以使得你的编程工作更为高效,对于在代码文件中快速导航.定位Bug以及新增应用特 ...
- Java中的集合(四)PriorityQueue常用方法
Java中的集合(四)PriorityQueue常用方法 PriorityQueue的基本概念等都在上一篇已说明,感兴趣的可以点击 Java中的集合(三)继承Collection的Queue接口 查看 ...
- 一个 json 转换工具
在前后端的数据协议(主要指http和websocket)的问题上,如果前期沟通好了,那么数据协议上问题会很好解决,前后端商议一种都可以接受的格式即可.但是如果接入的是老系统.第三方系统,或者由于某些奇 ...
- UML ——六种依赖关系.md
在UML类图中,常见的有以下几种关系: 泛化(Generalization), 实现(Realization), 关联(Association), 聚合(Aggregation), 组合(Compos ...
- OkHttp,一次无奈的使用
一次使用OKHTTP的心痛历程 最近由于一些不得已的原因,接触到了OKHttp,说起来也挺Dan疼的,之前同事将生产附件上传地址配置成了测试地址,还好数量不多,没有造成太大的影响,况且的是这位同事又离 ...
- Java实现 LeetCode 721 账户合并(并查集)
721. 账户合并 给定一个列表 accounts,每个元素 accounts[i] 是一个字符串列表,其中第一个元素 accounts[i][0] 是 名称 (name),其余元素是 emails ...
- [apue] epoll 的一些不为人所注意的特性
之前曾经使用 epoll 构建过一个轻量级的 tcp 服务框架: 一个工业级.跨平台.轻量级的 tcp 网络服务框架:gevent 在调试的过程中,发现一些 epoll 之前没怎么注意到的特性. a) ...