专栏首页Java架构师学习架构——Spring Cloud 服务第一次请求超时的优化1. 问题背景2. ribbon的饥饿加载3. zuul网关的饥饿加载4. 总结

架构——Spring Cloud 服务第一次请求超时的优化1. 问题背景2. ribbon的饥饿加载3. zuul网关的饥饿加载4. 总结

1. 问题背景

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

启动涉及到的相关服务:

gateway(zuul网关)

auth-Service(鉴权服务)

user-Service(用户服务)

测试的端点接口为:http:/login/oauth/token。服务之间的调用顺序为:gateway->auth-Service->user-Service。网关收到客户端的请求,转发请求到鉴权服务,鉴权服务对用户身份的核验是通过调用用户服,用户服务给鉴权服务返回身份校验的结果,鉴权服务将身份授权信息返回给gateway,gateway将最终的结果response返回给客户端。

三个服务启动后,通过zipkin监控调用链路信息,可以看到第一次和第二次调用情况如下图所示:

首次调用端点

第二次调用信息

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

如果你想学习Java工程化、高性能及分布式、高性能、深入浅出。性能调优、Spring,MyBatis,Netty源码分析和大数据等知识点可以来找我。

而现在我就有一个平台可以提供给你们学习,让你在实践中积累经验掌握原理。主要方向是JAVA架构师。如果你想拿高薪,想突破瓶颈,想跟别人竞争能取得优势的,想进BAT但是有担心面试不过的,可以加我的Java架构进阶群:554355695

Ribbon 客户端懒加载  

下面分两部分解决这个问题,一是服务之间调用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客户端维护了一个相对的子应用环境的上下文,应用的上下文在第一次请求到指定客户端的时候懒加载。不过可以通过如下配置进行修改:

Java架构进阶群:554355695

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

user服务eager load

3. zuul网关的饥饿加载

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

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.

具体配置如下:

Java架构进阶群:554355695

至此,优化完成,再次重启服务进行第一次请求,发现情况已经好多了,大家可以自己动手尝试改进一下。

4. 总结

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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 日志: 分布式系统的核心日志的应用

    最近这段时间一直在研究消息队列、文件系统、数据库等,慢慢的发现他们都有一个核心组件:日志.有时也叫write-ahead logs 、commit logs 或...

    Java架构
  • 优秀日志实践准则

    程序员的日常离不开日志,日志就好比私人秘书,负责运行周期一切trace工作。优秀的日志实践能极大帮助地程序员快速定位问题,减少在线错误报警。本文将从日志书写时各...

    Java架构
  • 今天是JVM的生日,来了解下JVM的发展历史吧

    Java架构
  • Spring Cloud 服务第一次请求超时的优化

    1. 问题背景 微服务网关netflix-zuul 介绍了微服务网关的使用。通过Spring Cloud组件构建的服务集群,在第一次请求网关时经常会出现time...

    aoho求索
  • go语言调度器源代码情景分析之八:系统调用

    我们将在最后一章讨论有关系统调用方面的抢占调度,所以这里有必要对系统调用有个基本的了解。

    阿波张
  • "类型初始值设定项引发异常" 解决方法

    thz
  • 深入理解计算机系统(3.7)------过程(函数的调用原理)

      上篇博客我们讲解了计算机汇编语言是如何实现循环结构的。本篇博客我们将介绍汇编语言中过程的实现方式。   过程在高级语言中也称为函数,方法。一个过程的调用包括...

    IT可乐
  • 基于区块链的可信成绩记录系统设计(CS CY)

    本文的主要目的是提供基于区块链的系统设计,该系统可产生可核实的成绩记录,对学生、雇主和高等教育机构具有广泛的潜在利益。可核实的成绩记录使学生能够在可信任的框架内...

    用户7495559
  • Cygwin安装镜像选择

    在谷歌查到,需要安装Cygwin,便立马按照文档的指示来下载安装,当安装Cygwin,需要选择下载镜像,列表中给出的镜像多是国外的,在大中国下载会很慢或报错。于...

    努力在北京混出人样
  • 10 道 Java 泛型面试题

      1. Java中的泛型是什么 ? 使用泛型的好处是什么?   这是在各种Java泛型面试中,一开场你就会被问到的问题中的一个,主要集中在初级和中级面试中。那...

    java达人

扫码关注云+社区

领取腾讯云代金券