SpringCloud之Gateway组件简介

本文涉及的产品
云数据库 Redis 版,标准版 2GB
推荐场景:
搭建游戏排行榜
传统型负载均衡 CLB,每月750个小时 15LCU
云原生内存数据库 Tair,内存型 2GB
简介: 网关类似于海关或者大门,出入都需要经过这个网关。别人不经过这个网关,永远也看不到里面的东西。可以在网关进行条件过滤,比如大门只有对应的钥匙才能入内。网关和大门一样,永远暴露在最外面

网关的理解

网关类似于海关或者大门出入都需要经过这个网关。别人不经过这个网关,永远也看不到里面的东西。可以在网关进行条件过滤,比如大门只有对应的钥匙才能入内。网关和大门一样,永远暴露在最外面

不使用网关

  • 前端需要记住每一个服务的IP和port
  • 如果有一个服务部署多台,那么前端需要自行分配

使用网关

  • 前端不需要记每一个服务的IP和port,只需要将请求发送到网关即可,网关根据资源路径做路由跳转
  • 网关中可以做安全控制 比如Token校验、限流等
  • 可以做负载均衡

Gateway的理解

是Spring官网推出的一套网关组件,用来取代Zuul

它的目的是为了让路由跳转更加方便、灵活,还提供了一些强大的过滤器功能。比如:IP黑名单、Token校验等

基于webFlux框架实现,webFlux框架底层使用了高性能的Reactor模式通信框架的Netty

Gateway是在Spring生态系统之上构建的API网关服务,基于Spring 5,Spring Boot 2和Project Reactor等技术。

Gateway旨在提供一种简单而有效的方式来对API进行路由,以及提供一些强大的过滤器功能,例如:熔断、限流、重试等。

① Gateway工作原理

客户端发送请求到Gatewaty,然后Gateway HandlerMapping通过对比映射,找到与其匹配的路由,将其发送到Gateway WebHandler。Handler再通过指定的过滤器将请求分发到实际的业务逻辑,并返回。

在过滤器中可以做增加代码:

  • 请求之前[pre]做校验等
  • 请求之后[post]做日志输出等

Gateway核心逻辑:根据资源路径做路由转发,并且执行过滤器链。

② Gateway三大核心概念

路由(Route)

和eureka结合做动态路由

组成部分:一个路由ID、一个唯一资源定位符URI、一组断言、一组Filter

如果路由断言为真,那么URL和配置路由匹配

断言(Predicate)

返回一个boolean表达式

过滤器(Filter)

Gateway中的过滤器分为Gateway Filter(针对一个路由)和Global Filter(全局)

在过滤器中可以编写校验规则以及响应的处理

③ Gateway和Nginx区别

Nginx做限流、负载均衡、路由都需要修改nginx.conf配置文件

Gateway和eureka结合,实现了自动路由跳转;和Ribbon集合,实现了负载均衡。Gateway也能够通过配置进行限流的实现

 

路由使用

① 访问流程

② Loing-service

1. @RestController
2. public class LoginController {
3. 
4. @GetMapping("doLogin")
5. public String doLogin(String username,String password){
6.         System.out.println(username+" -> "+password);
7. String token = UUID.randomUUID().toString();
8. return token;
9.     }
10. }

② Gateway-server

gateway依赖

1. <dependency>
2. <groupId>org.springframework.cloud</groupId>
3. <artifactId>spring-cloud-starter-gateway</artifactId>
4. </dependency>

配置路由

1. server:
2.   port: 80
3. spring:
4.   application:
5.     name: gateway-server
6.   cloud:
7.     gateway:
8.       enabled: true # 默认开启Gateway
9.       routes: # 路由组
10.         - id: login-service-route # 路由ID 保证唯一
11.           uri: http://localhost:8080 # uri唯一资源定位符 url唯一资源标识符
12.           predicates: # 断言
13.             - Path=/doLogin # 和服务中的路径匹配

④ 编程式路由

不借助配置文件,使用编码的方式来实现路由转发

1. @Configuration
2. public class RouteConfig {
3. 
4. @Bean
5. public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
6. return builder.routes()
7.                 .route("anime-id", r->r.path("/anime").uri("https://www.bilibili.com"))
8.                 .route("variety-id",r->r.path("/variety").uri("https://www.bilibili.com"))
9.                 .build();
10.     }
11. }

如果在uri后面的资源路径和path中的路由一样,那么gateway不会把path中的路由拼接到uri后面。

编程式和配置文件的方式可以结合使用

动态路由

