一文带你吃透微服务守门神SpringCloud-GateWay
一文带你吃透微服务守门神SpringCloud-GateWay
- GateWay简单介绍
- Gateway和Zuul的对比:
- gateWay的几个核心概念
- 入门案例
- 网关层负载均衡
- gateWay 工作原理
- 三大组件:高级工作原理图(左) 粗
- 工作流程:
- 网关路由断言工厂(路由规则)
- path路由规则:
- After路由规则:
- 其他路由规则
- 网关过滤器
- 分类
- PrefixPath 过滤器(局部)
- 去除前缀过滤器(局部)
- 自定义过滤器(重要)
- 自定义全局过滤器
- 过滤器优先级
- 网关降级
- 网关限流
- 令牌桶:
- 网关令牌桶限流(使用redis实现)
GateWay简单介绍
一句话:网关是微服务架构系统的守门神 网关本身是一个微服务,是所有微服务的入口。鉴权、限流、路由、监控【监控所有方法执行调用时间】
Gateway和Zuul的对比:
1.gateway是zuul的代替者。并不是zuul有什么大问题 而是后面zuul宣布闭源了 所以springcloud自己做了一个gateway后来就不再集成zuul了
2.Zuul是基于servlet阻塞式的并且不支持任何长连接 gateway是使用Reactor和springboot开发的 使用非阻塞式的API 性能要优于zuul
gateWay的几个核心概念
非常重要!
必须要对这几个概念熟悉了 才能分析他的高级特性以及功能
1. route/路由:路由是网关的最基本组成,由一个路由 id、一个目标地址 url,一组断言工厂及一组
filter组成。若断言为 true,则请求将经由 filter 被路由到目标 url。 一句话理解 就是定义一条游戏规则
2. predicate断言:断言即一个条件判断,根据当前的 http 请求进行指定规则的匹配,比如说 http
请求头,请求时间等。只有当匹配上规则时,断言才为 true,此时请求才会被直接路由到目标地址
(目标服务器),或先路由到某过滤器链,经过过程器链的层层处理后,再路由到相应的目标地址
(目标服务器)。一句话理解 就是定义一个游戏规则中的多个小规则
3. filter过滤器:对请求进行处理的逻辑部分。当请求的断言为 true 时,会被路由到设置好的过滤
器,以对请求进行处理。例如,可以为请求添加一个请求头,或添加一个请求参数,或对请求URI
进行修改等。总之,就是对请求进行处理。 一句话理解 对请求做过滤
入门案例
需求:访问网关服务跳转到百度(静态路由)
1.创建工程并且加入依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>springcloud-alibaba-sxw-parent</artifactId><groupId>com.sxw</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>03-gateway-simple</artifactId><properties><spring-cloud.version>Hoxton.SR8</spring-cloud.version><spring-cloud-alibaba.version>2.2.3.RELEASE</spring-cloud-alibaba.version></properties><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency><!-- actuator依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency></dependencies><dependencyManagement><!-- spring-cloud的依赖--><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud.version}</version><type>pom</type><scope>import</scope></dependency><!-- spring-cloud-alibaba的依赖 --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-alibaba-dependencies</artifactId><version>${spring-cloud-alibaba.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement>
</project>
2.配置文件
server:port: 9000spring:cloud:gateway:#添加一组路由routes:#路由id 唯一标识/名字- id: route_to_baidu#路由到的目标地址uri: http://www.baidu.com#断言 也就是规则 我需要定义什么样的请求被被这个路由拦截predicates:- Path=/**
3.测试
4.这是使用配置文件配置 也可以使用java类代码来配置
//区别在于可以直接声明好 不需要在配置文件上修改
@SpringBootApplication
public class ApiConfigGateWayApplication {public static void main(String[] args) {SpringApplication.run(ApiConfigGateWayApplication.class, args);}@Bean//使用的是构建者模式+java8 lambda的语法来编写 优雅简单public RouteLocator locator(RouteLocatorBuilder builder){return builder.routes().route(predicateSpec -> predicateSpec.path("/**").uri("https://www.baidu.com").id("api_config_route_to_baidu")).build();}
}
网关层负载均衡
需求:我的服务组成了集群 那么网关支持负载均衡吗? 当然支持
1.pom依赖
小疑问 为什么需要加入注册中心的依赖?
因为网关本身也是一个微服务 那么也可以将他注册到配置中心
负载均衡 顾名思义 用过feign的同学就知道 有点像域名找服务一样
<!-- 注册中心支持 其他依赖省略... 这里使用nacos作注册中心 -->
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
2.配置文件(同样可以使用java配置类的方式进行配置)
这里主要关注这个路由规则
uri这个参数:lb://provider
lb:是网关自有的协议 至于为什么叫lb 因为源码已经写死 感兴趣的可以自己查阅ribbon中的实现
provoder:这个其实就是服务名字 这个服务的集群不管有几个 服务名是不变的
这样就可以通过nacos找到这个名字背后的集群地址 通过某种负载均衡机制找到具体某一台 然后进行请求转发
erver:port: 9002spring:application:name: sxw-gateway-ribbon#注册中心配置cloud:nacos:discovery:server-addr: 127.0.0.1:8848#开启与discoveryClient的整合gateway:discovery:locator:enable: true#路由配置routes:- id: ribbon_routeuri: lb://providerpredicates:- Path=/provider/depart/**
3.修改均衡策略 随机负载均衡策略
@Bean
public IRule loadBalanceRule(){return new RandomRule();
}
4.启动提供者服务provider集群
5.验证
···
http://localhost:9002/provider/depart/get/122
···
gateWay 工作原理
三大组件:高级工作原理图(左) 粗
网关处理器映射器组件 HandlerMapping
网关WEB处理器组件Web Hnadler
网关过滤器组件Filter**
工作流程:
组装网关上下文->循环遍历所有的Mapper获取Handler->匹配路由信息,如果断言失败就返回->进入Filter过滤链条调用链->前置过滤器->自定义过滤器->后置过滤器
网关路由断言工厂(路由规则)
path路由规则:
含义:对这个路径进行拦截
如 - Path=/info/** 请求地址:http://localhost:9000/info/hello 那么就会被path_showinfo_route这个路由拦截转发到http://localhost:8088这个服务
也可以理解 访问 http://localhost:9000/info/hello 等同于访问 http://localhost:8088/info/hello
1.添加两组路由策略
server:port: 9000spring:cloud:gateway:#配置断言工厂1 路由到http://localhost:8999 这个服务routes:- id: path_consumer_routeuri: http://localhost:8999predicates:- Path=/consumer/depart/**#配置断言工厂2 路由到http://localhost:8088 这个服务- id: path_showinfo_routeuri: http://localhost:8088predicates:- Path=/info/**
2.测试
测试1:http://localhost:9000/consumer/depart/get/1
测试2:http://localhost:9000/info/hello
After路由规则:
一句话 配置的时间要比现在的时间小才能够访问 格式固定
如下:这样是不能访问的
配置文件
server:port: 9000spring:cloud:gateway:routes:- id: after_routeuri: http://www.baidu.compredicates:- After=2022-01-20T17:42:47.789-07:00[Asia/Shanghai]
其他路由规则
举一反三:基本的玩法就是配置 根据你的业务需要进行配置即可 不需要全部背熟 常用的还有如下这几种
- Before
- Between
- Cookie
- Header
- Host
- Method
网关过滤器
分类
- 局部过滤器:应用于单个路由策略上,其功能仅对路由断言为 true 的请求起作用
- 全局过滤器:应用于所有路由策略上,其功能就像前面的配置文件中设置的默认 Filter
PrefixPath 过滤器(局部)
任何请求都会进行拦截 并在请求地址上增加/info然后将请求转发到目标地址
localhot:9999/findById?id=1 添加之后: localhost:8088/info/findById?id=1
有啥用?保护我们的接口地址 防止被人恶意攻击
spring:cloud:gateway:routes:- id: prefixpath_routeuri: http://localhost:8088predicates:- Path=/**filters:- PrefixPath=/info
去除前缀过滤器(局部)
举一反三
localhost:9999/user/findById?id=1 去除之后 localhot:9999/findById?id=1
自定义过滤器(重要)
当内置的过滤器不满足业务需要时 当然也支持自定义的过滤器
比如支付有支付的独立网关,我们可以要求,所有的服务进入支付的相关服务之前需要有支付系统颁发的权限token,此时就可以在支付网关做这样一个校验支付token权限的事情。
需求:往请求头添加一个参数
1.编写自定义filter
public class CustomerFilter implements GatewayFilter {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {//1.构建改变后的request对象ServerHttpRequest request = exchange.getRequest().mutate().header("X-Request-customer", "customer").build();//2.将改变的request对象置入exchange对象中ServerWebExchange webExchange = exchange.mutate().request(request).build();//3.设置修改后的exchange对象return chain.filter(webExchange);}
}
2.配置自定义过滤器生效
@Bean
public RouteLocator routeLocator(RouteLocatorBuilder builder){return builder.routes().route(predicateSpec -> predicateSpec.path("/**").filters(gfs-> gfs.filter(new CustomerFilter())).uri("http://localhost:8088").id("updateRequest")).build();
}
3.另外一个服务(转发过去的服务)http://localhost:8088
@RestController()
@RequestMapping("/info")
public class InfoController {@GetMapping("/hello")public String hello(HttpServletRequest request){String header = request.getHeader("X-Request-customer");return "new header:" + header;}
}
4.测试
自定义全局过滤器
模拟鉴权 重要!
全局过滤器 针对所有的路由都生效 只需要交由spring容器管理即可
需求:判断当前请求是否携带了token 如果没有就返回错误信息 (实际开发应校验该token是否合法 也就是这个token存不存在 是否过期以及包含的用户是否合法)
1.定义全局过滤器
@Component
public class GlobalFilter implements org.springframework.cloud.gateway.filter.GlobalFilter, Ordered {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {//获取请求中的tokenString token = exchange.getRequest().getQueryParams().getFirst("token");//校验是否存在if (StringUtils.isEmpty(token)){//如果不存在 返回对应的错误码exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);return exchange.getResponse().setComplete();}//如果存在则放行请求return chain.filter(exchange);}@Overridepublic int getOrder() {//最高级别 返回的int值越大 优先级越高 spring-core的组件return Ordered.HIGHEST_PRECEDENCE;}
}
2.定义一个路由规则 因为是全局的 不需要指定参数filter
@Bean
public RouteLocator routeLocator(RouteLocatorBuilder builder){return builder.routes().route(predicateSpec -> predicateSpec.path("/**").uri("http://localhost:8088").id("global_filter_route")).build();
}
3.测试
测试1不带 token访问:http://localhost:9004/info/hello
测试2:带token访问http://localhost:9004/info/hello?token=222
过滤器优先级
值越大优先级越高的原则
网关降级
当我们路由到的服务不可用时 一样会报错 此时我们期望 网关可以实现降级 为什么需要降级? 给用户友好提示 不要一堆报错信息 看不懂!
1.添加依赖
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-circuitbreaker-reactor-resilience4j</artifactId>
</dependency>
2.定义降级处理器controller
@RestController
public class FallbackController {@RequestMapping("fallback")public Map<String,String> fallback(){Map<String,String> map = new HashMap<>();map.put("code","200");map.put("msg","服务降级");map.put("data",null);return map;}
}
3.编写降级配置(filter)-针对一个路由
@Bean
public RouteLocator routeLocator(RouteLocatorBuilder builder){return builder.routes().route(predicateSpec -> predicateSpec.path("/**").filters(fs->fs.circuitBreaker(config -> {//配置降级config.setName("myCircuitBreaker");config.setFallbackUri("forward:/fallback");})).uri("http://localhost:8088").id("global_filter_route")).build();
}
4.测试针对一个路由降级 把提供者服务下线http://localhost:9004/info/hello?token=222
5.配置全局路由熔断 配置文件
spring:cloud:gateway:default-filters:- name: CircuitBreakerargs:name: myCircuitBreakerfallbackUri: forward:/fallback routes: - id: test_filter uri: http://localhost:8088 predicates: - Path=/**
网关限流
针对一些恶意攻击 为了保护网关后面的服务 就可以将一些无效的请求拦截掉 这样的做法也是非常必要的
使用redis 令牌桶
令牌桶:
关键:1.桶(放redis 放令牌 放一定数量的令牌) 2.速率
含义:如果需要执行请求 需要去桶里拿到令牌 才能放行 否则被拒绝并返回
网关令牌桶限流(使用redis实现)
1.依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
2.配置文件
spring:redis:host: localhostport: 6379cloud:gateway:routes:- id: requestRateLimiter_filteruri: http://localhost:8088predicates:- Path=/info/**filters:- name: RequestRateLimiterargs:# key-resolver:用于限流的键的解析器的 Bean 对象的名字。它使用 SpEL 表达式根据#key-resolver: "#{@keyResolver}"# replenishRate:令牌桶每秒填充平均速率。redis-rate-limiter.replenishRate: 2# burstCapacity:令牌桶总容量。redis-rate-limiter.burstCapacity: 5
3.配置类
Bean
//配置令牌同算法key:将主机名作为限流key
public KeyResolver keyResolver(){return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostName());
}
4.测试
一文带你吃透微服务守门神SpringCloud-GateWay相关推荐
- 微服务网关:SpringCloud Gateway保姆级入门教程
什么是微服务网关 SpringCloud Gateway是Spring全家桶中一个比较新的项目,Spring社区是这么介绍它的: 该项目借助Spring WebFlux的能力,打造了一个API网关.旨 ...
- 什么是微服务网关?SpringCloud Gateway保姆级入门教程
什么是微服务网关 SpringCloud Gateway是Spring全家桶中一个比较新的项目,Spring社区是这么介绍它的: 该项目借助Spring WebFlux的能力,打造了一个API网关.旨 ...
- 微服务架构,springcloud核心组件和实战,docker容器
文章目录 前言 一.微服务开发基础 1.微服务架构开发 1.1单体架构的应用的困境 1.2 微服务架构 1.2.1 理解微服务架构 1.2.1 微服务的优缺点 1.3 微服务架构设计 1.3.1 微服 ...
- Java微服务篇2——SpringCloud
Java微服务篇2--SpringCloud 1.微服务架构 1.1.单体应用架构 的⽤户量.数据量规模都⽐较⼩,项目所有的功能模块都放在一个工程中编码. 编译.打包并且部署在一个Tomcat容器中的 ...
- spring cloud gateway 网关_微服务网关Spring Cloud Gateway全搞定
一.微服务网关Spring Cloud Gateway 1.1 导引 文中内容包含:微服务网关限流10万QPS.跨域.过滤器.令牌桶算法. 在构建微服务系统中,必不可少的技术就是网关了,从早期的Zuu ...
- 微服务架构与SpringCloud
微服务架构简述 通常而言,微服务架构是一种架构模式或者说是一种架构风格,它提倡将单一应用程序划分成一组小的服务,每个服务运行在其独立的自己的进程中,服务之间互相协调.互相配合为用户提供最终价值.服务之 ...
- 【微服务架构】SpringCloud组件和概念介绍
[微服务架构]SpringCloud组件和概念介绍(一) 一:什么是微服务(Microservice)微服务英文名称Microservice,Microservice架构模式就是将整个Web应用组织为 ...
- 容器化技术与微服务结合---结合springcloud微服务框架进行部署(含切换成阿里云docker仓库)(五)
目录 系列 更换成阿里云仓库 开通阿里云镜像服务 创建仓库 本地k8s切换成阿里云的镜像仓库 测试阿里云镜像 准备简单的微服务 eureka 应用配置 k8s配置: demo-a 应用配置 k8s配置 ...
- 微服务架构与SpringCloud:微服务架构的特点
微服务架构与Spring Cloud 近几年大家都在谈论云原生和微服务,例如 © 云原生技术能够帮助公司和机构在私有云.公有云和混有云等新型动态环境中,构建和运行可弹性扩展的应用. 微服务架构是一项在 ...
最新文章
- 宏基因组分析第9期(报名直播课免费参加线下2020.10本年最后一期)
- 我们的2009 梦想照进了现实
- 小程序获取头像试试水 02《 程序员变现指南之 微信QQ 小程序 真的零基础开发宝典》
- python flask框架是什么_Flask框架是什么?带你安装运行第一个Flask程序
- Java 7:使用NIO.2进行文件过滤-第2部分
- addition过程 sgnb_5G NR接入优化问题排查思路
- 使用蓝图构建Flask项目目录
- 基本排序算法[python实现]
- 11-7 无底洞问题
- 极品菜系列3 [图]
- mac 安装homebrew 并替换清华镜像
- RHEL6.3下如何解决DNS主从复制与selinux的并存问题
- LabVIEW安装多个NI软件产品时的安装顺序
- 全减器的原理与vhdl实现
- 微波射频十多年的舍与得
- jq ajax input file,基于jq的input file文件上传
- 音乐计算机锦鲤抄,锦鲤抄 (feat. 银临)
- java实习找工作经历
- ios ipad里面调用系统相册图片不完整解决方法
- 能代替苹果pencil的手写笔有吗?比较好用的ipad手写笔推荐