后台服务底层网络通信框架设计方案推演

内容梗概

  • 从简单到复杂,推演后台服务的底层通信框架的进化过程,包括网络IO模型、多线程模型的选择和组合。
  • 推演的最基础模型是IO同步阻塞+单线程模型,然后逐步进化。推动网络框架进化的3个因素是,每秒请求量的增大,并发量的增大,逻辑计算量的增大。
  • 本文使用的底层通信协议以TCP为基础,因此所有推演方案不考虑适用于UDP的信号驱动模型和适用于于文件操作的异步IO模型。
  • 只考虑同步阻塞、同步非阻塞、IO多路复用。
  • 本文不讨论多进程和多线程的区别,在提高cpu利用率上,这两个模型的作用是一致的,因此本文只选择多线程模型进行讨论。
  • 本文主要讨论单机网络通信框架的设计演化,不考虑分布式场景下。本文各项性能对比指标也仅指单台服务器的性能。

推演之前,需要一些系统相关数据支撑。

现有的硬件条件,2017年:

  • 单台服务器处理网络连接请求数,每秒约10W量级。
  • 单机并发处理网络长连接数上限在10W左右(C100K)。
  • CPU 单核,3000MHz,一台服务器以24核计,单核每秒亿次运算。
  • 抛离单次请求的网络处理过程,单核每秒处理每个请求的业务计算量在0-10000W之间。

最简单的网络通信模型, 同步IO阻塞+单线程

此模型是我们推演的基础模型。

适用场景,最简单的网络请求、处理和返回。每秒处理请求量低,并发处理请求数只有1,计算量小。系统硬件、网络IO都不会构成瓶颈。

实例,各类demo、模拟后台服务的测试服务、大型系统中开发的调试接口、数据接口、监控接口。

开始推演:

  1. 假如处理单个请求的计算量不变(依然很小),但请求量增大,并发量增大,网络IO成为瓶颈,这种模型是不能满足需求的。因此需要使用 IO多路复用 + 单线程模型。

  2. 假如 请求量、并发量不变,但是处理请求计算量变大,单核CPU成为瓶颈,这种模型也是不能满足需求的。此时需要使用 IO阻塞 + 多线程模型,利用CPU多核提高计算能力。

  3. 假如请求量、并发量变大,而且处理单个请求的计算量也变大,这种模型更是不能满足需求,但此种情况比较复杂,下面需要详细论述。不过一般情况下也可以使用 IO多路复用 + 多线程模型。

IO同步阻塞 + 多线程

使用这种模型,则是计算量变大,单核CPU往往成为瓶颈,必须使用多核来提高计算能力,但并发度低。数据举例,24核CPU处理每秒处理请求数小于1W,并发度小于24,请求量小于1000/s。

实例,各类 FastCGI 后台服务、php-fpm,用于机器学习模型计算的服务,图像处理服务。

开始推演:

IO同步阻塞 + 多线程,并发度受限于线程数,不适合处理并发,一旦并发量变高,则网络模型应该改用IO多路复用。

IO多路复用 + 单线程

使用这种模型,请求量大,并发量大,但处理每个请求的计算量小。数据举例,qps 5W以上,并发数高,但单核cpu每秒处理也在5W以上。

实例, redis和memcache的网络模型。

IO多路复用 + 多线程

经过上面的推演,IO多路复用 + 多线程模型应该是推演过程的终点。既能处理大量请求,又能提升并发度,提高CPU的利用率解决计算量大的问题。

实例, 大型网络应用。

总结

无论选择什么样的模型,最终的目的就是提高服务器硬件的利用率,并避免资源浪费。

选择合适模型,必须依据其所在的业务场景,根据请求量、并发量、计算量这个3个指标,选择合适的模型。

问题总结

  1. 为什么不是所有情况都选择IO多路复用 + 多线程模型,IO多路复用 + 多线程解决了高访问量、高并发、计算量大的业务?

主要是因为在一些非高访问量、非高并发、非计算量大的业务场景下,IO多路复用 + 多线程是一种过度设计,容易造成资源浪费。

  1. 为什么同步IO非阻塞并没有在推演过程中使用?

    非阻塞的编码,会让代码逻辑复杂,一般不会使用。

Memcache源代码阅读总结

