ZUUL参数调优

依赖:

spring cloud Eureka Client 启动器

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zuul</artifactId>
</dependency>

zuul网关的重试机制,不是使用ribbon内置的重试机制
是借助spring-retry组件实现的重试
开启zuul网关重试机制需要增加下述依赖

<dependency>
    <groupId>org.springframework.retry</groupId>
    <artifactId>spring-retry</artifactId>
</dependency>

参数:

一.-----------------zuul的路由相关配置--------------:

服务名称匹配,url路径匹配,路由排除配置,路由前缀配置

zuul:

sensitive-headers: Cookie         #全局设置,如果你不想把一些敏感headers泄露到下游服务器,sensitiveHeaders就相当于是一个向下游传递的请求头黑名单。
                                    #默认包含了 Cookie,Set-Cookie和Authorization三个请求头。
                                    #因此,如果你需要向下传递所有的请求头信息,需要明确地把sensitiveHeaders设置成一个空列表,
  ignored-headers:                  #全局设置,可以把那些不需要传递到下游的请求头或响应头配置到 zuul.ignoredHeaders 中,可以达到和sensitive-headers相同的作用。
  prefix: /zuul                     #配置请求路径前缀,例如/zuul/api/**的请求会被路由到daas-apicore服务
  strip-prefix: false               #全局配置:默认情况下,Zuul代理会在将请求转发出去之前先将其中的前缀字符串剔除掉。
                                    #如果你不想剔除前缀,可以设置 zuul.stripPrefix=false。
                                    #zuul.stripPrefix只使用于使用了zuul.prefix配置情况下。在一个定义好了的 route’s path中不会有任何影响。
  ignored-services: /*              #排除指定服务,/*表示给所有新发现的服务默认排除zuul网关访问方式,只有配置了路由网关的服务才可以通过zuul网关访问
  ignored-patterns: /*/test/*       #排除指定路径 使用符号通配,不对符合的路径进行路由代理
  routes:
    core-api:                       #自定义,通常使用要调用的服务名称,方便后期管理
      path: /api/**                 #被路由的path
      serviceId: daas-apicore       #serviceId用于配置符合path的请求路径路由到的服务名称
      stripPrefix: false            #局部设置
      sensitive-headers: Cookie     #局部设置
    test-app:
      path: /test/**
      url: http://127.0.0.1:8080/   #url用于配置符合path的请求路径路由到的服务地址

通过url配置的路由不会被当作HystrixCommand执行,自然也就不会使用Ribbon在多个Url之间进行负载均衡。所以,推荐使用serviceId进行配置。或者,指定一个包含有多个可用服务列表的serviceId,

路由配置的简写(下面表示将/api/*转发到core-api):

zuul:
    routes:
      core-api: /api/**

还可以不用写映射规则(下面表示将/core-api/**转发到core-api):

zuul:
    routes:
      core-api: 

甚至可以啥都不写,zuul会默认给从eureka发现到的所有服务进行代理,默认的path是“/【微服务名称】/** ”,如果我们在ignored-services配置了/*,zuul就不会对这些所有发现的微服务进行代理,而只会代理配置了routes的微服务。

二.-------------------zuul过滤器的相关配置---------------:

zuul:
  SendResponseFilter:             #希望被禁用的过滤器名称
    post:                         #过滤器类型
      disable: true               #设置为ture表示禁用该过滤器

三.--------------------zuul网关的限流配置-----------------:

Zuul的限流保护需要额外依赖spring-cloud-zuul-ratelimit组件。

<dependency>
    <groupId>com.marcosbarbero.cloud</groupId>
    <artifactId>spring-cloud-zuul-ratelimit</artifactId>
    <version>1.3.4.RELEASE</version>
</dependency>
zuul:
  ratelimit:
    enabled: true                   # 开启限流保护
    default-policy:                 #default-policy表示开启的是全局限流,#policies表示开启的是局部限流
      limit: 3    
      refresh-interval: 60          #60秒内请求超过3次,服务端就抛出异常
      type: url                     #type可以指定是针对IP(origin)还是url(url)限流
    policies:                   
      test-app:                     #想要限流的服务名称
        limit: 3
        refresh-interval: 50
        type: origin
    repository: redis               #限流保护的存储位置,默认是in_memory,存在内存的ConcurrentHashMap中,只适合单机限流
                                    #可选的值还有 consul-consul存储,redis-redis缓存存储,jpa-数据库存储

四.--------------------zuul并发请求数优化--------------------:

zuul网关的参数调优,有以下几个方面:容器(Tomcat)、zuul、hystrix、ribbon、feign等

1.zuul能接收多少请求受到http连接池的限制:

​SpringBoot默认使用8.5版本的Tomcat作为内嵌的Web容器。因此Zuul或Service接收到的请求时,都是由Tomcat中Connector的线程池数量决定,也就是worker线程数。

#默认10000 
server.tomcat.max-connections=10000    #最大接收请求数
#默认200
server.tomcat.max-threads=1000    #最大线程数

zuul有个http连接池用来处理请求,池中没有可用的连接就会阻塞直到池中有连接,zuul启动时会初始化连接池,以前用的是zuul.max.host.connections,现在已经由下面取代:

zuul.host.max-per-route-connections = 1000(适用于ApacheHttpClient,如果是okhttp无效。单个微服务的单实例允许的最大请求数,默认值是20)

zuul.host.max-total-connections = 10000(适用于ApacheHttpClient,如果是okhttp无效。单个微服务的多实例(因为有负载均衡)允许的最大请求数,也就是http客户端连接池最大连接,默认是200)

虽然启动时初始化了,但是在请求时又再次初始化了,用的是这俩参数:

ribbon.MaxConnectionsPerHost = 50

ribbon.MaxTotalConnections = 100

按照以上设置,某个微服务单实例通过代理最多只能跑到50,多实例最多100。

2.zuul能同时处理多少请求受到线程池或者是信号量的限制(二选一)

隔离策略都是控制线程数量的,只不过是控制的方式不同。 hystrix默认的隔离策略是thread,但是在zuul中,默认的hystrix隔离策略是semaphore。

可以通过下面这个参数来改变zuul中hystrix的隔离策略,改为thread

zuul:
 ribbon-Isolation-Strategy: THREAD

 thread-pool.use-separate-thread-pools:true    #意思是每个路由都有自己的线程池,而不是共享一个

 thread-pool.thread-pool-key-prefix:"/pp"      #指定一个线程池前缀方便调试

同时还要改变hytrix中的参数

hystrix.command.default.execution.isolation.strategy= THREAD

这两个要同时设置

如果隔离策略为默认的semaphore:

zuul中可以设置信号量,hystrix也可以设置信号量

[优先级1]zuul.eureka.[service-id].semaphore.maxSemaphores
[优先级2]zuul.routes.[service-id].semaphore
[优先级3]zuul.semaphore.max-semaphores
[优先级4]hystrix.command.[HystrixCommandKey].execution.isolation.semaphore.maxConcurrentRequests
[优先级5]hystrix.command.default.execution.isolation.semaphore.maxConcurrentRequests                                  #同一时间的请求不超过这个数字,没有时间窗口

如果隔离策略为thread线程池:

hystrix的隔离策略为thread时,可为Hystrix配置独立线程池,如果不设置独立线程池,那么HystrixThreadPoolKey 是 RibbonCommand,THREAD隔离策略下,需优化coreSize、maximumSize、maxQueueSize:

hystrix.threadpool.default.coreSize: 10
hystrix.threadpool.default.maximumSize: 10
hystrix.threadpool.default.maxQueueSize: -1      # 如该值为-1,那么使用的是SynchronousQueue,否则使用的是LinkedBlockingQueue。注意,修改MQ的类型需要重启。例如从-1修改为100,需要重启,因为使用的Queue类型发生了变化
allowMaximumSizeToDivergeFromCoreSize:    #是否让maximumSize生效

五.-----------------zuul网关超时的配置-----------------:

zuul网关有三种超时可以配置:

#zuul

zuul.host.connect-timeout-millis                               #此参数为 zuul 网关连接服务的时间

zuul.host.socket-timeout-millis                                 #zuul 网关连接到服务并且服务返回结果这一部分时间

#ribbon

zuul.ribbon.OkToRetryOnAllOperations   = true         #全部开启请求重试机制(对所有的操作请求都进行重试,如果是get则可以,如果是post,put等操作没有实现幂等的情况下是很危险的,所以设置为false)

zuul.ribbon.SocketTimeout    = 3000                         #请求建立连接时间

zuul.ribbon.ReadTimeout    = 2000                            #请求处理超时时间

zuul.ribbon.MaxTotalHttpConnections   = 1000        #最大http连接数

zuul.ribbon.MaxConnectionsPerHost  = 300              #每个host最大连接数

zuul.ribbon.MaxAutoRetries =  2                                #最大同一台实例重试次数,不包括首次调用(实际项目中由于网络或者资源不够,偶尔会出现后端服务不能访问,一次访问失败不能代表后端服务就挂了。因此开启重试机制,调整重试次数。在一定时间内,重试几次都失败,我们才认为后端服务挂了。)

zuul.ribbon.MaxAutoRetriesNextServer =  3              #切换负载均衡的其他实例的重试次数,不包括首次调用

#hystrix

hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds = 1800000    #全局的hystrix超时时间,用来设置thread和semaphore两种隔离策略的超时时间,默认值是1000。在Hystrix 1.4.0之前,semaphore-isolated隔离策略是不能超时的,从1.4.0开始semaphore-isolated也支持超时时间了。execution.timeout.enabled:是否开启超时,默认是true,开启。

1.当路由方式是url的超时配置

如果路由方式是url的方式,则zuul.host开头的生效。zuul请求下一个服务共三步:发送请求,下一个服务处理请求,下一个服务返回请求。第一步对应的超时时间是zuul.host.connect-timeout-millis设定的,第一二三步总的对应的超时时间是zuul.host.socket-timeout-millis设置的。假设第一个参数设置为20s,第二个参数设置为60s,url的路由配置方式,按理来说60s后就应该超时了,如果出现超过60s还未超时的情况,会是什么原因呢?zuul底层使用NIO架构拦截请求,并处理请求,zuul准备了一个线程池来处理拦截到的请求,线程池的连接数由下面两个参数决定:

maxTotalConnections:HttpClient 总连接数,默认值为200

maxPerRouteConnections:HttpClient 单个服务(即服务发现中的每个服务)连接数,默认为20

假设有100个请求过来都被zuul拦截了,线程池大小为20,那么就有80个请求等待,这80个请求并未开始被zuul处理,所以zuul配置的上面两个超时时间不生效。zuul这里会堆积很多请求,如果希望这80个请求120s后拿不到线程就返回了,就需要配置zuul.host.connectionRequestTimeoutMillis设置为120s,当请求来到zuul网关首先等待120s没有被处理,就超时了,如果有幸被处理了那么就继续等待60秒获取来自其他微服务返回的响应,如果60s内没有获取到响应,就超时了。

2.当路由方式是serviceId的超时配置

如果路由方式是serviceId的方式,那么ribbon与hystrix同时生效,哪个值小哪个生效,如果想让ribbon的重试生效,就要让hystrix时间超过ribbon总的时间(等ribbon重试完了再熔断):

具体服务的hytrix超时时间 > 全局的hytrix超时时间 > ribbon超时时间

ribbon超时时间=总共访问次数*(ReadTimeout+connectTimeout),

总共访问次数怎么计算?根据如上配置,当首次访问到故障请求的时候,它会再尝试访问一次当前实例(这个次数由MaxAutoRetries决定),如果不行,就换一个负载均衡实例进行访问,如果还不行,再换一次实例访问(更换次数由MaxAutoRetriesNextServer配置),如果依然不行,返回失败信息,所以总共访问次数是:

(首次+MaxAutoRetries)*(首次+MaxAutoRetriesNextServer)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值