如果在路由转发时直接将URL写死,从而IP和port也被写死,那么Gateway将无法达到负载均衡的效果。应该是只提供服务名,然后通过这个名字去找对应的服务,从而达到负载均衡的效果

让Gateway服务也注册到注册中心中,那么Gateway就能够拥有所有的服务信息

Gateway会根据注册中心中的服务列表,以每个服务名为路径创建动态路由进行转发

① 第一种实现方式

使用lb(Load Balance)协议,表示启用Gateway的负载均衡功能

1. server:
2.   port: 80
3. spring:
4.   application:
5.     name: gateway-server
6.   cloud:
7.     gateway:
8.       enabled: true # 默认开启Gateway
9.       routes: # 路由组
10.         - id: login-service-route # 路由ID 保证唯一
11.           # uri: http://localhost:8080 # uri唯一资源定位符 url唯一资源标识符
12.           uri: lb://login-service # lb://服务名
13.           predicates:
14.             - Path=/doLogin # 和服务中的路径匹配

调用:http://localhost/doLogin

② 第二种实现方式

使用服务发现,自动创建动态路由从而实现负载均衡

1. server:
2.   port: 80
3. spring:
4.   application:
5.     name: gateway-server
6.   cloud:
7.     gateway:
8.       enabled: true # 默认开启Gateway
9.       discovery:
10.         locator:
11.            enabled: true # 开启动态路由
12.            lower-case-service-id: true # 将注册列表中的服务名小写

断言

在项目启动的时候,Gateway会去加载一些路由断言工厂,例如:After、Query

断言就是给路由增加一些匹配规则,如果发送的请求符合这些规则,就能够去访问,否则404。简单说这些匹配规则也就是一些boolean表达式,要么true进入,要么false拒绝

① 分类

② 使用

在配置文件中,对某个路由进行操作。动态路由不能使用断言

1. spring:
2.   application:
3.     name: gateway-server
4.   cloud:
5.     gateway:
6.       enabled: true # 默认开启Gateway
7.       routes:
8.         - id: login-service-route
9.           uri: lb://login-service
10.           predicates:
11.             - Path=/doLogin
12.             - Method=GET,POST # GET,POST请求能够访问
13.             - After=2022-11-02T17:23:16.423+08:00[Asia/Shanghai] # 在指定时间后才能访问 通过ZonedDateTime获取
14.             - Query=username,admin. # 必须给username传值 后面的值必须是:adminx

过滤器

Gateway中的过滤器和Servlet里面的过滤器差不多,用户修改进入HTTP请求和HTTP响应

分为GatewayFilter(针对某一个路由)和GlobalFilter(全局过滤)

① 自定义全局过滤器

在自定义过滤器中编写业务逻辑,比如Token校验、限流。

1. @Component
2. public class TestFilter implements GlobalFilter {
3. 
4. @Override
5. public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
6. // 获取请求对象
7. ServerHttpRequest request = exchange.getRequest();
8. RequestPath path = request.getPath();
9. // 打印路由以及服务名
10.         System.out.println(path);
11. HttpHeaders headers = request.getHeaders();
12. // 获取主机IP
13. String ip = headers.getHost().getHostName();
14.         System.out.println(ip);
15. // 获取响应对象
16. ServerHttpResponse response = exchange.getResponse();
17. // 放过
18. return chain.filter(exchange);
19.     }
20. }

定义过滤器顺序

1. @Component
2. public class TestFilter implements Ordered {
3. 
4. @Override
5. public int getOrder() {
6. // 数字越小 越往前
7. return 0;
8.     }
9. }

返回值处理

1. // 获取响应对象
2. ServerHttpResponse response = exchange.getResponse();
3. // 设置响应头
4. response.getHeaders().set("content-Type","application/json;charset=UTF-8");
5. // 封装返回数据
6. Map<String,Object> map = new HashMap<>();
7. map.put("code", 401);
8. map.put("msg","没有该权限");
9. ObjectMapper objectMapper = new ObjectMapper();
10. try {
11. // 将map集合转为byte数组
12. byte[] bytes = objectMapper.writeValueAsBytes(map);
13. // 将byte数组包装成一个数据缓冲包
14. DataBuffer wrap = response.bufferFactory().wrap(bytes);
15. // 返回
16. return response.writeWith(Mono.just(wrap));
17. } catch (JsonProcessingException e) {
18.     e.printStackTrace();
19. }

限流

在一定的时间段内,限制用户的访问频率。

① 限流模型

漏斗算法、令牌通算法、计算器算法、窗口滑动算法

