首页 > 其他分享 >Gateway服务网关的介绍与使用

Gateway服务网关的介绍与使用

时间:2022-12-14 18:33:32浏览次数:60  
标签:网关 服务 请求 介绍 gateway 过滤器 Gateway 路由


什么是服务网关

传统的单体架构中只需要开放一个服务给客户端调用,但是微服务架构中是将一个系统拆分成多个微服务,如果没有网关,客户端只能在本地记录每个微服务的调用地址,当需要调用的微服务数量很多时,它需要了解每个服务的接口,这个工作量很大。那有了网关之后,能够起到怎样的改善呢?

网关作为系统的唯一流量入口,封装内部系统的架构,所有请求都先经过网关,由网关将请求路由到合适的微服务,所以,使用网关的好处在于:

  • 简化客户端的工作。 网关将微服务封装起来后,客户端只需同网关交互,而不必调用各个不同服务;
  • 降低函数间的耦合度。 一旦服务接口修改,只需修改网关的路由策略,不必修改每个调用该函数的客户端,从而减少了程序间的耦合性
  • 解放开发人员把精力专注于业务逻辑的实现。
    由网关统一实现服务路由(灰度与ABTest)、负载均衡、访问控制、流控熔断降级等非业务相关功能,而不需要每个服务 API 实现时都去考虑
    但是 API 网关也存在不足之处,在微服务这种去中心化的架构中,网关又成了一个中心点或瓶颈点,它增加了一个我们必须开发、部署和维护的高可用组件。正是由于这个原因,在网关设计时必须考虑即使 API 网关宕机也不要影响到服务的调用和运行,所以需要对网关的响应结果有数据缓存能力,通过返回缓存数据或默认数据屏蔽后端服务的失败。

服务网关的基本功能:

Gateway服务网关的介绍与使用_gateway

流量网关与服务网关的区别

Gateway服务网关的介绍与使用_微服务_02


流量网关和服务网关在系统整体架构中所处的位置如上图所示,流量网关(如Nignx)是指提供全局性的、与后端业务应用无关的策略,例如 HTTPS证书卸载、Web防火墙、全局流量监控等。

而微服务网关(如Spring Cloud Gateway)是指与业务紧耦合的、提供单个业务域级别的策略,如服务治理、身份认证等。也就是说,流量网关负责南北向流量调度及安全防护,微服务网关负责东西向流量调度及服务治理。

服务网关的介绍

Gateway服务网关的介绍与使用_gateway_03

  • **Kong 网关:**Kong 的性能非常好,非常适合做流量网关,但是对于复杂系统不建议业务网关用 Kong,主要是工程性方面的考虑
  • Zuul1.x 网关:Zuul 1.0
    的落地经验丰富,但是性能差、基于同步阻塞IO,适合中小架构,不适合并发流量高的场景,因为容易产生线程耗尽,导致请求被拒绝的情况
  • gateway 网关:功能强大丰富,性能好,官方基准测试 RPS (每秒请求数)是Zuul的1.6倍,能与 SpringCloud
    生态很好兼容,单从流式编程+支持异步上也足以让开发者选择它了。
  • Zuul 2.x:性能与 gateway 差不多,基于非阻塞的,支持长连接,但 SpringCloud 没有集成 zuul2 的计划,并且
    Netflix 相关组件都宣布进入维护期,前景未知。
    综上,gateway 网关更加适合 SpringCloud 项目,而从发展趋势上看,gateway 替代 zuul 也是必然的。

Spring Cloud Gateway 网关的

  • pom.xml 的 引入
<properties>
<spring-boot.version>2.3.2.RELEASE</spring-boot.version>
<spring-cloud.version>Hoxton.SR9</spring-cloud.version>
<spring-cloud-alibaba.version>2.2.6.RELEASE</spring-cloud-alibaba.version>
</properties>

<!-- 只声明依赖,不引入依赖 -->
<dependencyManagement>
<dependencies>
<!-- 声明springBoot版本 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- 声明springCloud版本 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- 声明 springCloud 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>
<!-- 引入gateway网关 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</dependencyManagement>
  • 配置项目名与端口:
