转载

微信Mars与其策略

前几年在微信工作时,参加一些内部会议当时也有做了相关简要整理:Android网络,前端时间也有总结了微信的心跳机制,今天主要是对已开源的Mars进行窥探。

Mars是微信 已经开源 的小数据传输的解决方案。

具体部分可以参考官方图片:

微信Mars与其策略

  • Commn: 网络组件
  • STN: 信令网络(小数据传输),Mars的主要部分
  • SDT: 网络争端组件
  • CDN: 数据网络(大数据传输)( 由于耦合腾讯CDN服务,因此没有开源 )
  • XLOG: 日志组件
  • 终端质量平台

I. STN模块

要求: 高可用、高性能、低负载、容灾性

架构: 稳定、简化

微信Mars与其策略

1. 对比

相比 IOS AFNetworking、Android Retrofit, OkHttp

  • 跨平台
  • Socket层(大多数其他的库都是http层),是为了更深入的优化
  • 更适用于小数据传输,信令网络

2. 特点:

  • 包含两种通道: 长连接(性能要求要的请求),短连接(普通一来一回的请求),对于上层业务而言只需要关注业务。
  • 更适合做移动互联网组件: 前后台、活跃态、休眠、省电、省流量。DNS防劫持,负载,容灾。
  • 更多: 数据监控(网络情况),参数配置。

3. 连接策略

微信Mars与其策略

3.1 建立连接:

连接超时情景

  • 连不通: 无论如何都差不多
  • 被劫持/服务器故障: 希望更快的返回,以便于更换ip端口快速查找可用资源。
  • 弱网络,基站繁忙、连接信号弱,丢包率高: 希望超时更长些,延时高,丢包率高,等长一点,重试多些(由于换IP/端口无用)

连接超时考量点

可用性,网络敏感性,用户体验(< 1min)

连接超时间隔策略:

  • Linux与Android:指数递增(0,2,4,8,16)

    微信Mars与其策略
  • IOS:优化后的指数递增(1,1,1,1,1,2,4,8,16)

    微信Mars与其策略
  • STN: 策略权衡相对适用于微信(可能有些应用需要更高的敏感性): 10s
    微信Mars与其策略

STN连接超时间隔10s的原因:

  1. 占用重试频率比较高的间隔
  2. 10s之后,Android需要经过5s才能发起下一次重试(需要相对长无效的等待时间)

STN连接效率策略

快速找到有效可用的ip/端口资源

常见策略:

  • 串行连接: 资源占用少、无服务器负载问题、超时选择困难、最慢可用选择
  • 并发连接: 网络资源竞争(复杂度、性能消耗)、服务器负责(成倍增加)、最快可用(提高效率)

STN策略:

  • STN复合连接:更快的找到可用并不增加服务器负载

    微信Mars与其策略

建立连接其他优化

微信Mars与其策略

3.2 维持连接

优化探究

  • 链路层: 需要在不可靠的物理设备的基础上,实现节点与节点间可靠的信息传输,一般使用混合自动重传请求(HARQ(Hybrid Automatic Repeat reQuest) = FEC(前馈式错误修正) + ARQ(自动重传请求)),其能够使得前一个失败的尝试中存下有用资讯供之后的解码使用,这个需要手机与RNC都支持.
  • 传输层(TCP层): 需要基于不可靠的链路做端与端之间每个TCP数据包的可靠传输,是通过超时和重传做到的,在发送数据时设定一个定时器,定时器溢出时还没有收到ACK,则重传该数据。

作为应用层:

  • 更应该为用户体验考虑(尽可能提高成功率)
  • 保障弱网络下的可用性
  • 具有网络敏感性,快速的发现新链路

读写超时间隔策略

TCP确认失败: Android系统16min, IOS系统1min~3.5min

  • UNIX的指数退避^1: [1,3,6,12,24,48,64,64…]
    微信Mars与其策略
  • Android: (OPPO手机数据,前部分更积极) [0.25,0.5,1,2,4,8,16,32,64,64,64…]
    微信Mars与其策略
  • IOS: (前部分更积极,后部分也很积极) [1,1,1,2,4.5,9,13.5,26,26…]

STN读写超时(多级超时方案)(应用层读写超设计):

  • 目标: 高性能(体验与尽可能的提高成功率)、可用性(弱网)、敏感性(网络敏感性,快速发现新链路)
  • 做法: 将原有连接断掉,重新选择IP与端口
  • 作用: 减少无效的等待时间(因为重传间隔越来越大,断连重连,使TCP层保持积极重连间隔),增加重试次数;切换链路,在较大波动/严重拥塞,通过更换连接(IP&端口)获得更好的性能。

STN读写超时具体多级超时方案:

总读写超时:请求发出去到完整的服务器回包收完为止。= 发包大小/最低网速(主观 评估值) + 服务器约定最大耗时(主观) + 最大回包大小(由于无法事先获知回包大小(微信最大回包128KB))/最低网速(主观 评估值) + 并发数 * 常量