入不敷出:生产令牌的速度赶不上使用的速度

  1. 系统以提前配置好的速率去生产令牌。
  2. 给令牌桶设置一个阈值,当桶满后,多余的令牌直接丢弃
  3. 客户发送请求都需要去拿令牌
  4. 如果没有拿到令牌该请求不能成功访问
  5. 如果拿到令牌将去访问服务,完成业务处理后删除令牌
  6. 当桶中的令牌数达到最低额度时,使用完的令牌返回

② Gateway中的限流

Gateway中已经内置了RequestRateLimiterGatewayFilterFactory,结合Redis做令牌桶算法。需要导入redis依赖

1. <dependency>
2. <groupId>org.springframework.boot</groupId>
3. <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
4. </dependency>

配置限流规则

1. @Configuration
2. public class RequestLimiterConfig {
3. 
4. /*
5.       基于IP做限流
6.      */
7. @Bean
8. @Primary // 主候选
9. public KeyResolver ipKeyResolver(){
10. return exchange-> Mono.just(exchange.getRequest().getHeaders().getHost().getHostName());
11.     }
12. 
13. /*
14.       基于API接口最限流
15.      */
16. @Bean
17. public KeyResolver apiKeyResolver(){
18. return exchange -> Mono.just(exchange.getRequest().getPath().toString());
19.     }
20. }

修改配置文件

1. spring:
2.   application:
3.     name: gateway-server
4.   cloud:
5.     gateway:
6.       enabled: true # 默认开启Gateway
7.       routes:
8.         - id: login-service-route
9.           uri: lb://login-service
10.           predicates:
11.             - Path=/doLogin
12.           filters:
13.             - name: RequestRateLimiter # 过滤器名称
14.               args:
15.                 key-resolver: '#{@ipKeyResolver}' # Bean对象的名字
16.                 redis-rate-limiter.replenishRate: 1 # 每秒钟生产多少令牌
17.                 redis-rate-limiter.burstCapacity: 3 # 令牌桶中的容量

只针对某一个路由

跨域配置

跨域:CORS同源策略。

因为网关是服务的最边缘,所有的请求都需要走网关,将跨域的配置写在网关。

编程式

1. @Configuration
2. public class CorsConfig {
3. @Bean
4. public CorsWebFilter corsFilter() {
5. CorsConfiguration config = new CorsConfiguration();
6.         config.addAllowedMethod("*");
7.         config.addAllowedOrigin("*");
8.         config.addAllowedHeader("*");
9. UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(new PathPatternParser());
10.         source.registerCorsConfiguration("/**", config);
11. return new CorsWebFilter(source);
12.     }
13. }

配置文件

1. spring:
2.   cloud:
3.     gateway:
4.       globalcors:
5.         cors-configurations:
6. '[/**]': # 针对那些路径
7.             allowCredentials: true # 可以携带Cookie
8.             allowedHeaders: '*'
9.             allowedMethods: '*'
10.             allowedOrigins: '*'

面试题相关

什么是微服务网关

Spring Cloud Gateway 是 Spring 官方基于 Spring 5.x,Spring Boot 2.0 和 Project Reactor 等技术开发的网关,Spring Cloud Gateway 旨在为微服务架构提供一种简单而有效的统一的 API 路由管理方式。Spring Cloud Gateway 作为 Spring Cloud 生态系统中的网关,目标是替代 Netflix Zuul,其不仅提供统一的路由方式,并且基于 Filter 链的方式提供了网关基本的功能,例如:安全性、监视/指标和弹性。

 

使用Gateway的优势

Spring Cloud Gateway 可以看做是一个 Zuul 1.x 的升级版和代替品,比 Zuul 2 更早的使用 Netty 实现异步 IO,从而实现了一个简单、比 Zuul 1.x 更高效的、与 Spring Cloud 紧密配合的 API 网关。

Spring Cloud Gateway 里明确的区分了 Router 和 Filter,并且一个很大的特点是内置了非常多的开箱即用功能,并且都可以通过 SpringBoot 配置或者手工编码链式调用来使用

比如内置了 10 种 Router,使得我们可以直接配置一下就可以随心所欲的根据 Header、或者 Path、或者 Host、或者 Query 来做路由。

比如区分了一般的 Filter 和全局 Filter,内置了 20 种 Filter 和 9 种全局 Filter,也都可以直接用。当然自定义 Filter 也非常方便。

zuul和spring cloud gateway的对比

  • zuul:是Netflix的,是基于servlet实现的,阻塞式的api,不支持长连接。
  • gateway:是springcloud自己研制的微服务网关,是基于Spring5构建,能够实现响应式非阻塞式的Api,支持长连接