Memcache的组成部分

从设计的层面讲,Memcache的基本组成元素只有3个:

  • 网络IO多路复用, 由libevent库来支持
  • 内存存储,使用Slab的数据结构 和 LRU内存回收算法,管理内存。
  • Hash算法索引数据,使用链表法来存储hash node/item和解决hash冲突。

Memcache 为什么这么设计?

可以拆解为下面的问题:

  • 为什么网络IO多路复用模型?
  • 为什么要用Hash算法?
  • 为什么要使用Slab的内存管理方法?

为了解答上面的问题,首先要探讨Memcache业务场景的特点

Memcache 的使用场景都是被作为分布式缓存

  • 请求量大,连接数多
  • 单次请求数据小,作为缓存消耗的存储空间小
  • 请求延时要求极小

正是以上特点:

  • IO多路复用用于解决请求量大,连接数多的问题
  • 内存存储数据,读写快,解决延时小的问题,并且满足分布式缓存的需求
  • 使用hash索引数据,则提升数据查询速度,更能满足请求延迟小的要求。

这样设计的好处是,既能满足业务场景的需要,又能有很高的性能。

问题汇总

有没有比memcache更好的设计了?

网络模型可以解除libevent依赖,直接使用epoll。 代码质量可以进一步优化。

memcache 选择单线程还是多线程?

早期memcache使用单线程,后期换为多线程。

为什么高版本的memcache选择了多线程模型?

突破单核cpu计算瓶颈,增强并发能力。但我认为提升成本大,效果小,单线程更合理些。

广告引擎技术特点

是一种搜索引擎

广告引擎,是适用于广告搜索场景下的搜索引擎。广告引擎特点,也是由广告业务需求所决定的。

流量大

  • 依附于大流量的用户产品之中,负责将用户流量转化为商业流量。
  • 用户量大,但客户数广告数少。
  • 虽然流量大,但是对并发度的要求比较低。和用户产品相比,广告引擎的业务场景往往不需要和客户端维持长连接。

低延迟

  • 信息流广告必须快于信息,才能不伤害用户体验。
  • 特殊场景广告,必须低延迟,比如APP的开屏、插屏,不然会影响客户使用APP。
  • 在RTB系统中,对低延迟的要求更高。

一方面,由于exchange的存在,增加了一次网络请求和中间的竞价过程,DSP系统的响应时间就要更加短;另一方面,exchange对于DSP的响应时间会作为二次竞价的权值,提高响应速度对提高收入有利。

检索数据量少

  • 业界广告主数量少, 100万~1000万量级
  • 广告物料也少,1亿量级

和传统的搜索引擎相比,广告引擎的数据量并不大。

生产的数据量大

  • 用户每次的访问、展示打点追踪、点击打点追踪都要被记录,每日产生的数据按TB计算。

高可用

虽说高可用几乎成了所有后台服务的特点,但是广告引擎对高可用的要求尤其要高。

  • 系统的每次故障,都可能会造成公司收入的直接降低。

用户的产品的后台系统一旦出现故障,可能损失是用户数,或者伤害了用户体验,但是广告系统损失的是最直接的收入。

实时性

实时性的要求主要体现在广告的及时上下线。如果广告上线不及时,则不能及时产生收入;反之,如果广告下线不及时,则会引发广告超投,也是一种收入损失。

时序性

时序性比较表现在,同一广告的上线、修改、下线等改动,作为消息传递给广告引擎时,必须保证时序性。不然广告的上线和下线等投放状态会出现错误。

二八原则规律的一些特征

  • 80%的收入来自20%的大客户
  • 80%的收益得益于20%的数据

广告收入异常原因追踪总结

本文内容梗概

总结和列举作者常见的广告收入异常的原因,总结问题定位和修复的经验。

因为作者日常多从事广告引擎的开发工作,所以下面的内容往往从广告引擎的视角来阐述。

本文内容多依赖数据监控的一些指标,比如流量、广告展示数、广告点击数、CTR、CPC、CPM、广告召回率、广告存量等。

正常的收入曲线特征

