关于spring:SpringCloud-第十三篇-Zuul高层架构二

6次阅读

共计 5481 个字符,预计需要花费 14 分钟才能阅读完成。

1:架构图

2:ZuulServlet

Zuul 的外围是一系列的 filters,Zuul 大部分性能都是通过过滤器来实现的

1:ZuulServlet 是 Zuul 的外围类,用来调度不同阶段的 filters,解决申请,并解决异样等,门路是 /zuul,能够应用 zuul.servlet-path 属性更改此门路
2:性能相似于 SpringMvc 的 DispatcherServlet,所有的 Request 都要通过它的解决
3:外面有三个外围办法:preRoute(),route(), postRoute()
4:ZuulServlet 会把具体的执行交给 ZuulRunner 去做,ZuulServlet 是单例,因而 ZuulRunner 也仅有一个实例
5:Zuul 的过滤器之间没有间接的互相通信,它们之间通过一个 RequestContext 的动态类来进行数据传递的。RequestContext 类中有 ThreadLocal 变量来记录每个 Request 所须要传递的数据,ZuulRunner 会初始化 RequestContext
6:ZuulRunner 间接将执行逻辑交由 FilterProcessor 解决,FilterProcessor 也是单例,其性能就是根据 filterType 执行 filter 的解决逻辑,大抵过程如下:
(1)依据 Type 获取所有输出该 Type 的 filter
(2)遍历执行每个 filter 的解决逻辑,processZuulFilter(ZuulFilter filter)
(3)RequestContext 对每个 filter 的执行情况进行记录,如果执行失败则对异样封装后抛出

3:生命周期

4:过滤器类型与申请生命周期

  • PRE:这种过滤器在申请被路由之前调用。可利用这种过滤器实现身份验证、在集群中抉择申请的微服务、记录调试信息等。
  • ROUTING:这种过滤器将申请路由到微服务。这种过滤器用于构建发送给微服务的申请,并应用 Apache HttpClient 或 Netfilx Ribbon 申请微服务。
  • POST:这种过滤器在路由到微服务当前执行。这种过滤器可用来为响应增加规范的 HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端等。
  • ERROR:在其余阶段产生谬误时执行该过滤器。

一般来说,如果须要在申请达到后端利用前就进行解决的话,会抉择前置过滤器,例如鉴权、申请转发、减少申请参数等行为。在申请实现后须要解决的操作放在后置过滤器中实现,例如统计返回值和调用工夫、记录日志、减少跨域头等行为。
路由过滤器个别只须要抉择 Zuul 中内置的即可,谬误过滤器个别只须要一个,这样能够在 Gateway 遇到谬误逻辑时间接抛出异常中断流程,并间接对立解决返回后果

5:外围过滤器

5.1:概述

在 spring cloud zuul 中,为了让 api 网关组件能够被更不便的应用,它在 http 申请生命周期的各个阶段默认实现了一批外围过滤器,它们会在 api 网关服务启动的时候被主动加载和启动。
默认 spring-cloud-netflix-core 模块 org.springframework.cloud.netflix.zuul.filters 包下

5.2:pre 过滤器

  • ServletDetectionFilter

