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,使 ...
随机推荐
- 工业互联网可视化系统风格的抉择:线框模式之 3D 数据中心机房的实现
前言 3D 可视化,就是把复杂抽象的数据信息,以合适的视觉元素及视角去呈现,方便系统的展示.维护和管理.而在可视化系统的搭建选择上,所呈现的风格样式效果多种多样,各自所突出的适用场合也不尽相同.对于科 ...
- Java——分布式
分布式编程技术的基本思想:客户计算机产生一个请求,然后将这个请求通过网络发送到服务器.服务器处理这个请求,并发送回一个针对该客户端的响应,供客户端进行分析.客户端和服务端之间用代理进行通讯,客户端调用 ...
- poi--读取不同类型的excel表格
要想根据不同类型excel表格获取其数据,就要先判断其表格类型 poi-api种方法: getCellType public int getCellType() Return th ...
- windows 10 2016 企业版 长期服务 激活方式
试了很多,失败. 使用这个ok———————————————————————————————— 使用方式: 2.1.下载AAct.exe https://www.baidu.com/link?url ...
- SpringCloud(三)- OpenFeign简介及@FeignClient等注解的使用
唯能极于情,故能极于剑 有问题或错误请及时联系小编或关注小编公众号 "CodeCow",小编一定及时回复和改正,期待和大家一起学习交流 此文由四部分组成(OpenFeign简介.@ ...
- 《计算机网络》课程笔记 (Ch03-运输层)
为运行在不同主机上的应用进程之间提供逻辑通信功能. 将应用层报文切分为块,然后加上运输层首部,形成报文段,交付给网络层. 多路复用与多路分解 将网络层提供的主机到主机交付服务延伸到进程到进程交付服务. ...
- Golang源码学习:监控线程
监控线程是在runtime.main执行的时候在系统栈中创建的,监控线程与普通的工作线程区别在于,监控线程不需要绑定p来运行. 监控线程的创建与启动 简单的调用图 先给出个简单的调用图,好心里有数,逐 ...
- Postgre数据库自定义函数
自定函数 1.查询函数: select prosrc from pg_proc where proname='test' 参数说明 : test 为函数名. 2.删除函数: drop function ...
- DQN(Deep Q-learning)入门教程(五)之DQN介绍
简介 DQN--Deep Q-learning.在上一篇博客DQN(Deep Q-learning)入门教程(四)之Q-learning Play Flappy Bird 中,我们使用Q-Table来 ...
- 使用jetty作为内嵌服务器启动项目
http://blog.csdn.net/robinpipi/article/details/7557035 需求:把jetty作为内嵌的一个服务器,直接启动,web项目不用部署在应用服务器中.在网上 ...