^图1:MediaNova 对静态资源服务 TTFB 优劣的看法^
在 上一篇《RTT 篇》中我们介绍了影响 FFTB 的 TCP时间 和 TLS时间 两个因素,这次来看 Server-Time
。
名词介绍
什么是服务器处理时间 Server-Time ?
假设,为我们传递信息的
快递员
能以最光速往返两地,那么我们从对方获取信息的效率是否就一定足够高了呢?不一定 ,还取决于对方回信时
撰写信件的速度
。
如果把网络的 数据包 (Data Packet) 比做信件,那么服务器在接到获取信息的请求后 迟迟无法回信
,那么即使在传输的过程中不需要任何耗时,TTFB 表现也会非常差。
我们通常把服务端处理请求数据并往回发出的时间称为:
Server Processing Time 下文缩写为 Server-Time。
我们之前介绍过:
TCP(单次 RTT 的时间)可以被认为是信息交换时的计时单位
任何后续的两端的交互耗时都理应约等于
TCP时间 + 处理时间
即:
- TLS 握手时间 ~理应~ ≈ TCP时间 + 服务器处理握手的时间
同理:
- Server Processing时间 ~也理应~ ≈ TCP时间 + 服务器处理数据的时间
如何观测 Server-Time
我们可以尝试用 httpstat 工具来观察:
~以阿里云OSS、缤纷云S4和七牛Koda 为例~
^图2:阿里云OSS 和 缤纷云S4 主动携带的 Server-Time 数据^
- 阿里云OSS 的服务端统计 Server Time 为 2ms
- 阿里云OSS 的客户端观测结果:
- TCP 建连时间 为 43ms
- TLS 握手处理时间 为 45ms ~88ms - 43ms~
- Server Time 为 44ms ~87ms - 43ms~
实测 Server Time 和 x-oss-server-time 相差很大,推测 OSS 服务给出的值测量范围并不完整(部分耗时的过程没有包括)。
^图3:阿里云OSS 和 缤纷云S4 主动携带的 Server-Time 数据^
- 缤纷云S4 的客户端观测结果:
- TCP 建连时间 为 32ms
- TLS 握手处理时间 为 3ms ~35ms - 32ms~
- Server Time 为 2ms ~34ms - 32ms~
^图4:七牛Koda不透露服务端的 Server-Time 数据^
- 七牛云Koda 的客户端观测 Server Time 为 13ms ~53ms - 40ms~
如何优化 Server-Time
在服务内部有哪些流程、
由于这一部分的时间消耗都在对象存储服务端架构的内部,且各家内部的架构以及复杂程度各不相同,故我们很难从外部细致地检测服务架构内各个部件的准确耗时。
根据我们对云存储的经验,可以大致合理地推测通用流程:
- 硬件防火墙 ------ 通常在数据中心入口统一部署
- 四层负载平衡 ------ 用于统一接收流量分发至具体服务入口
- WAF防火墙层 ------ 用于处理七层请求的安全检测和过滤;
- 七层API网关层 ------ 用于做业务层的请求与分发,通常还包含:
- 自定义域名配置;
- 证书配置;
- IP (段) 黑白名单;
- 规则引擎(执行
防盗链
、User-Agent
等规则)。
- S3协议层 ------ 处理业务层逻辑:
- 解析 S3 协议;
- 根据 IAM 对请求进行身份校验;
- 处理元数据;
- 处理镜像回源;
- 处理媒体(
视频截图
、图片裁剪
等);
- 分布式存储层 ------ 保存海量对象实体数据。
以上是简单的归纳,实际上可能还有更多的组件,如:元数据通常部署于独立的分布式系统中。
这5个主要步骤之间,无一例外也都需要进行网络数据的交换,也会经历多个 RTT 和 Server-Time,所以数据经过的组件越多 ,总体的IO路径越长 ,响应越慢。
缤纷云如何优化
统一流量处理系统 - UPS
为了避免系统组件过多,导致 IO 链路过长,我们放弃了当下流行的 微服务
架构。
除去硬件防火墙和硬件4层负载平衡外,我们把 WAF层
、API网关层
、S3服务层
、统一缓存层
合并为一个单体的 统一上下文处理系统
。
UPS(Unified Processing System)
全称为 统一流量处理系统,本质上是一组 Shared Everything 的无状态流量处理集群,运行在 99th 延迟低于 30us 的内网中。每个 UCPS 之间完全对等的。它能够理解、观测和处理整个链路中的所有协议。
它在过去的一年运行良好,并帮助我们达成以下目标:
- 避免引入太多开源项目,减少不确定性,如:
- Envoy、Openresty 等 ~根据图4中推测七牛 Koda 使用了 Openresty~;
- Kafka 等独立的队列系统;
- Consul 等服务发现
要深刻理解每一个开源项目的优劣并利用好它们并不容易,还需要随时警惕公共漏洞、许可证变更 等不确定风险。遇到紧急问题可能需要购买昂贵的支持服务。
一套系统掌管所有上下文,理解所有协议,掌握所有细节:
- 在相当靠前的位置执行:
- 用户的IP黑白名单策略;
- 参数和请求体的 WAF 过滤策略;
- 限流、限频策略;
- 对内容进行:
- 基于二进制的类型推理(自动 MIME);
- 压缩、优化策略;
- 风险内容的检测和过滤;
- 得以观测TLS的握手细节,允许我们:
- 对带有不规范TLS指纹的请求进行干涉;
- 原生支持 HTTP/2 和 HTTP/3;
- 原生支持多路复用 Multiplexing;
- 原生支持自动的证书管理;
- 原生支持双证书(RSA + ECC);
- 原生支持OCSP装订,并对OCSP过程进行加速。
- 直接处理用户定义的 HTTP 规则策略,如:来路、UA检测;
- S3 协议、IAM协议、元数据 处理。
得益于高度集成的上下文处理系统,所有这些策略都在同一处理解并高效执行。
- 构建高度灵活、实时的系统:
- 实时统计每个存储桶的文件数和占用容量;
- 实时统计每个存储桶和CDN的访问情况(请求次数、出口流量);
- 所有配置实时生效(黑白名单、域名绑定、证书配置);
- 实时日志(已上线);
- 高度隔离。
系统在TLS握手时就已经可以感知业务侧的
BucketName
和AccountID
执行低层次的隔离策略,即使遇到攻击也可以实时在四层阶段拦截;
大幅降低成本、提高性能、可靠性:
- 节省运维大量开源组件需要的额外资源和人力;
- 90% 的情况下流量不用在多个架构组件之间流转和复制多次,可以将外部交换网络最多 12次 的额外 RTT 降低到 0次。
「无状态」的 统一缓存池
得益于 UPS 完全对等 和 理解全局 的特性,我们可以将每个节点剩余的 内存 和 高速SSD 资源充分利用起来,构建出一个 无状态
、低维护
、可 持久化
的分布式多级缓存池,它具有以下特点:
- 接近无状态:由于 UPS 可以在很靠前的阶段感知每个对象的
增、删、改、查
,所以该缓存无需依赖特定时间触发过期:- 热对象缓存永不过期:不会
击穿
也不会 雪崩; - 持久化:自动整合内存与SSD数据,大大降低极端情况下的
缓存踩踏
概率; - 极热内容在
扩容
、缩容
时会自动迁移,大大降低雪崩概率。
- 热对象缓存永不过期:不会
- 架构灵活:由于 UPS 从 4层阶段即可理解几乎全部上下文,我们能够灵活地从大的缓存池中单独为
特定用户或存储桶
灵活地划出「独享资源」:- 可以让单个存储桶 完全独享 多块高速缓存资源;
- 也可以让多个存储桶,共同独享 一块高速缓存资源;
- 高度可靠:
- 缓存利用率可以长期在90%以上,最大程度利用资源;
- 系统会保障新内容在首次访问前 99% 的情况下自动缓存,瞬间大并发场景也能保障
仅有1次
回源; - 幂等,原对象进行删、改缓存会实时生效,缓存结果
强一致
。
高效算法
我们积极地利用更高效地算法为所有用户提供低延迟的服务,例如:
- 我们采用DFA(确定有限状态自动机)来高效地匹配自定义路由和各种用户定义策略;
- TCP层我们使用一种压缩的格式,高效存储存储IP或IP段的黑白名单,在存取和匹配之间不需要进行转换,同时消耗极少的内存。
经测试,我们在匹配自定义的多达1万个IP(或IP段)的混合规则时,即使完全不命中,也只需要约
0.2 毫秒
的时间。
通过我们的长期观察发现,在 99.5% 的情况下 Server Time 的响应时间都低于6ms。
本篇我们介绍了令我们自豪的 统一流量处理系统
和 统一缓存系统
,下篇会介绍同样是我们自研的媒体处理引擎 CoreIX
如何灵活高性能地处理图片。
~Server-Time 上篇 · 完~