irpas技术客

ZUUL参数调优_小路遥同学_zuul调优

网络投稿 4647

依赖:

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)


1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,会注明原创字样,如未注明都非原创,如有侵权请联系删除!;3.作者投稿可能会经我们编辑修改或补充;4.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。

标签: #zuul调优 #依赖spring #Cloud #Eureka #client