由于 总读写超时 太主观,并且是一个差网络下、完整的完成单次信令交互的时间估值,因此会显得过长,特别在网络波动或拥塞时,显示无法敏感的发现问题并重试,遂更具步骤进行拆分:

  • 首包超时: 当发送数据大于MSS时,数据会被分段传输,分段到达接收端后重新组合发,因此这里将首个数据分段到达超时定义为首包超时 = 发包大小/最低网速(主观 评估值) + 服务器约定最大耗时(主观) + 并发数 * 常量
  • 包包超时: 两个数据分段之间的超时时间,这个时候因为服务端已经处理完成,不需要再计算等待耗时、请求传输耗时、服务器处理耗时 = 发包大小/网速(客观 准确值) + 并发数 * 常量
  • 动态超时: 分析网络状态,当趋于稳定的时候就减少首包超时,此时如果网络波动时我们预期它能够快速恢复,所以尽快超时然后进行重试,从而改善用户体验
    微信Mars与其策略

II. XLog

高性能跨平台日志模块

1. 所解决的问题

性能 + 可靠性 + 安全

  • 避免频繁GC: 由于Native的实现,有效避免了频繁写文件造成的频繁的GC
  • 避免频繁IO与加密: 达到一定数量日志了再压缩,压缩完再加密
  • 避免丢日志: 将日志写入mmap中,避免程序被系统杀死不会有事件通知
  • 避免IO的耗时: 通过写mmap来达到写文件,其性能与直接操作内存相当
  • 避免日志泄露: 在写入mmap之前就已经对每行日志进行压缩加密,并且采逐行压缩
  • 避免CPU短暂飙高: 采用多条日志流式压缩(日志行数累计到一定大小作为一个压缩单元进行压缩),压缩算法性能较高,由于每个单元的日志并不多,可以把压缩时间分散在整个分散周期内,CPU曲线更平滑。

2. mmap

2.1 写文件

写文件,系统是不会直接把数据写入磁盘,而是 先把数据写入到系统缓存(dirty page),再根据策略将dirty page写入磁盘

dirty page写入磁盘策略:

  • 定时写回 (相关变量在: /proc/sys/vm/dirty_writeback_centisecs/proc/sys/vm/dirty_expire_centisecs )
  • dirty page的大小超过一定比例 (调用write时检测,比例变量存储在 /proc/sys/vm/dirty_background_ratio/proc/sys/vm/dirty_ratio )
  • 内存不足

程序 -> 磁盘: 用户空间内存 -> 内核空间缓存 -> 硬盘 ,因此涉及用户空间与内核空间频繁切换。应用层不可控,出现瓶颈。

2.2 引入mmap的原因:

综合频繁写文件会带来的瓶颈以及 写入内存缓存带来的丢日志的问题 (还有共享内存在Android 4.0以后便不再有权限使用),更好的解决方案mmap

2.3 什么是mmap?

逻辑内存对磁盘文件进行映射(不再有拷贝)

mmap带来的益处显而易见, 操作内存 = 操作文件 , 从而避免了 用户空间与内核空间频繁的切换,也正因为如此,我们只需要将日志写入mmap,就不会应用当前进程(/虚拟机)被杀导致日志丢失的问题。

微信Mars与其策略

2.4 XLog中将mmap回写文件的策略:

  • 内存不足
  • 进程 crash
  • 调用 msync 或者 munmap
  • 不设置 MAP_NOSYNC 情况下 30s-60s(仅限FreeBSD)

3. 压缩算法

该压缩方法只包含了LZ77中的 短语式压缩 ,因为进一步的压缩(如自定义字典/huffman表)无法带来显著的效果,而只要提供控制好压缩单元的长度,仅仅 短语式压缩 就能带来 83.7% 的压缩率。

XLog 采用该算法,对根据策略累计了一定长度的日志进行压缩

通过记录( 距离可复用字符串位置距离,复用字符串长度 ) 来代替可被压缩的字符串进行压缩:

微信Mars与其策略

  • 最终没压缩的字符依然是ascci编码,因此最终的压缩结果都是一堆整数。
  • 滑动历史缓存窗口: 一般是32kb,因此只需要一定大小的压缩单元就可以达到很好的压缩率, 并非 大小越大的单元压缩率越大。
  • 采用分单元流式压缩,而非整个app生命周期内一起压缩,虽然耗时慢了许多但是由于耗时极小因此可以忽略,并且带来了很多好处:1. 个别的压缩错误影响面缩小到对应的单元; 2. 压缩时间分散在各个单元压缩时,因此CPU曲线更平滑
  • 微信Mars:客户端跨平台组件的开发经验
  • 微信Mars——移动互联网下的高质量网络连接探索
  • 微信终端跨平台组件 mars 系列(一) - 高性能日志模块xlog
  • 混合自动重传请求
  • 微信终端跨平台组件 mars 系列(二) - 信令传输超时设计

© 2017, Jacksgong(blog.dreamtobe.cn). Licensed under the Creative Commons Attribution-NonCommercial 3.0 license (This license lets others remix, tweak, and build upon a work non-commercially, and although their new works must also acknowledge the original author and be non-commercial, they don’t have to license their derivative works on the same terms). http://creativecommons.org/licenses/by-nc/3.0/

原文  http://blog.dreamtobe.cn/mars/
正文到此结束
Loading...