server:
port: 8100
spring:
application:
name: gateway-service
cloud:
nacos:
server-addr: 33.183.134.49:8848
gateway:
routes:
- id: mqtt-service-route
uri: lb://mqtt-service
predicates:
- Path=/mqtt/**
- id: usermgr-service-route
uri: lb://usermgr-service
predicates:
- Path=/usermgr/**
  • Spring Cloud Gateway 配置项的说明:
  • 断言(Predicate):参照 Java8 的新特性Predicate,允许开发人员匹配 HTTP请求中的任何内容,比如请求头或请求参数,最后根据匹配结果返回一个布尔值。
  • 路由(route):由ID、目标URI、断言集合和过滤器集合组成。如果聚合断言结果为真,则转发到该路由。
  • 过滤器(filter):可以在返回请求之前或之后修改请求和响应的内容。
  • 路由 Route:
    Route 主要由 路由id、目标uri、断言集合和过滤器集合组成,那我们简单看看这些属性到底有什么作用。
  • id:路由标识,要求唯一,名称任意(默认值 uuid,一般不用,需要自定义)
  • uri:请求最终被转发到的目标地址
  • order:路由优先级,数字越小,优先级越高
  • predicates:断言数组,即判断条件,如果返回值是boolean,则转发请求到 uri 属性指定的服务中
  • filters:过滤器数组,在请求传递过程中,对请求做一些修改
  • 断言 Predicate
    Predicate 来自于 Java8 的接口。Predicate 接受一个输入参数,返回一个布尔值结果。该接口包含多种默认方法来将 Predicate 组合成其他复杂的逻辑(比如:与,或,非)。
    Predicate 可以用于接口请求参数校验、判断新老数据是否有变化需要进行更新操作。Spring Cloud Gateway 内置了许多 Predict,这些 Predict 的源码在 org.springframework.cloud.gateway.handler.predicate 包中。
    实例如下:
spring:
cloud:
gateway:
# 路由数组:指当请求满足什么样的断言时,转发到哪个服务上
routes:
# 路由标识,要求唯一,名称任意
- id: gateway-provider_1
# 请求最终被转发到的目标地址
uri: http://mqtt-service
# 设置断言
predicates:
# Path Route Predicate Factory 断言,满足 /gateway/provider/** 路径的请求都会被路由到 http://localhost:9024 这个uri中
- Path=/mqtt/**
# Weight Route Predicate Factory 断言,同一分组按照权重进行分配流量,这里分配了80%
# 第一个group1是分组名,第二个参数是权重
- Weight=group1, 8
# 配置过滤器(局部)
filters:
# StripPrefix:去除原始请求路径中的前1级路径,即/gateway
- StripPrefix=1
  • 过滤器 filter:
    Gateway 过滤器的生命周期:
  • PRE:这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试信息等。
  • POST:这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的 HTTP
    Header、收集统计信息和指标、将响应从微服务发送给客户端等。
    Gateway 过滤器从作用范围可分为两种:
  • GatewayFilter:应用到单个路由或者一个分组的路由上(需要在配置文件中配置)
  • GlobalFilter:应用到所有的路由上(无需配置,全局生效)

  • 自定义局部过滤器
    虽说内置的过滤器能够解决很多场景,但是难免还是有些特殊需求需要定制一个过滤器,下面就来介绍一下如何自定义局部过滤器。
/**
* 名称必须是xxxGatewayFilterFactory形式
* todo:模拟授权的验证,具体逻辑根据业务完善
*/
@Component
@Slf4j
public class AuthorizeGatewayFilterFactory extends AbstractGatewayFilterFactory<AuthorizeGatewayFilterFactory.Config> {

private static final String AUTHORIZE_TOKEN = "token";

//构造函数,加载Config
public AuthorizeGatewayFilterFactory() {
//固定写法
super(AuthorizeGatewayFilterFactory.Config.class);
log.info("Loaded GatewayFilterFactory [Authorize]");
}

//读取配置文件中的参数 赋值到 配置类中
@Override
public List<String> shortcutFieldOrder() {
//Config.enabled
return Arrays.asList("enabled");
}

@Override
public GatewayFilter apply(AuthorizeGatewayFilterFactory.Config config) {
return (exchange, chain) -> {
//判断是否开启授权验证
if (!config.isEnabled()) {
return chain.filter(exchange);
}

ServerHttpRequest request = exchange.getRequest();
HttpHeaders headers = request.getHeaders();
//从请求头中获取token
String token = headers.getFirst(AUTHORIZE_TOKEN);
if (token == null) {
//从请求头参数中获取token
token = request.getQueryParams().getFirst(AUTHORIZE_TOKEN);
}

ServerHttpResponse response = exchange.getResponse();
//如果token为空,直接返回401,未授权
if (StringUtils.isEmpty(token)) {
response.setStatusCode(HttpStatus.UNAUTHORIZED);
//处理完成,直接拦截,不再进行下去
return response.setComplete();
}
/**
* todo chain.filter(exchange) 之前的都是过滤器的前置处理
*
* chain.filter().then(
* 过滤器的后置处理...........
* )
*/
//授权正常,继续下一个过滤器链的调用
return chain.filter(exchange);
};
}

@Data
@AllArgsConstructor
@NoArgsConstructor
public static class Config {
// 控制是否开启认证
private boolean enabled;
}
}

局部过滤器需要在路由中配置才能生效,配置如下:

