当前位置: 代码迷 >> 综合 >> springcloud — 微服务网关之spring cloud zuul
  详细解决方案

springcloud — 微服务网关之spring cloud zuul

热度:69   发布时间:2023-12-24 20:25:06.0

API网关

API 网关(API Gateway)主要负责服务请求路由、组合及协议转换。
API网关是一个服务器,是系统的唯一入口。从面向对象设计的角度看,它与外观模式类似。API网关封装了系统内部架构,为每个客户端提供一个定制的API。它可能还具有其它职责,如身份验证、监控、负载均衡、缓存、请求分片与管理、静态响应处理。
API网关方式的核心要点是,所有的客户端和消费端都通过统一的网关接入微服务,在网关层处理所有的非业务功能。通常,网关也是提供REST/HTTP的访问API。服务端通过API-GW注册和管理服务。

Netflix zuul的特点及功能

Zuul是从设备和web站点来的所有访问Netflix 流程序的请求的前门。作为一个边缘服务程序,Zuul带来动态路由、监视、弹性和安全能力。它也有能力把请求路由到多个适当的 Amazon Auto Scaling Groups。
Zuul使用很多不同类型的过滤器,可以快速灵活地把功能应用到我们的边缘服务。这些过滤器帮助我们执行下列功能:

  • 认证和安全-为每个需要的资源做识别认证,拒绝不安全的请求
  • 洞察和监控-跟踪有意义的数据,在边缘做统计,以便准确了解产品的运行情况
  • 动态路由-把请求动态路由到不同的后端集群
  • 压力测试-逐渐增加集群的流量,来评估性能
  • 甩负荷-为每种请求分配容量,拒绝超限的请求
  • 静态响应处理-在边缘直接生成一些响应而不访问内部集群
  • 多区域弹性-跟 AWS区域做路由,让ELB的使用更多样化,让边缘接近成员

Spring Cloud Zuul

在微服务框架中,API网关对于微服务至关重要,所以在Spring Cloud 中提供了基于Netflix Zuul实现的API网关组件——Spring Cloud Zuul,兼容Spring Cloud体系。
官方文档描述如下:

  • front door. API Gateway.Zuul is a JVM based router and server side load balancer by Netflix.(所有请求的入口)
  • As an edge service application, Zuul is built to enable dynamic routing, monitoring, resiliency and security. (作为边界应用服务,zuul能实现动态路由、监控、弹性与安全性。)

Spring Cloud Zuul功能实现

Spring Cloud Zuul有如下的主要功能:
Authentication 认证,Insights 洞察力,Stress Testing 压力测试,Canary Testing 金丝雀测试,Dynamic Routing 动态路由,Service Migration 服务迁移,Load Shedding 减载,Security 安全校验,Static Response handling 静态响应处理,Active/Active traffic management 流量控制。
在微服务中,对于路由规则和服务实例的维护问题,可以通过与Spring Cloud Eureka进行整合,从Euerka中获取其它服务的实例信息,不需要人工干预;路由规则默认通过以服务名作为ContextPath的方式创建路由映射,可以轻松实现大部分路由需求(也可以手工配置老的url);对于类似的签名校验和登陆校验,通过提供一套过滤机制,可以很号的支持各种非业务性质的处理

Spring Cloud Zuul请求响应过程

在这里插入图片描述

Spring Cloud Zuul微服务集成

1.引入依赖,引入最新版本1.4.7.RELEASE
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-zuul -->
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-zuul</artifactId><version>1.4.7.RELEASE</version>
</dependency>

spring-cloud-starter-zuul依赖中,不仅包含了Netflix Zuul的核心依赖zuul-core,还包含spring-cloud-starter-hystrix依赖,在网关的转发服务中实现对微服务的转发时候的保护机制;
spring-cloud-starter-ribbon依赖,在网关服务进行路由转发的时候客户端的负载均衡以及路由重试;spring-cloud-starter-actuator依赖,提供常规的微服务管理度端点。

2.配置文件:
  • 静态路由