以下特征,仅适用于pv、广告数量级大,收入高的广告系统。

  • 收入曲线平滑变化,没有骤升骤降。
  • 收入变化呈现周期规律特征
  • 同比和环比没有大的变化。日期上与近几日或上周同一时间、上月同一时间,时间上取相同时间间隔内(5分钟)的收入相比,没有特别大的变化
  • 曲线变化符合当日特殊事件给广告收入带来的影响,比如双十一春节等节日、国家重要事件发布、大面积自然灾害等。

如果不满足上面的特征,则收入可能异常。

广告收入异常的数据表现

  • 流量异常
  • 广告展示量异常
  • 广告点击量异常
  • CTR异常
  • CPC、CPM异常

不同原因数据指标的表现不同

  • 流量异常

流量的异常,往往也导致展示量、点击量降低和升高,但是CTR、CPC、CPM等指标不会发生变化。这种情况将收入下降的排查范围缩小到流量端。

  • 广告展示量异常,但流量没有变化
  1. 如果广告召回率(广告存量)是否有异常,排查范围则缩小至广告上下线流程。比如系统问题导致广告上下线异常,广告主是否有大量的上下线操作等。
  2. 如果广告投放机有问题,则把排查范围缩小至广告投放机。
  • ctr 异常
  1. 广告展示量、CPC、CPM不变,则广告主投放的广告质量降低,广告创意素材吸引力差等。
  2. 广告展示量不变,CPC、CPM异常,有可能是由广告主调整价格。
  • CPC、CPM异常,流量、ctr、展示量、点击量都无变化
  1. 算法和竞价策略
  2. 广告主调价

为便于浏览,可参考下面的鱼骨图:

广告收入异常原因

总结

  • 有一个直观易读的数据监控和展示平台非常重要,有利于排查问题的效率。
  • 问题的排查特别依赖数据监控平台,因此数据监控平台必须先保证高可用和数据准确。

技术随笔

此文内容为未经整理的技术工程碎片。

分布式技术已经非常普及,但是为了提高系统的qps和并发能力,我们为什么优先挖掘机器潜力(提高硬件利用率),而不是优先扩容集群。

原因:

  • 服务器运维费用比电费贵多了。提高硬件利用率,虽然不节省电费,但是省服务器。

架构思想

  • 分层 (垂直分离)
  • 分而治之 (水平分离)
  • 动静分离、冷热分离、读写分离
  • 缓冲区
  • 扩展和复用
  • 总线思想、归一
  • 保持简单

方法论

  • 代码和配置分离

工程师手记-将多进程后台服务改造为多线程

背景

2016年秋,部门计划将移动广告引擎和新的移动DSP引擎做架构融合。保留原来的移动广告引擎的业务逻辑,将其移植到新的框架当中去。

新框架有很多特点,其中之一是所有模块都使用了多线程模型而老的移动广告引擎的一个模块则使用了多进程模型。

改造注意点

  • 临界资源的共享
  • 单例资源
  • 内存的共享

改造的陷阱

改造方法

在多进程模型中,单例模式可以安全地被使用。但是在多线程环境中,则要考虑多线程都要抢占单例类,单例类会成为瓶颈,而且还有可能出现线程不安全的问题。

解决方法:

将多进程的单例类,改造成进程体里多例模式,但是在每个线程体内单例。具体方法参考线程安全的单例模式

改造结果

改造成功,并且顺利上线,正常服务。

改造后带来的好处和坏处

  • 性能的提升
  • 内存

广告引擎技术总结

日志尚未完成、持续总结中……

广告引擎,是适用于广告搜索场景下的搜索引擎。

广告引擎特点

广告引擎特点,也是由广告业务需求所决定的。

  • 流量大
  • 低延迟
  • 生产的数据量大
  • 高可用
  • 实时性

详细阐述,请看这里

业务

  • 业务的抽象

架构

  • 广告检索流程
  • 前端
  • 索引
  • 实时数据流

详细阐述,请看这里

算法

  • 竞价排名
  • 机器学习

trouble shoot

性能测试

  • 压力测试
  • IO测试

监控

  • 系统监控

CPU负载、内存使用率、qps、连接数、网络通信延时、第三方服务网络通信延时、计算延时、分业务分模块统计延时、网络IO。

  • 业务监控

广告召回率、广告返回为空比率、ctr、CPC、CPM、展示量、点击量、索引广告数目。

运维

测试

团队

  • 流程管理