spring:
cloud:
gateway:
routes:
- id: gateway-provider_1
uri: http://localhost:9024
predicates:
- Path=/gateway/provider/**
## 配置过滤器(局部)
filters:
- AddResponseHeader=X-Response-Foo, Bar
## AuthorizeGatewayFilterFactory自定义过滤器配置,值为true需要验证授权,false不需要
- Authorize=true
  • GlobalFilter 全局过滤器:

全局过滤器应用全部路由上,无需开发者配置

@Slf4j
@Component
@Order(value = Integer.MIN_VALUE)
public class AccessLogGlobalFilter implements GlobalFilter {

@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//filter的前置处理
ServerHttpRequest request = exchange.getRequest();
String path = request.getPath().pathWithinApplication().value();
InetSocketAddress remoteAddress = request.getRemoteAddress();
return chain
//继续调用filter
.filter(exchange)
//filter的后置处理
.then(Mono.fromRunnable(() -> {
ServerHttpResponse response = exchange.getResponse();
HttpStatus statusCode = response.getStatusCode();
log.info("请求路径:{},远程IP地址:{},响应码:{}", path, remoteAddress, statusCode);
}));
}
}

全局过滤器不必在路由上配置,注入到IOC容器中即可全局生效。
网关自定义全局异常处理器:

/**
* 用于网关的全局异常处理
* @Order(-1):优先级一定要比ResponseStatusExceptionHandler低
*/
@Slf4j
@Order(-1)
@Component
@RequiredArgsConstructor
public class GlobalErrorExceptionHandler implements ErrorWebExceptionHandler {

private final ObjectMapper objectMapper;

@SuppressWarnings({"rawtypes", "unchecked", "NullableProblems"})
@Override
public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {
ServerHttpResponse response = exchange.getResponse();
if (response.isCommitted()) {
return Mono.error(ex);
}

// JOSN格式返回
response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
if (ex instanceof ResponseStatusException) {
response.setStatusCode(((ResponseStatusException) ex).getStatus());
}

return response.writeWith(Mono.fromSupplier(() -> {
DataBufferFactory bufferFactory = response.bufferFactory();
try {
//todo 返回响应结果,根据业务需求,自己定制
CommonResponse resultMsg = new CommonResponse("500",ex.getMessage(),null);
return bufferFactory.wrap(objectMapper.writeValueAsBytes(resultMsg));
}
catch (JsonProcessingException e) {
log.error("Error writing response", ex);
return bufferFactory.wrap(new byte[0]);
}
}));
}
}


标签:网关,服务,请求,介绍,gateway,过滤器,Gateway,路由
From: https://blog.51cto.com/u_15461374/5938173

相关文章

  • Gateway 代理日志记录 Filter
    前言我们在使用网关的时候,有时候客户端会有莫名其妙的问题需要服务端辅助定位,这时候有一份完全的请求的信息的日志会非常有帮助,这里提供一种基于过滤器的实现方式。我的实......
  • 通过服务网格减少对API网关依赖
    微服务和微服务之间有调用关系,所有调用关系都经过API网关,最终的调用链如图1所示。基于API网关的数据转发如图1所示,展示了4个微服务之间的3次调用,可以看出任何服务到服务之......
  • asp.net core 微服务网关示例 ocelot gateway Demo
    ocelotasp.netcore微服务gateway介绍https://ocelot.readthedocs.io/en/latest/introduction/gettingstarted.html 1.新建asp.netcorewebapi空项目AProject,nug......
  • Spring Cloud Config介绍
    市场上的开源的配置中心有很多,如奇虎360的QConf、淘宝的Diamond、百度的Disconf、携程的Apollo都可解决上述提到的问题,同样地SpringCloud提供的配置中心则是SpringCloud......
  • EhCache的介绍
    ehcache是一个非常轻量级的缓存实现,而且从1.2之后就支持了集群,而且是hibernate默认的缓存provider。EhCache是一个纯Java的进程内缓存框架,具有快速、精干等特点,是Hibernat......
  • Ribbon介绍和使用
    Ribbon是Netflix公司提供的一个在SpringCloud中免费使用的客户端负载均衡器组件。它在集群中为各个客户端之间的通信提供支持,可以控制、管理HTTP和TCP客户端的负载均衡。......
  • BL110网关远程监测充电桩断网故障解决方案
    在碳中和等因素的影响下,燃油车逐步退出市场,新能源汽车逐步替代燃油车市场,获得了爆发性增长的市场空间。近年来,中国新能源汽车市场保持高速增长,新能源汽车当前的保有量、增......
  • Ocelot API网关的实现剖析
    在微软TechSummit2017大会上和大家分享了一门课程《.NETCore在腾讯财付通的企业级应用开发实践》,其中重点是基于ASP.NETCore打造可扩展的高性能企业级API网关,以开源的......
  • 2.0FreeRTOS文件介绍
    1、打开FreeRTOSv9.0.0,有两个文件夹FreeRTOS、FreeRTOS-Plus。FreeRTOS-Plus是一些第三方产品,一般用不到  2、打开FreeRTOS有Demo、License、Source Demo:官方为......
  • spring-cloud-alibaba-整合spring-clouid-gateway-3.1.4
    spring-cloud-alibaba-整合spring-clouid-gateway-3.1.4spring-cloud-alibaba-整合spring-clouid-gateway-3.1.4前言版本说明引入spring-cloud-gatewayspring-cloud......