zuul:routes:myroute1:path: /mypath/**url: http://localhost:8080	(注意这里url要http://开头)

Path和Url要一对一进行手工配置,这种要手工维护Url转发路径,维护具体的微服务实例增加了工作量

  • 动态路由
zuul:routes:myroutes1:	#路由ID唯一path: /mypath/**serviceId: myserverId

根据serviceId进行负载均衡和动态的路由转发,这种面向服务的转发规则方式,不需要维护具体的微服务位置。

  • 转发规则

(1)忽略特定微服务转发

zuul:
ignored-services: '*'  #对微服务不进行默认路由转发,几个微服务可以用“,”隔开

(2)转发过滤前缀

zuul: 
stripPrefix=true    // 转发会过滤掉前缀prefix: /myapi            //增加前缀routes:local:path: /myapi/**     //默认时转发到服务的请求是 /**url: forward:/local

请求路径http://localhost:8888/ myapi /local/abc http://localhost:8888前端服务器
转发路径:http://localhost:9006/local/abc

(3)转发添加前缀
如果stripPrefix=false,转发的请求是
/myusers/**
zuul.prefix=/api
会对所有的path增加一个/api前缀

zuul:prefix: /myapi                  #增加前缀ignored-patterns: /**/hello/**    #忽略该路径不进行转发routes:local:path: /local/**url: forward:/local

请求路径http://localhost:8888 /local/abc http://localhost:8888前端服务器
转发路径:http://localhost:9006/myapi/local/abc

  • 超时重试配置

(1) 重试机制配置

#关闭全局重试机制
zuul:retryable: false
#关闭个别服务的重试机制
zuul:routes:feign-consumer:retryable: false

(2)超时配置

hystrix:command:  default: execution:  isolation:  thread.timeoutInMilliseconds: 10000 #熔断设定
ribbon: ConnectTimeout: 3000 #表示路由转发请求的时候,创建请求连接的超时时间ReadTimeout: 5000 #用来设置路由转发请求的超时时间,它的超时是对请求建立连接之后的处理时间
  • 两种路由配置对应不一样的超时配置

1.ribbon.ReadTimeout,ribbon.SocketTimeout这两个就是ribbon超时时间设置。
2.zuul.host.connect-timeout-millis, zuul.host.socket-timeout-millis这两个配置,这两个和上面的ribbon都是配超时的。
区别在于,如果路由方式是serviceId的方式,那么ribbon的生效,如果是url的方式,则zuul.host开头的生效
使用url的方式将没有线程隔离和断路器的保护,并且也不会具备负载均衡的能力。所以不建议使用url的方式

  • zuul中几种超时情况

1.hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds:该参数用来设置API网关中路由转发请求的执行时间,执行超过配置值之后Hystrix会将执行命令标记为TIMEOUT并抛出异常。
2.ribbon.ReadTimeout:配置值小于hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds配置值时,路由请求出现超时,会自动进行路由重试,如果依旧失败出现重试失败;
ribbon.ReadTimeout:配置值大于hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds配置值时,路由请求出现超时,返回TIMEOUT的错误信息。
3.ConnectTimeout和ribbon.ReadTimeout相似,唯一的区别就在于它的超时是对请求建立连接之后的处理时间,具有重试机制。

zuul.retryable=false和zuul.routes.< route>.retryable=false可以关闭重试机制

  • 其他配置

(1)设置Host头信息,传递敏感头部信息

zuul:add-host-header: true  //表示API网关在进行请求路由转发前为请求设置Host头信息routes:feign-consumer:sensitiveHeaders: Cookie,Set-Cookie,Authorization

默认情况下,敏感的头信息无法经过API网关进行传递,我们可以通过上面配置使之可以传递

3.启动类
新建一个springboot项目,添加注解

@SpringBootApplication
@EnableZuulProxy
@EnableEurekaServer
public class GatewayServiceZuulApplication {
    public static void main(String[] args) {
    SpringApplication.run(GatewayServiceZuulApplication.class, args);}
}

@EnableZuulProxy简单理解为@EnableZuulServer的增强版,当Zuul与Eureka、Ribbon等组件配合使用时,我们使用@EnableZuulProxy。
@EnableEurekaServer Eureka作为注册中心时,添加该注解。

spring Cloud Zuul核心实现

1、zuul核心过滤器

1.1.四种过滤器类型,Zuul中默认定义了四种不同生命周期的过滤器类型

  • pre 可以在请求被路由之前调用
  • routing 在路由请求时被调用,route型过滤器在pre过滤器后面运行,是用来发送请求给其他的服务用的,在这里它的大部分工作是转换请求和响应数据给前台客户端。
  • post 在routing和error过滤器之后被调用
  • error 处理请求时发生错误时被调用

1.2. 自定义zuul的过滤器需要继承ZuulFilter接口,实现com.netflix.zuul.ZuulFilter接口中定义的4个抽象方法:

(1)String filterType()方法
filterType:该函数需要返回一个字符串代表过滤器的类型,而这个类型就是在http请求过程中定义的各个阶段。
(2)int filterOrder()方法
通过int值来定义过滤器的执行顺序,数值越小优先级越高。
(3)boolean shouldFilter()方法
返回一个boolean值来判断该过滤器是否要执行。我们可以通过此方法来指定过滤器的有效范围。
(4)Object run()方法
过滤器的具体逻辑。在该函数中,我们可以实现自定义的过滤逻辑,来确定是否要拦截当前的请求,不对其进行后续的路由,或是在请求路由返回结果之后,对处理结果做一些加工等。

示例代码:

public class MyFilter extends ZuulFilter {
    public boolean shouldFilter() {
    return true;}public Object run() {
    System.out.println("执行 MyFilter 过滤器");return null;}@Overridepublic String filterType() {
    return FilterConstants.ROUTE_TYPE;}@Overridepublic int filterOrder() {
    return 1;}}

配置类:

@Configurationpublic class FilterConfig {
    @Beanpublic MyFilter myFilter() {
    return new MyFilter();}}

2、zuul限流实现

2.1.zuul的限流介绍

Zuul的限流实现是基于redis实现限流策略,主要的常见的限流算法有:令牌桶、漏桶。 计数器也可以进行粗暴限流实现。服务限流主要是保护服务节点或者数据节点,防止瞬时流量过大造成服务和数据崩溃,导致服务不可用。

2.2.限流策略

(1)令牌桶策略

大小固定的令牌桶可自行以恒定的速率源源不断地产生令牌。如果令牌不被消耗,或者被消耗的速度小于产生的速度,令牌就会不断地增多,直到把桶填满。后面再产生的令牌就会从桶中溢出。最后桶中可以保存的最大令牌数永远不会超过桶的大小。
在这里插入图片描述

  1. 所有的流量在放行之前需要获取一定量的 token;
  2. 所有的 token 存放在一个 bucket(桶)当中,每 1/r 秒,都会往这个 bucket 当中加入一个 token;
  3. bucket 有最大容量(capacity or limit),在 bucket 中的 token 数量等于最大容量,而且没有 token 消耗时,新的额外的 token 会被抛弃。
    这种实现方法有几个优势:
  4. 避免了给每一个 Bucket 设置一个定时器这种笨办法,
  5. 数据结构需要的内存量很小,只需要储存 Bucket 中剩余的 Token 量以及上次补充 Token 的时间戳就可以了;
  6. 只有在用户访问的时候,才会计算 Token 补充量,对于系统的计算资源占用量也较小。
(2)漏桶策略

漏桶算法强制一个常量的输出速率而不管输入数据流的突发性:
在这里插入图片描述
流程:
到达的数据包(网络层的PDU)被放置在底部具有漏孔的桶中(数据包缓存);
漏桶最多可以排队b个字节,漏桶的这个尺寸受限于有效的系统内存。如果数据包到达的时候漏桶已经满了,那么数据包应被丢弃;
数据包从漏桶中漏出,以常量速率(r字节/秒)注入网络,因此平滑了突发流量。

  相关解决方案