Spring Cloud 服务第一次请求超时的优化

1. 问题背景

使用Spring Cloud组件构建的服务集群,在第一次请求时常常会出现timeout的状况,然而第二次就正常了。Spring Cloud版本为Dalston.SR4。html

启动涉及到的相关服务:spring

  • gateway(zuul网关)
  • auth-Service(鉴权服务)
  • user-Service(用户服务)

测试的端点接口为:http:/login/oauth/token。服务之间的调用顺序为:gateway->auth-Service->user-Service。网关收到客户端的请求,转发请求到鉴权服务,鉴权服务对用户身份的核验是经过调用用户服,用户服务给鉴权服务返回身份校验的结果,鉴权服务将身份受权信息返回给gateway,gateway将最终的结果response返回给客户端。
三个服务启动后,经过zipkin监控调用链路信息,能够看到第一次和第二次调用状况以下图所示:app

not-eager-1st
not-eager-1st

second
second

经过上面两次的链路监控信息截图,能够看到第一次的耗时是第二次的10多倍。遇到某些状况,极可能会出现第一次请求的超时。去官网看了下,主要缘由是zuul网关和各个调用服务之间的Ribbon进行客户端负载均衡的Client懒加载,致使第一次的请求调用包括了建立Ribbon Client的时间。经过启动日志信息就能够发现:负载均衡

lazy-load
lazy-load

下面分两部分解决这个问题,一是服务之间调用Ribbon的饥饿加载,对应上面的测试为auth-Service调用user-Service;二是zuul网关的饥饿加载。性能

2. ribbon的饥饿加载

通过调查发现,形成第一次auth-Service调用user-Service耗时长的缘由主要是,Ribbon进行客户端负载均衡的服务实例并非在服务启动的时候就初始化好的,而是在调用的时候才会去建立相应的服务实例。因此第一次调用user-Service耗时不单单包含发送HTTP请求的时间,还包含了建立Ribbon Client的时间,这样一来若是建立时间速度较慢,同时设置的请求超时又比较短的话,很容易就会出现耗时很长甚至超时的状况。
在官网能够看到以下的配置说明:测试

Each Ribbon named client has a corresponding child Application Context that Spring Cloud maintains, this application context is lazily loaded up on the first request to the named client. This lazy loading behavior can be changed to instead eagerly load up these child Application contexts at startup by specifying the names of the Ribbon clients.优化

意为Spring Cloud为每一个Ribbon客户端维护了一个相对的子应用环境的上下文,应用的上下文在第一次请求到指定客户端的时候懒加载。不过能够经过以下配置进行修改:this

ribbon:
 eager-load:
 enabled: true
 clients: client1, client2, client3复制代码

按照如上的配置以后,发现鉴权服务启动时就将user服务的Ribbon客户端进行了加载。url

el
el

3. zuul网关的饥饿加载

上面小节解决了auth-Service调用user-Service的Ribbon客户端启动时饥饿加载。网关做为对外请求的入口,zuul内部使用Ribbon调用其余服务,Spring Cloud默认在第一次调用时懒加载Ribbon客户端。zuul一样须要维护一个相对的子应用环境的上下文,因此也须要启动时饥饿加载。spa

Zuul internally uses Ribbon for calling the remote url’s and Ribbon clients are by default lazily loaded up by Spring Cloud on first call. This behavior can be changed for Zuul using the following configuration and will result in the child Ribbon related Application contexts being eagerly loaded up at application startup time.

具体配置以下:

zuul:
 ribbon:
 eager-load:
 enabled: true复制代码

至此,优化完成,再次重启服务进行第一次请求,发现状况已经好多了,你们能够本身动手尝试改进一下。

4. 总结

本文主要介绍了Spring Cloud的服务第一次请求超时的优化方法。首先介绍了问题的背景,并排查了问题形成的缘由,主要是Ribbon客户端的懒加载;而后分别针对zuul网关和服务之间调用的Ribbon客户端进行配置,使其启动时便加载Ribbon客户端的相关上下文信息。最后想说的是,http调用毕竟仍是性能远低于RPC。。🙂

订阅最新消息,关注公众号,加入个人星球。

xq
xq


参考

  1. spring-cloud Dalston.SR4
  2. Spring Cloud实战小贴士:Ribbon的饥饿加载(eager-load)模式
相关文章
相关标签/搜索