用来检测以后申请是通过 Spring 的 DispatcherServlet 解决运行的,还是通过 ZuulServlet 来解决运行的。它的检测后果会以布尔类型保留在以后申请上下文的 isDispatcherServletRequest 参数中,这样后续的过滤器中,能够通过 RequestUtils.isDispatcherServletRequest() 和 RequestUtils.isZuulServletRequest() 办法来判断申请解决的源头,以实现后续不同的解决机制。
个别状况下,发送到 API 网关的内部申请都会被 Spring 的 DispatcherServlet 解决,除了通过 /zuul/* 门路拜访的申请会绕过 DispatcherServlet,被 ZuulServlet 解决。

  • FormBodyWrapperFilter:

解析表单数据,并对上游申请进行从新编码。
该过滤器仅对两类申请失效,第一类是 Context-Type 为 application/x-www-form-urlencoded 的申请,第二类是 Context-Type 为 multipart/form-data 并且是由 String 的 DispatcherServlet 解决的申请,而该过滤器的次要目标是将符合要求的申请体包装成 FormBodyRequestWrapper 对象

  • DebugFilter:

该过滤器会依据配置参数 zuul.debug.request 和申请中的 debug 参数来决定是否执行过滤器中的操作。
它的具体操作内容是将以后申请上下文中的 debugRouting 和 debugRequest 参数设置为 true。因为在同一个申请的不同生命周期都能够拜访到这二个值,所以咱们在后续的各个过滤器中能够利用这二个值来定义一些 debug 信息,这样当线上环境呈现问题的时候,能够通过参数的形式来激活这些 debug 信息以帮忙剖析问题,另外,对于申请参数中的 debug 参数,咱们能够通过 zuul.debug.parameter 来进行自定义。

  • PreDecorationFilter:

此过滤器依据提供的 RouteLocator 确定在哪里和如何路由。
该过滤器会判断以后申请上下文中是否存在 forward.do 和 serviceId 参数,如果都不存在,那么它就会执行具体过滤器的操作(如果有一个存在的话,阐明以后申请曾经被解决过了,因为这二个信息就是依据以后申请的路由信息加载进来的)。
另外,还能够在该实现中找到对 HTTP 头申请进行解决的逻辑,其中蕴含了一些耳熟能详的头域,比方 X -Forwarded-Host,X-Forwarded-Port。对于这些头域是通过 zuul.addProxyHeaders 参数进行管制的,而这个参数默认值是 true,所以 zuul 在申请跳转时默认会为申请减少 X -Forwarded-* 头域,包含 X -Forwarded-Host,X-Forwarded-Port,X-Forwarded-For,X-Forwarded-Prefix,X-Forwarded-Proto。也能够通过设置 zuul.addProxyHeaders=false 敞开对这些头域的增加动作

5.3:route 过滤器

  • RibbonRoutingFilter:

该过滤器只对申请上下文中存在 serviceId 参数的申请进行解决,即只对通过 serviceId 配置路由规定的申请失效。
该过滤器的执行逻辑就是面向服务路由的外围,它通过应用 ribbon 和 hystrix 来向服务实例发动申请,并将服务实例的申请后果返回

  • SimpleHostRoutingFilter:

该过滤器只对申请上下文存在 routeHost 参数的申请进行解决,即只对通过 url 配置路由规定的申请失效。
该过滤器的执行逻辑就是间接向 routeHost 参数的物理地址发动申请,从源码中咱们能够晓得该申请是间接通过 httpclient 包实现的,而没有应用 Hystrix 命令进行包装,所以这类申请并没有线程隔离和断路器的爱护。

  • SendForwardFilter:

该过滤器只对申请上下文中存在的 forward.do 参数进行解决申请,即用来解决路由规定中的 forward 本地跳转拆卸

5.4:post 过滤器

  • SendErrorFilter:

该过滤器仅在申请上下文中蕴含 error.status_code 参数(由之前执行的过滤器设置的谬误编码)并且还没有被该过滤器解决过的时候执行。
该过滤器的具体逻辑就是利用上下文中的错误信息来组成一个 forward 到 api 网关 /error 谬误端点的申请来产生谬误响应。
能够通过设置 error.path 属性来更改默认转发门路(/error)。

  • SendResponseFilter:

该过滤器会查看申请上下文中是否蕴含申请响应相干的头信息,响应数据流或是响应体,只有在蕴含它们其中一个的时候执行解决逻辑。
其解决逻辑就是利用上下文的响应信息来组织须要发送回客户端的响应内容

5.5:禁用过滤器

  • 重写 shouldFilter 逻辑,让它返回 false
  • 通过配置来禁用:

zuul.<SimpleClassName>.<filterType>.disable=true
<SimpleClassName> 代表过滤器的类名,<filterType> 代表过滤器类型

6: 重试机制

  • Zuul 的重试机制是依赖于 Spring-Retry 的,因而 pom.xml 必须有 spring-retry,
<dependency>  
    <groupId>org.springframework.retry</groupId>  
    <artifactId>spring-retry</artifactId>  
</dependency> 
  • 开启重试,也能够具体的为某个服务开启重试

zuul.routes.user-api.retryable=true
其中的 user-api 是路由名称,可自行自定义

  • 而后是相应的 hystrix 和 Ribbon 的配置
hystrix.command.default.execution.timeout.enabled=true  
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=2000  
ribbon.ConnectTimeout=250  
ribbon.ReadTimeout=1000  
ribbon.OkToRetryOnAllOperations=true  
ribbon.MaxAutoRetries=0  
ribbon.MaxAutoRetriesNextServer=1  
  • 敞开重试机制

全局敞开:
zuul.retryable=false
指定路由敞开
zuul.routes.<route>.retryable=false

7: 饿汉式加载

  • Zuul 外部应用 Ribbon 调用近程 URL,并且 Ribbon 客户端默认在第一次调用时由 Spring Cloud 加载。能够应用以下配置更改 Zuul 的此行为:

zuul.ribbon.eager-load.enabled=true

  • 在 Spring Cloud Zuul 的饥饿加载中没有设计专门的参数来配置,而是间接采纳了读取路由配置来进行饥饿加载的做法。所以,如果咱们应用默认路由,而没有通过配置的形式指定具体路由规定,那么 zuul.ribbon.eager-load.enabled=true 的配置就没有什么作用了。
  • 因而,在真正应用的时候,能够通过 zuul.ignored-services=* 来疏忽所有的默认路由,让所有路由配置均保护在配置文件中,以达到网关启动的时候就默认初始化好各个路由转发的负载平衡对象

8:上传文件

8.1:对于小文件

Zuul 不必做任何特地配置,间接依照门路进行路由就能够了

8.2:对于大文件

一个简略的计划就是应用在你的门路前增加上 /zuul/,来绕开 Spring 的 DispatcherServlet,以防止多局部解决,同时也躲避了后盾提取中文名乱码的问题。

  • 要设置真正解决文件上传的利用,设置容许大文件上传,默认最大是 10M,如:
spring.http.multipart.enabled=true
spring.http.multipart.max-file-size=1000Mb
spring.http.multipart.max-request-size=1500Mb
  • 要设置 zuul 利用,次要是超时的问题,如:
zuul.host.socket-timeout-millis=10000 
zuul.host.connect-timeout-millis=10000

hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=15000

ribbon.ConnectTimeout=500
ribbon.ReadTimeout=15000

9:健康检查

  • 退出依赖
<dependency>  
    <groupId>org.springframework.boot</groupId>  
    <artifactId>spring-boot-starter-actuator</artifactId>  
</dependency>  
  • 配置示例
# 开启健康检查 (须要 spring-boot-starter-actuator 依赖)  
eureka.client.healthcheck.enabled=true  
#租期到期工夫,默认 90 秒  
eureka.instance.lease-expiration-duration-in-seconds=30  
#租赁更新工夫距离,默认 30,即 30 秒发送一次心跳  
eureka.instance.lease-renewal-interval-in-seconds=10 
#hystrix dashboard 的信息收集频率,默认 500 毫秒,设置 dashboard 的刷新频率
hystrix.stream.dashboard.intervalInMilliseconds=5000 
正文完
 0