一文带你吃透微服务守门神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相关推荐

  1. 微服务网关:SpringCloud Gateway保姆级入门教程

    什么是微服务网关 SpringCloud Gateway是Spring全家桶中一个比较新的项目,Spring社区是这么介绍它的: 该项目借助Spring WebFlux的能力,打造了一个API网关.旨 ...

  2. 什么是微服务网关?SpringCloud Gateway保姆级入门教程

    什么是微服务网关 SpringCloud Gateway是Spring全家桶中一个比较新的项目,Spring社区是这么介绍它的: 该项目借助Spring WebFlux的能力,打造了一个API网关.旨 ...

  3. 微服务架构,springcloud核心组件和实战,docker容器

    文章目录 前言 一.微服务开发基础 1.微服务架构开发 1.1单体架构的应用的困境 1.2 微服务架构 1.2.1 理解微服务架构 1.2.1 微服务的优缺点 1.3 微服务架构设计 1.3.1 微服 ...

  4. Java微服务篇2——SpringCloud

    Java微服务篇2--SpringCloud 1.微服务架构 1.1.单体应用架构 的⽤户量.数据量规模都⽐较⼩,项目所有的功能模块都放在一个工程中编码. 编译.打包并且部署在一个Tomcat容器中的 ...

  5. spring cloud gateway 网关_微服务网关Spring Cloud Gateway全搞定

    一.微服务网关Spring Cloud Gateway 1.1 导引 文中内容包含:微服务网关限流10万QPS.跨域.过滤器.令牌桶算法. 在构建微服务系统中,必不可少的技术就是网关了,从早期的Zuu ...

  6. 微服务架构与SpringCloud

    微服务架构简述 通常而言,微服务架构是一种架构模式或者说是一种架构风格,它提倡将单一应用程序划分成一组小的服务,每个服务运行在其独立的自己的进程中,服务之间互相协调.互相配合为用户提供最终价值.服务之 ...

  7. 【微服务架构】SpringCloud组件和概念介绍

    [微服务架构]SpringCloud组件和概念介绍(一) 一:什么是微服务(Microservice)微服务英文名称Microservice,Microservice架构模式就是将整个Web应用组织为 ...

  8. 容器化技术与微服务结合---结合springcloud微服务框架进行部署(含切换成阿里云docker仓库)(五)

    目录 系列 更换成阿里云仓库 开通阿里云镜像服务 创建仓库 本地k8s切换成阿里云的镜像仓库 测试阿里云镜像 准备简单的微服务 eureka 应用配置 k8s配置: demo-a 应用配置 k8s配置 ...

  9. 微服务架构与SpringCloud:微服务架构的特点

    微服务架构与Spring Cloud 近几年大家都在谈论云原生和微服务,例如 © 云原生技术能够帮助公司和机构在私有云.公有云和混有云等新型动态环境中,构建和运行可弹性扩展的应用. 微服务架构是一项在 ...

最新文章

  1. 宏基因组分析第9期(报名直播课免费参加线下2020.10本年最后一期)
  2. 我们的2009 梦想照进了现实
  3. 小程序获取头像试试水 02《 程序员变现指南之 微信QQ 小程序 真的零基础开发宝典》
  4. python flask框架是什么_Flask框架是什么?带你安装运行第一个Flask程序
  5. Java 7:使用NIO.2进行文件过滤-第2部分
  6. addition过程 sgnb_5G NR接入优化问题排查思路
  7. 使用蓝图构建Flask项目目录
  8. 基本排序算法[python实现]
  9. 11-7 无底洞问题
  10. 极品菜系列3 [图]
  11. mac 安装homebrew 并替换清华镜像
  12. RHEL6.3下如何解决DNS主从复制与selinux的并存问题
  13. LabVIEW安装多个NI软件产品时的安装顺序
  14. 全减器的原理与vhdl实现
  15. 微波射频十多年的舍与得
  16. jq ajax input file,基于jq的input file文件上传
  17. 音乐计算机锦鲤抄,锦鲤抄 (feat. 银临)
  18. java实习找工作经历
  19. ios ipad里面调用系统相册图片不完整解决方法
  20. 能代替苹果pencil的手写笔有吗?比较好用的ipad手写笔推荐

热门文章

  1. nodejs 学习笔记
  2. 零基础童鞋快速学习前端开发 ---- (1)
  3. 大数据24小时:今日头条因“不正当竞争”起诉百度,金山云47天内获46亿元融资
  4. matlab中发现一特么别好用的画三维图函数ezmesh()
  5. Qt官方示例-计算器
  6. 【算法题】触宝2018编程题二
  7. 7-8 整数四则运算 (10分)
  8. 自学前端第二十九天 CSS高级之细节技巧
  9. 17个最好用的iPhone数据恢复工具【2019更新】
  10. Mybatis <choose> <when> <otherwise>