gateway的组成

  • 路由 : 网关的基本模块,有ID,目标URI,一组断言和一组过滤器组成
  • 断言:就是访问该旅游的访问规则,可以用来匹配来自http请求的任何内容,例如headers或者参数
  • 过滤器:这个就是我们平时说的过滤器,用来过滤一些请求的,gateway有自己默认的过滤器,具体请参考官网,我们也可以自定义过滤器,但是要实现两个接口,ordered和globalfilter
相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
5天前
|
SpringCloudAlibaba JavaScript 前端开发
谷粒商城笔记+踩坑(2)——分布式组件、前端基础,nacos+feign+gateway+ES6+vue脚手架
分布式组件、nacos注册配置中心、openfegin远程调用、网关gateway、ES6脚本语言规范、vue、elementUI
谷粒商城笔记+踩坑(2)——分布式组件、前端基础,nacos+feign+gateway+ES6+vue脚手架
|
6天前
|
负载均衡 Java Nacos
SpringCloud基础2——Nacos配置、Feign、Gateway
nacos配置管理、Feign远程调用、Gateway服务网关
SpringCloud基础2——Nacos配置、Feign、Gateway
|
8天前
|
XML 监控 Java
Spring Cloud全解析:熔断之Hystrix简介
Hystrix 是由 Netflix 开源的延迟和容错库,用于提高分布式系统的弹性。它通过断路器模式、资源隔离、服务降级及限流等机制防止服务雪崩。Hystrix 基于命令模式,通过 `HystrixCommand` 封装对外部依赖的调用逻辑。断路器能在依赖服务故障时快速返回备选响应,避免长时间等待。此外,Hystrix 还提供了监控功能,能够实时监控运行指标和配置变化。依赖管理方面,可通过 `@EnableHystrix` 启用 Hystrix 支持,并配置全局或局部的降级策略。结合 Feign 可实现客户端的服务降级。
67 23
|
17天前
|
安全 Java 开发者
强大!Spring Cloud Gateway新特性及高级开发技巧
在微服务架构日益盛行的今天,网关作为微服务架构中的关键组件,承担着路由、安全、监控、限流等多重职责。Spring Cloud Gateway作为新一代的微服务网关,凭借其基于Spring Framework 5、Project Reactor和Spring Boot 2.0的强大技术栈,正逐步成为业界的主流选择。本文将深入探讨Spring Cloud Gateway的新特性及高级开发技巧,助力开发者更好地掌握这一强大的网关工具。
72 6
|
1月前
|
负载均衡 监控 Java
SpringCloud常见面试题(一):SpringCloud 5大组件,服务注册和发现,nacos与eureka区别,服务雪崩、服务熔断、服务降级,微服务监控
SpringCloud常见面试题(一):SpringCloud 5大组件,服务注册和发现,nacos与eureka区别,服务雪崩、服务熔断、服务降级,微服务监控
SpringCloud常见面试题(一):SpringCloud 5大组件,服务注册和发现,nacos与eureka区别,服务雪崩、服务熔断、服务降级,微服务监控
|
2月前
|
负载均衡 Java Spring
Spring cloud gateway 如何在路由时进行负载均衡
Spring cloud gateway 如何在路由时进行负载均衡
288 15
|
2月前
|
Java Spring
spring cloud gateway在使用 zookeeper 注册中心时,配置https 进行服务转发
spring cloud gateway在使用 zookeeper 注册中心时,配置https 进行服务转发
59 3
|
2月前
|
Java 微服务 Spring
SpringCloud gateway自定义请求的 httpClient
SpringCloud gateway自定义请求的 httpClient
112 3
|
2月前
|
JSON 前端开发 Java
SpringCloud怎么搭建GateWay网关&统一登录模块
本文来分享一下,最近我在自己的项目中实现的认证服务,目前比较简单,就是可以提供一个公共的服务,专门来处理登录请求,然后我还在API网关处实现了登录拦截的效果,因为在一个博客系统中,有一些地址是可以不登录的,比方说首页;也有一些是必须登录的,比如发布文章、评论等。所以,在网关处可以支持自定义一些不需要登录的地址,一些需要登录的地址,也可以在网关处进行校验,如果未登录,可以返回JSON格式的出参,前端可以进行相关处理,比如跳转到登录页面等。
|
2月前
|
监控 Java 应用服务中间件
SpringCloud面试之流量控制组件Sentinel详解
SpringCloud面试之流量控制组件Sentinel详解
151 0