专栏首页携程技术干货 | 计算密集型服务的负载均衡策略

干货 | 计算密集型服务的负载均衡策略

作者简介

罗茂林,携程国际机票后台研发总监,主要负责国际机票引擎的研发工作。致力于系统性能优化和研发效率提升。

一般情况下,在计算密集型服务中,即使处理单个请求也需要使用到服务器的所有CPU。如果单台服务器连续接收到两个请求,要么两个请求互相争抢CPU,要么后来的请求排在前面的后面等待处理。最终,会导致平均处理时间变长。常规的负载均衡策略(如轮询、随机等)下,负载均衡器不关心服务器的负载情况,这就很容易造成服务器同时收到多个请求,从而使服务器的服务质量下降。

一、背景

有一天,携程国际机票查询引擎经过一次改造后,虽然平均响应时间得到了提升,但是响应时间也有非常大的波动。从监控图上看,非常明显的尖刺持续存在。如下图:

经过分析,我们发现这次改造深度优化了服务的并行计算能力,使得引擎成为了一个完全的计算密集型服务,它的最大并发处理能力为1。然而,我们却没有相应的修改负载均衡策略,而是继续使用的轮询策略。

对于计算密集型服务,如果使用轮询策略,有如下三种情况:

理想情况是连续两个请求之间无间隔、无重叠,既下一个请求刚好在上一个请求处理完成的时刻到达。这种情况下,后来的请求没有等待时间,服务器也没有空闲时间,得到了充分的利用。

通常情况下,由于请求的到达普遍服从泊松分布,如果使用轮询、随机等负载均衡策略,单机的请求也服从泊松分布,即连续两个请求间总会存在间隔或者重叠,导致服务器资源空闲或者请求响应时间上升。

在极端情况下,如果某个请求的处理时间特别长,后续的一大串请求将产生积压,最终导致这些请求的响应时间也变得特别长,甚至超时。

我们发现,引擎的响应时间尖刺是由极端情况的case造成的。引擎有一类请求A,它qps不高,但是却需要CPU满负荷运转长达几秒甚至10秒才能算出结果。另有一类请求B,它qps非常高,只需要CPU满负荷运转几十毫秒就能算出结果。

当一台服务器正在处理一个A类请求时,在接下来的几秒内,它将继续收到几十个B类请求,而且所有的B类请求都要排队,直到A类请求完成。这就导致大批B类请求的响应时间由应该的几十毫秒升高到几秒,从而造成了严重的尖刺。

二、pooling

为了解决这个问题,我们使用了一种新的负载均衡策略,在这种策略下,服务器不再被动的接收请求,而是主动的去获取请求,这种方式非常容易做到服务器同一时刻只处理一个请求。在我们内部,这种方式被称为pooling(它和线程池类似,可以叫做服务器池)。

在pooling模式中,有三个主要角色:submitor、queue、worker。

  • submitor

submitor一方面用于接收请求方的调用,它收到请求后,不直接处理请求,而是把这个请求提交给queue。

另一方面,submitor接收worker的回调,submitor收到worker的结果后,直接把它转发给请求方。

  • queue

pooling的关键是引入了一个queue,queue是一个全局唯一队列,用于暂时缓冲请求。

我们使用了redis的list结构来实现queue。入队操作为lpush,出队操作为brpop。brpop是阻塞式的操作,当队列为空时,brpop会阻塞直到队列非空。队列非空时,如果有该队列有多个brpop操作阻塞,只有其中一个会被唤醒并且返回数据。

  • worker

worker是实际的请求处理者。在旧的模式下,worker是被动接收请求。在pooling模式下,worker要主动去queue获取请求。worker启动时,要创建一个线程,这个线程启动后,便进入一个无限循环,循环的主要内容为:

1)从queue获取一个请求,当queue没有请求时,worker被阻塞。

2)worker处理这个请求。

3)把结果返回给submitor。

如此往复。可以看到,worker要么正在处理一个请求,要么正在等待一个请求。

三、效果

国际机票查询引擎的负载均衡策略由轮询改为pooling后,效果非常好。系统的平均响应时间降低了大约20%,并且完全消除了响应时间尖刺。

轮询方式:

pooling方式:

本文分享自微信公众号 - 携程技术中心(ctriptech),作者:罗茂林

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-12-12

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

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 干货 | 携程的 Dubbo 之路

    实际上从 2013 年底起,携程内主要使用的就是基于 HTTP 协议的 SOA 微服务框架。这个框架是携程内部自行研发的,整体架构在这近6年中没有进行大的重构。...

    携程技术
  • 干货 | Qunar全链路跟踪及Debug

    作者简介 王克礼,去哪儿平台事业部基础架构Java开发工程师,参与开发和维护去哪儿内部中间件,包括配置中心、消息队列、日志收集及链路跟踪系统QTracer等。 ...

    携程技术
  • 干货 | 关于数据的异常检测,看这一篇就够了

    束开亮,携程大市场部BI团队,负责数据分析与挖掘。同济应用数学硕士,金融数学方向,法国统计学工程师,主修风险管理与金融工程。

    携程技术
  • axios发送两次请求及遇到的坑

    在以前的Vue项目商城中,使用axios组件做数据请求,在页面交互中发现会发送两次网络请求,因为没有造成什么影响,一直也没有追究原因。在一个新的项目中,需要加入...

    honey缘木鱼
  • 从http规范角度来看xmlhttprequest发送请求

    最近有点怠工,停更好久,今天分享一篇小白文,原生ajax,看标题肯定不同于其他文章的ajax,而是从http规范角度来看xmlhttprequest发送请求。

    挥刀北上
  • 每天一道面试题 | day07

    GET请求获取Request-URI所标识的资源,例如:在浏览器的地址栏中输入网址的方式访问网页时,浏览器采用GET方法向服务器获取资源。

    剑走天涯
  • 测试工具Fiddler(三)—— 常见功能介绍

    3、autoresponder: 文件代理:可以使用fiddler来自定义请求返回的文件。

    小菠萝测试笔记
  • 面试官:说说你对 options 请求的理解

    简单来说,就是可以用 options 请求去嗅探某个请求在对应的服务器中都支持哪种请求方法。

    Tusi
  • 小结HTTP状态码

    作为一个web开发工程师,我们平时都会和诸如200, 304, 404, 501等状态码打交道,那么它们是什么意思呢?今天,我们来聊聊~

    嘉明
  • Provisional headers are shown in Chrome network tab

    细心的同学应该留意到,新版开发者工具的 Network 面板中,某些请求头后面会跟着下面这行文字:

    Jerry Wang

扫码关注云+社区

领取腾讯云代金券