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=truespring.http.multipart.max-file-size=1000Mbspring.http.multipart.max-request-size=1500Mb
- 要设置zuul利用,次要是超时的问题,如:
zuul.host.socket-timeout-millis=10000 zuul.host.connect-timeout-millis=10000hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=15000ribbon.ConnectTimeout=500ribbon.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