b1gc8v 发表于 2024-7-9 15:22:34

百度App弱网优化实践:为性能而发烧,网络请求平均耗时降低超20%!


    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><img src="https://mmbiz.qpic.cn/mmbiz_jpg/XIibZ0YbvibkUekjNiaXRrnAS4zOTMPR6TLFGH05BnrRIgLictic0lw5wEEmAD2tLwYMnURTC6NvI4wnT05a2xZ2Bsw/640?wx_fmt=jpeg&amp;tp=webp&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" style="width: 50%; margin-bottom: 20px;"></p>作者 | 蔡锐
    编辑 | Yonie本文是百度网络优化系列<span style="color: black;">文案</span>的终结篇,该文深入探讨了网络优化中最为<span style="color: black;">繁杂</span>且难验证和分析的问题——弱网问题。本文经授权转载自【百度App技术】。<span style="color: black;">&nbsp; 前言&nbsp;&nbsp;</span>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">网络优化<span style="color: black;">处理</span>的核心问题有三个,<strong style="color: blue;"><span style="color: black;">第1</span>是安全问题</strong>,<span style="color: black;">咱们</span>在系列《一》DNS 优化 进行了<span style="color: black;">仔细</span>的讲解。<strong style="color: blue;">第二是速度问题</strong>,<span style="color: black;">咱们</span>系列《二》连接优化 <span style="color: black;">亦</span>做了<span style="color: black;">仔细</span>的介绍。<strong style="color: blue;">第三是弱网问题</strong>,它是网络优化中最为<span style="color: black;">繁杂</span>且<span style="color: black;">必须</span>反复验证和分析的问题,<span style="color: black;">咱们</span>的系列《三》弱网优化<span style="color: black;">便是</span>要深入探讨这个问题。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">关联</span>链接:</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">《百度 App 网络深度优化系列(一):DNS 优化》:
      https://www.infoq.cn/article/3QZ0o9Nmv*O0LoEPVRkN</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">《百度 App 网络深度优化系列(二):连接优化》:
      https://www.infoq.cn/article/CDaih849Ao4rS_pctQ2T</p>
    <span style="color: black;">&nbsp; 背景&nbsp;&nbsp;</span>弱网优化<span style="color: black;">必须</span><span style="color: black;">处理</span>的核心问题有两点:<strong style="color: blue;">移动网络环境如此<span style="color: black;">繁杂</span>,<span style="color: black;">咱们</span><span style="color: black;">怎样</span>确定当下<span style="color: black;">便是</span>弱网环境</strong>。<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;">确定为弱网环境下,<span style="color: black;">咱们</span><span style="color: black;">怎样</span><span style="color: black;">提高</span>弱网下的成功率,降低弱网下的时延,<span style="color: black;">从而</span><span style="color: black;">提高</span>用户的网络体验</strong>。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">百度 App 承载着亿级流量,<strong style="color: blue;">弱网比例 0.95%</strong>,可谓不小,这个比例是<span style="color: black;">怎样</span>得来的呢?还是要从什么是判断弱网指标说起。</p>
    <span style="color: black;">判断弱网的指标</span>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">首要</span><span style="color: black;">咱们</span>来探讨下都有<span style="color: black;">那些</span>指标会影响到网络的质量,<span style="color: black;">包含</span> httprtt,tcprtt,throughput,signal strength,bandwidth-delay product。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><img src="https://mmbiz.qpic.cn/mmbiz_png/XIibZ0YbvibkUekjNiaXRrnAS4zOTMPR6TLNLFMT9cN6JEmPEz6jUpRIicIRC3qTB5l2xz0ic7LPQUvABLGRvU27AOA/640?wx_fmt=png&amp;tp=webp&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" style="width: 50%; margin-bottom: 20px;"></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">影响网络质量的指标</span></p>
    1.httprtt <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">httprtt(http Round-Trip Time)又名 TTFB(Time to first byte),<strong style="color: blue;">指从客户端请求的<span style="color: black;">第1</span>个字节<span style="color: black;">起始</span>发送到接收到 http header 的<span style="color: black;">第1</span>个字节的时间差</strong>。httprtt 的时间<span style="color: black;">倘若</span>过长,一方面是客户端本身接入网络质量的问题,另一方面是服务的延时比<span style="color: black;">很强</span>。</p>
    2.tcprtt <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">tcprtt(tcp Round-Trip Time)<strong style="color: blue;">指客户端 tcp 信道<span style="color: black;">第1</span>个字节发送到接收<span style="color: black;">第1</span>个字节的时间差</strong>。<span style="color: black;">由于</span> HTTP 协议底层是基于 TCP 的,<span style="color: black;">因此</span>在复用同一条 tcp 连接的前提下,httprtt 的时间是<span style="color: black;">包括</span> tcprtt 的时间的。大部分<span style="color: black;">状况</span>下 httprtt <span style="color: black;">已然</span><span style="color: black;">能够</span>说明问题的<span style="color: black;">原由</span>。</p>
    3.throughput <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">throughput,中文名字吞吐量,<strong style="color: blue;">它是用来衡量单位时间内成功传送数据的数量,是<span style="color: black;">能够</span>比较客观的衡量网络质量的指标</strong>。吞吐量 =(获 bits 结束<span style="color: black;">体积</span> - 获 bits <span style="color: black;">起始</span><span style="color: black;">体积</span>)/(获 bits 结束时间 - 获 bits <span style="color: black;">起始</span>时间),<span style="color: black;">这儿</span>有个细节<span style="color: black;">必须</span><span style="color: black;">重视</span>,posix socket 的 read 函数返回值是 bytes,<span style="color: black;">因此</span>要乘以 8 得到 bits。<span style="color: black;">一般</span>在 httprtt 比较小的<span style="color: black;">状况</span>下,网络依然很慢,这个时候就<span style="color: black;">能够</span><span style="color: black;">运用</span>吞吐量来确定网络的质量。</p>
    4.signal strength <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">signal strength,<strong style="color: blue;"><span style="color: black;">这儿</span>指的是<span style="color: black;">没</span>线信号强度</strong>,在 Android 上<span style="color: black;">能够</span><span style="color: black;">经过</span> PhoneStateListener 的 onSignalStrengthsChanged <span style="color: black;">办法</span>获取到信号强弱,但要<span style="color: black;">重视</span>只能在 Android M 以上的版本才生效。iOS 上暂时<span style="color: black;">无</span><span style="color: black;">可靠</span>的实现。</p>
    5.bandwidth-delay product <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">bandwidth-delay product,中文名 <strong style="color: blue;">带宽时延乘积</strong>,<strong style="color: blue;">指的是一个数据链路的能力(throughput)与来回通信延迟(rtt)的乘积</strong>。带宽时延乘积的结果是比特不是位,这个比特值反应出当前网络管道的最大容量。TCP 中有一个窗口<span style="color: black;">体积</span>的概念,会限制发送和接收数据的<span style="color: black;">体积</span>,<span style="color: black;">因此</span> TCP 窗口<span style="color: black;">体积</span>的调节是直接受带宽时延乘积的影响,<span style="color: black;">按照</span>带宽时延乘积的值去设置套接字的 setsockopt <span style="color: black;">办法</span>,设置的 option 是 SO_RCVBUF(接收缓冲区<span style="color: black;">体积</span>)和 SO_SNDBUF(发送缓冲区<span style="color: black;">体积</span>)。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">经过</span>上面的内容,<span style="color: black;">咱们</span>对影响网络质量的指标有了<span style="color: black;">必定</span><span style="color: black;">认识</span>,<strong style="color: blue;"><span style="color: black;">针对</span><span style="color: black;">区别</span>的<span style="color: black;">制品</span>,影响网络质量的指标<span style="color: black;">能够</span>理解成<span style="color: black;">同样</span>的,但<span style="color: black;">针对</span><span style="color: black;">每一个</span>指标的阈值肯定是不<span style="color: black;">同样</span>的</strong>,<span style="color: black;">由于</span>这<span style="color: black;">包括</span>着业务场景,<span style="color: black;">例如</span>抖音是视频类网络传输,<span style="color: black;">微X</span>是长连接数据传输,百度是文本<span style="color: black;">照片</span>类数据传输。还<span style="color: black;">包含</span>服务端配备,<span style="color: black;">区别</span><span style="color: black;">制品</span>线的服务集群能力肯定不<span style="color: black;">同样</span>,<span style="color: black;">例如</span>返回客户端的服务端耗时肯定不<span style="color: black;">同样</span>。<span style="color: black;">因此</span>针对<span style="color: black;">区别</span>的<span style="color: black;">制品</span>弱网指标是基本一致的,<span style="color: black;">然则</span>指标的取值肯定是不<span style="color: black;">同样</span>的。</p>
    <span style="color: black;"><span style="color: black;">怎样</span><span style="color: black;">创立</span>弱网标准</span>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">创立</span>弱网标准是一个循序渐进的过程,在一穷二白的时候<span style="color: black;">咱们</span>应该<span style="color: black;">怎样</span><span style="color: black;">创立</span>这个标准呢?答案分为三个<span style="color: black;">周期</span>。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><img src="https://mmbiz.qpic.cn/mmbiz_png/XIibZ0YbvibkUekjNiaXRrnAS4zOTMPR6TLhOzsN8IyNWAbNTpqwa0oic8ChWia0wxU0K0vtDI0JcSMiah4wPxZDVVvA/640?wx_fmt=png&amp;tp=webp&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" style="width: 50%; margin-bottom: 20px;"></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">创立</span>弱网标准的<span style="color: black;">过程</span>:</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;"><span style="color: black;">第1</span><span style="color: black;">周期</span>,线下进行测试。</strong>获取<span style="color: black;">有些</span>符合<span style="color: black;">咱们</span>预期的阈值,这个时候<span style="color: black;">咱们</span><span style="color: black;">必须</span>借助<span style="color: black;">有些</span>网络测试<span style="color: black;">工具</span>,<span style="color: black;">例如</span>苹果的 Network Link Conditioner,Facebook 的 ATC(Augmented Traffic Control),来获取到线下<span style="color: black;">区别</span>网络<span style="color: black;">状况</span>的阈值,<span style="color: black;">通常</span><span style="color: black;">咱们</span>会测试 App 冷<span style="color: black;">起步</span>的场景,网络切换的场景,DNS 故障场景,弱网场景(<span style="color: black;">通常</span>都是配置上下行的带宽,丢包率,延迟,DNS 延迟参数,<span style="color: black;">或</span>更为简单的是<span style="color: black;">运用</span><span style="color: black;">工具</span>默认的<span style="color: black;">有些</span>弱网配置)。</p><strong style="color: blue;">第二<span style="color: black;">周期</span>,线上进行验证</strong>。<span style="color: black;">经过</span>线下充分测试获取到的阈值,在线上<span style="color: black;">能够</span>获取到弱网的比例,在<span style="color: black;">这儿</span>百度 App 是针对特定场景的,<span style="color: black;">例如</span> Feed 刷新,搜索落地页打开等,就算是在移动时代被<span style="color: black;">大众</span>公认的网络体验好的<span style="color: black;">微X</span>,<span style="color: black;">亦</span>只是在信令传输(收发<span style="color: black;">信息</span>)上做到极致优化,<span style="color: black;">因此</span>针对场景搜集弱网数据很<span style="color: black;">要紧</span>。<p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;">第三<span style="color: black;">周期</span>,线上的反复<span style="color: black;">实验</span></strong>。想做到理想的弱网效果,少不了线上反复的阈值<span style="color: black;">调节</span>,<span style="color: black;">经过</span><span style="color: black;">调节</span>阈值比较针对场景的网络请求的成功率、耗时、连接复用率等指标,使<span style="color: black;">咱们</span><span style="color: black;">得到</span>趋向于针对场景的<span style="color: black;">恰当</span>阈值。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">聊了这么多,<span style="color: black;">那样</span>弱网的探测<span style="color: black;">怎样</span>实现呢?</p>
    <span style="color: black;">网络探测的整体架构和实现</span>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">网络探测是弱网检测的<span style="color: black;">基本</span>,<span style="color: black;">是不是</span>能即时,正确的检测出网络质量,是<span style="color: black;">咱们</span><span style="color: black;">首要</span>要<span style="color: black;">处理</span>的问题。<span style="color: black;">咱们</span>把网络探测划分为两部分,<strong style="color: blue;">主动网络探测</strong> 和 <strong style="color: blue;">被动网络采集</strong>。</p>
    <span style="color: black;">1. 主动网络探测</span>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">所说</span>主动探测,<strong style="color: blue;"><span style="color: black;">便是</span>在触发了某些<span style="color: black;">要求</span>后,主动的进行网络探测,并<span style="color: black;">根据</span><span style="color: black;">必定</span>的<span style="color: black;">要求</span><span style="color: black;">检测</span>出<span style="color: black;">是不是</span>是弱网状态</strong>。百度 App 自研了主动探测组件,如下图所示。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><img src="https://mmbiz.qpic.cn/mmbiz_png/XIibZ0YbvibkUekjNiaXRrnAS4zOTMPR6TLq5UHvrkBnjX3xyGPUKYqee1H32bt1acqjVdSSgpV08MZKpT8x8CeCQ/640?wx_fmt=png&amp;tp=webp&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" style="width: 50%; margin-bottom: 20px;"></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">主动网络探测</span></p>
    策略层 <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">探测策略层<span style="color: black;">经过</span>多种策略的组合,使主动探测的即时性和准确性得以大大<span style="color: black;">加强</span>,<span style="color: black;">咱们</span>结合上面的策略层图来解释下检测维度的<span style="color: black;">道理</span>。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">咱们</span>分别在网络请求成功和失败的时候触发了弱网检测的<span style="color: black;">规律</span>。<span style="color: black;">重点</span>分为如下三种<span style="color: black;">规律</span>。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">1)成功时,<span style="color: black;">怎样</span>判断进入弱网状态?<span style="color: black;">检测</span> weakhttprtt 的阈值,这个值取决于业务的设置(<strong style="color: blue;"><span style="color: black;">通常</span>这个值会针对特殊场景的请求取 95 分位<span style="color: black;">或</span>更大分位的值</strong>),大于这个值就会进入弱网检测,为了防止频繁触发探测加了时间间隔维度,<span style="color: black;">日前</span>定义的是 10 分钟。从线下模拟测试来看,只要大于这个阈值,检测结果必然是弱网状态。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">2)成功时,<span style="color: black;">怎样</span>判断退出弱网状态?<span style="color: black;">检测</span> goodhttprtt 的阈值,这个值取决于业务的设置(<strong style="color: blue;"><span style="color: black;">通常</span>这个值会取整体网络的 95 分位<span style="color: black;">或</span>更大分位的值</strong>),<span style="color: black;">少于</span>这个值证明要切换回正常网络状态,为了防止频繁触发探测加了时间间隔维度,<span style="color: black;">日前</span>定义的是 30 秒。从线下模拟测试来看,只要<span style="color: black;">少于</span>这个阈值,检测结果必然是正常状态。<span style="color: black;">倘若</span>大于<span style="color: black;">或</span>等于这个阈值,<span style="color: black;">亦</span><span style="color: black;">不可</span>证明<span style="color: black;">必定</span>不是正常网络,<span style="color: black;">因此</span><span style="color: black;">亦</span><span style="color: black;">必须</span>发起网络探测,<span style="color: black;">然则</span><span style="color: black;">因为</span>这是在成功回调里,频次会很高,<span style="color: black;">因此</span><span style="color: black;">咱们</span>加上时间间隔的限制 30 秒,还加入了次数的限制,连续成功次数 % 次数阈值(4 次)等于 0。但这看起来还是频次有点高,<span style="color: black;">因此</span><span style="color: black;">咱们</span>引入了阶梯递增机制,随着次数的增长,成 60 秒几何倍数增长。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">3)失败时,<span style="color: black;">怎样</span>判断进入弱网状态?<span style="color: black;">首要</span>会判断连续失败次数,连续失败次数 / 次数阈值(2 次)等于 1 并且连续失败次数 % 次数阈值(2 次)等于 0,<strong style="color: blue;">相比成功,失败的次数<span style="color: black;">检测</span>较为苛刻,<span style="color: black;">重点</span>还是<span style="color: black;">思虑</span>多次触发网络检测损耗性能</strong>。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;">进入弱网状态后,就会触发<span style="color: black;">基本</span>能力层的 ping 和 dns query 的探测。</strong></p>
    <span style="color: black;">基本</span>能力层 <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">探测<span style="color: black;">基本</span>能力层,<span style="color: black;">重点</span><span style="color: black;">供给</span>弱网检测的手段,<strong style="color: blue;">一是 dns query,一是 ping</strong>,百度 App <span style="color: black;">运用</span> C++ 实现了这两个能力。<span style="color: black;">为何</span>要<span style="color: black;">选择</span>这两种手段呢?<span style="color: black;">咱们</span>在系列二<span style="color: black;">中间商</span>绍过,一个网络请求,分为 DNS-》TLS-》TCP-》数据传输 四个<span style="color: black;">周期</span>。想判定网络连通性<span style="color: black;">重点</span>在 DNS 和 TCP <span style="color: black;">周期</span>,<span style="color: black;">因此</span> dns query 和 ping <span style="color: black;">便是</span>用来检测这两个<span style="color: black;">周期</span>的连通性手段。dns query 向百度核心域名 mbd.baidu.com 发起 dns <span style="color: black;">查找</span>,<span style="color: black;">查找</span>的 DNS 服务器为系统配置的 DNS 服务器(iOS <span style="color: black;">经过</span> res_ninit 函数构建一个 __res_state 的结构体,Android <span style="color: black;">经过</span> systemproperty 获取 net.dns1 和 net.dns2 的值,便可获取系统配置的 DNS 服务器),DNS <span style="color: black;">查找</span>的超时时间为 3s。ping 的<span style="color: black;">目的</span><span style="color: black;">位置</span>为百度核心域名 mbd.baidu.com,ping 的次数为两次,每次超时时间是默认的 1s。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;">判断出弱网状态后,会将结果<span style="color: black;">供给</span>给接口层。</strong></p>
    接口层 <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">接口层<span style="color: black;">重点</span><span style="color: black;">供给</span>主动探测出来的网络状态,<strong style="color: blue;"><span style="color: black;">日前</span><span style="color: black;">包含</span> GOOD,BAD,UNKNOWN,OFFLINE</strong>。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">1)GOOD:dns <span style="color: black;">查找</span>成功并且 ping <span style="color: black;">亦</span>成功,即标记为 GOOD 状态。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">2)BAD:ping 失败一次标记为 BAD 状态。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">3)UNKNOWN:初始状态<span style="color: black;">或</span>识别不出来状态为 UNKNOWN 状态。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">4)OFFLINE:dns server 错误(<span style="color: black;">无</span>获取到要发送的 DNS server <span style="color: black;">位置</span>),网关错误(读取 /proc/net/route 文件内容失败),发送 dns 错误(发送 dns 数据出错),ping 读写错误(ping 的过程中读写错误),接收 dns 错误(接收 dns 数据出错),ping <span style="color: black;">位置</span>错误(ping <span style="color: black;">位置</span>是空),dns 未知域名错误(dns <span style="color: black;">无</span><span style="color: black;">查找</span>到域名错误),初始化 icmp 错误(初始化 icmp 失败),dns udp 错误(创建 UDP socket 失败),即标记为 OFFLINE 状态。</p>
    <span style="color: black;">2. 被动网络采集</span>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">所说</span>被动采集,<strong style="color: blue;"><span style="color: black;">便是</span>每一次网络请求的所有细节都进行记录,并<span style="color: black;">根据</span><span style="color: black;">必定</span>的<span style="color: black;">要求</span>将原始信息进行上报,上层再<span style="color: black;">按照</span><span style="color: black;">要求</span>判断<span style="color: black;">是不是</span>是弱网状态</strong>。百度 App 基于 cronet 的 NQE(Network Quality Estimator)进行了二次订制<span style="color: black;">研发</span>。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">首要</span><span style="color: black;">咱们</span>讲解下<span style="color: black;">必须</span>采集的数据,<span style="color: black;">包含</span> tcprtt、httprtt、throughput 三个维度,如下图所示。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><img src="https://mmbiz.qpic.cn/mmbiz_png/XIibZ0YbvibkUekjNiaXRrnAS4zOTMPR6TLUWQiaL8Gib2Z5fwZNiao7S55ylCGAay9TATyw2tazrGmktwrcUic2mdQTg/640?wx_fmt=png&amp;tp=webp&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" style="width: 50%; margin-bottom: 20px;"></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">被动采集数据</span></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">1)tcprtt,基于 posix 和 windows 的 socket 编程接口来获取 tcprtt。获取<span style="color: black;">机会</span>在连接完成,读完成和写完成。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">2)httprtt,基于 HTTP 协议栈实现,<span style="color: black;">经过</span>计算接收 response 数据<span style="color: black;">起始</span>和<span style="color: black;">起始</span>发送的时间差,来获取 httprtt。获取<span style="color: black;">机会</span>在读首包完成时。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">3)throughput,<span style="color: black;">经过</span>上面的计算公式<span style="color: black;">必须</span>获取 bytes 和时间,基于 posix 和 windows 的 socket 编程接口来获取 bytes。获取<span style="color: black;">机会</span>在读完成时记录接收的 bytes,在写完成时记录发送的 bytes。时间的获取在吞吐量管理模块里完成,下面会讲到。获取<span style="color: black;">机会</span>在请求完成和请求销毁时。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">如下为被动网络采集的整体架构图。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><img src="https://mmbiz.qpic.cn/mmbiz_png/XIibZ0YbvibkUekjNiaXRrnAS4zOTMPR6TLHH2RpqhibBmxDpR4RaqOaEymGNhEXlTzhbEjNqIfobfJgBshUdgDTmQ/640?wx_fmt=png&amp;tp=webp&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" style="width: 50%; margin-bottom: 20px;"></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">被动网络采集</span></p>
    能力层 <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;">能力层内容上面<span style="color: black;">咱们</span><span style="color: black;">已然</span>讲过,<span style="color: black;">重点</span>采集 tcprtt、httprtt、throughput 三个维度的数据</strong>。</p>
    策略层 <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;">被动采集策略层<span style="color: black;">经过</span>多种策略的组合,降低<span style="color: black;">各样</span>采集数据的上报<span style="color: black;">机会</span>,降低性能的影响</strong>。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">1)套接字管理模块,<span style="color: black;">首要</span>负责获取 tcprtt 的值,<span style="color: black;">怎样</span>获取 tcprtt 呢?<span style="color: black;">经过</span> getsockopt 函数获取 tcp_info 结构体里的 tcpi_rtt 值。其次<span style="color: black;">因为</span> tcprtt 的上报频次比较频繁,<span style="color: black;">因此</span>做了 1 秒的时间间隔上报限制。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">2)吞吐量管理模块,负责吞吐量的计算,上面介绍了计算公式,从网络活动监控器模块获取 bytes,但吞吐量的计算单位是 bits(位),<span style="color: black;">因此</span>将 bytes 乘以 8。<span style="color: black;">仅有</span> GET 请求会被<span style="color: black;">加入</span>统计计算,并且<span style="color: black;">最少</span>要累计 5 个请求后<span style="color: black;">才可</span><span style="color: black;">起始</span>统计计算。排除<span style="color: black;">精细</span>度的干扰,<span style="color: black;">例如</span> localhost,私有子网上的主机,特定用途子网主机,可参考 RFC1918。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">3)网络质量管理模块,从套接字管理模块获取 tcprtt,从吞吐量管理模块获取吞吐量,并且在 HTTP 协议栈读首包完成时获取 httprtt。获取到这三个值后,<span style="color: black;">必须</span>经过<span style="color: black;">有些</span>策略限制上报的频次,10 秒间隔的限制;网络类型<span style="color: black;">不可</span>是 UNKNOWN(1.3 的第三部分会<span style="color: black;">仔细</span>讲解);网络<span style="color: black;">不可</span>频繁切换;rtt 和吞吐量总<span style="color: black;">体积</span>各 300 个。</p>
    接口层 <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;">接口层<span style="color: black;">重点</span><span style="color: black;">供给</span>被动采集出来的网络状态,<span style="color: black;">日前</span><span style="color: black;">包含</span> GOOD,BAD,UNKNOWN,OFFLINE</strong>。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">1)GOOD:3G 和广义的 4G,任一<span style="color: black;">要求</span>满足标记为 GOOD 状态。<span style="color: black;">经过</span>阈值标记 3G 和广义的 4G,httprtt 大于等于 273ms,tcprtt 大于等于 204ms,即标记为 3G 状态。<span style="color: black;">少于</span>这两个值被标记为广义的 4G,<span style="color: black;">所说</span>广义的 4G <span style="color: black;">包括</span> 4G、WiFi、以及质量较好的<span style="color: black;">各样</span>接入网络。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">2)BAD:慢 2G,2G 和 httprtt 大于 1.31 秒,任一<span style="color: black;">要求</span>满足标记为 BAD 状态。<span style="color: black;">经过</span>阈值标记慢 2G 和 2G,httprtt 大于等于 2.01 秒,tcprtt 大于等于 1.87 秒,标记为慢 2G。httprtt 大于等于 1.42 秒,tcprtt 大于等于 1.28 秒,标记为 2G。httprtt 大于 1.31 秒,为百度 App 的 Feed 刷新业务阈值。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">注:上面<span style="color: black;">触及</span>的时间值为 nqe 内部的机制,<span style="color: black;">拥有</span>普适性。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">3)UNKNOWN:<span style="color: black;">违法</span>的 httprtt,tcprtt,吞吐量,任一<span style="color: black;">要求</span>满足标记为 UNKNOWN 状态。何为<span style="color: black;">违法</span>?值为 -1 为<span style="color: black;">违法</span>,那什么<span style="color: black;">要求</span>被标记为 -1 呢?<span style="color: black;">首要</span>初始化时会被标记为 -1,其次在从来<span style="color: black;">无</span>获取到过 httprtt,tcprtt,throughput 的值时,会<span style="color: black;">运用</span>本地默认的值做为判断标准,这是一种容错处理。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">4)OFFLINE:依赖平台能力进行判断,Android 平台依赖 ConnectivityManager 获取 NetworkInfo,<span style="color: black;">经过</span> NetworkInfo 的 isConnected 获取<span style="color: black;">是不是</span>连接,<span style="color: black;">倘若</span>未连接则判断为 OFFLINE 状态,<span style="color: black;">倘若</span> NetworkInfo 为空则判断为 OFFLINE 状态。</p>
    <span style="color: black;">弱网状态下百度App<span style="color: black;">怎样</span>改善用户体验</span>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><img src="https://mmbiz.qpic.cn/mmbiz_png/XIibZ0YbvibkUekjNiaXRrnAS4zOTMPR6TLh0uNELARLBjZ0WC4frqmSGibKFppU0VN7Gjibxu66RYofia8EicvXgza7Q/640?wx_fmt=png&amp;tp=webp&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" style="width: 50%; margin-bottom: 20px;"></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">百度 App 在弱网下的手段</span></p>
    <span style="color: black;">QUIC 在百度App弱网下的最佳实践</span>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">QUIC(Quick UDP Internet Connections)是新一代的互联网传输协议,最早源于 Google,它的详尽内容可参考资料【3】,本章<span style="color: black;">咱们</span>不做 QUIC 的科普介绍。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">百度 App 的普通网络请求在弱网状态下会切换到 QUIC,本章重点讲解下百度 App 针对弱网下开启 QUIC 后遇到的问题,<strong style="color: blue;">一是开启 QUIC 一旦遇到问题<span style="color: black;">是不是</span><span style="color: black;">能够</span>回滚?二是在弱网下<span style="color: black;">怎样</span>能让流量尽可能的走 QUIC?针对这两个问题,<span style="color: black;">咱们</span>的<span style="color: black;">处理</span><span style="color: black;">方法</span>是 QUIC 升降级原理和 QUIC 预连接</strong>。</p>QUIC 升降级原理 <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><img src="https://mmbiz.qpic.cn/mmbiz_png/XIibZ0YbvibkUekjNiaXRrnAS4zOTMPR6TLuwQzqS7zZMeNLvauxzlrGIkkXMd9vnvy6iaY5ibS97CyvmwhxLCJtPOA/640?wx_fmt=png&amp;tp=webp&amp;wxfrom=5&amp;wx_lazy=1&amp;wx_co=1" style="width: 50%; margin-bottom: 20px;"></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">QUIC 升降级原理</span></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">如上图所示,QUIC 的升降级依赖于 HTTP Alternative Services,HTTP Alternative Services 是与 HTTP <span style="color: black;">相关</span>的一个协议,它不是为 QUIC 专门设计的,在 HTTP 协议上<span style="color: black;">重点</span>负责新服务的替换,<span style="color: black;">针对</span> HTTP1.1 协议,它是<span style="color: black;">经过</span> HTTP 响应头传输回来的,<span style="color: black;">因此</span>只能在第二次请求时生效,如下面格式。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">Alt-Svc: quic="alt.example.com:443", quic=":443"; ma=2592000</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">如上信息<span style="color: black;">显示</span>切换到 quic 协议,指定了域名服务和端口,并且指定了生效时间,以秒为单位。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">Alt-Svc: clear</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">如上信息<span style="color: black;">显示</span>将 alter 配置清空</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">在网络库内部有一个 alter 连接和原连接的竞争机制,<span style="color: black;">倘若</span> alter 信息<span style="color: black;">已然</span>存在,优先发送 alter 连接,而原连接会延迟发送,延迟时间默认 300ms,谁先成功就<span style="color: black;">运用</span>哪个连接,<span style="color: black;">倘若</span> alter 连接在 QUIC 握手时失败,会记录这个 alter 信息的失败次数,并<span style="color: black;">按照</span>失败的次数,计算出一个过期时间,这个过期时间会随失败次数指数<span style="color: black;">增多</span>,最长为 2 天。当过期时间到期后,会清除这个 alter 信息,当这个 alter 连接在 QUIC 握手成功后,会清除这个 alter 信息。</p>&nbsp;QUIC 预连接 <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">所说</span> QUIC 的预连接,<span style="color: black;">便是</span>在进入弱网状态前提前<span style="color: black;">创立</span> QUIC 连接。<span style="color: black;">大众</span>都<span style="color: black;">晓得</span> QUIC 引以为傲的 0RTT,但<span style="color: black;">第1</span>次<span style="color: black;">创立</span>连接的时候是<span style="color: black;">必须</span> 1RTT 的,客户端<span style="color: black;">首要</span>会向服务器发送一个 client hello <span style="color: black;">信息</span>,服务器会回复一个 server reject <span style="color: black;">信息</span>,这个<span style="color: black;">信息</span>中<span style="color: black;">包含</span>了 server config,有了 server config 后客户端就<span style="color: black;">能够</span>直接计算出密钥,完成 0RTT,详尽内容可参考资料【4】。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">经过</span>上面的原理,客户端拉取 server config 的成功概率会直接影响 QUIC 在弱网下的流量,<span style="color: black;">因此</span><span style="color: black;">咱们</span>在 App <span style="color: black;">起步</span>的过程中会做一次 QUIC 预连接,将 server config 拉取下来,<span style="color: black;">这般</span>等进入弱网后 alter 连接会大概率的竞争过原连接,<span style="color: black;">从而</span>走 QUIC 协议。</p>
    <span style="color: black;">2. 复合连接在百度 App 弱网下的最佳实践</span>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">复合连接的<span style="color: black;">详细</span>原理<span style="color: black;">能够</span>查看《百度 App 网络深度优化系列《二》连接优化》里的<span style="color: black;">详细</span>介绍,百度 App <span style="color: black;">日前</span>在弱网下只是针对<span style="color: black;">照片</span>网络请求开启了复合连接,<span style="color: black;">由于</span><span style="color: black;">照片</span>请求不管是 HTTPDNS 结果还是 localDNS 的结果都是多个 IP,这是满足复合连接的前提。在弱网下多 IP 的尝试会比单 IP 的结果好些,<span style="color: black;">另一</span>弱网的比例相对较小,复合连接<span style="color: black;">针对</span>服务器的负载<span style="color: black;">亦</span>会小些。</p>
    <span style="color: black;">百度 App 网络整体架构</span>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><img src="data:image/svg+xml,%3C%3Fxml version=1.0 encoding=UTF-8%3F%3E%3Csvg width=1px height=1px viewBox=0 0 1 1 version=1.1 xmlns=http://www.w3.org/2000/svg xmlns:xlink=http://www.w3.org/1999/xlink%3E%3Ctitle%3E%3C/title%3E%3Cg stroke=none stroke-width=1 fill=none fill-rule=evenodd fill-opacity=0%3E%3Cg transform=translate(-249.000000, -126.000000) fill=%23FFFFFF%3E%3Crect x=249 y=126 width=1 height=1%3E%3C/rect%3E%3C/g%3E%3C/g%3E%3C/svg%3E" style="width: 50%; margin-bottom: 20px;"></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">百度 App 网络整体架构</span></p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">百度 App 网络整体架构,<strong style="color: blue;">以网络门面为中间层,隔离上层的最佳实践和底层的<span style="color: black;">基本</span>网络库</strong>。</p>
    最佳实践 <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">客户端网络库的一部分工作量是在<span style="color: black;">怎样</span>让最佳实践做的更好,在音视频上,不管是 iOS 的 AVPlayer,还是双端的 ijkPlayer,都是<span style="color: black;">运用</span> HTTPDNS 组件接管 DNS 模块,<span style="color: black;">无</span><span style="color: black;">所有</span>接管网络模块。ReactNative 的网络模块 RCTNetworking,<span style="color: black;">照片</span>库 Android 的 Fresco 和 iOS 的 SDWebImage,WebView 组件 Android 的 Chromium 和 iOS 的 WKWebView,以及百度 App 的自有业务,都是<span style="color: black;">经过</span>网络门面的接口层直接接管。而<span style="color: black;">针对</span>第三方业务考虑到与宿主耦合的关系,直接<span style="color: black;">运用</span> Android 的 HttpURLConnection 和 iOS 的 URLSession 系统标准的接口。</p>
    网络门面 <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">网络门面<span style="color: black;">重点</span><span style="color: black;">包含</span>,拦截器模块(<span style="color: black;">供给</span>给业务订制网络门面的机制)、并发队列模块(<span style="color: black;">供给</span>高中低以及非常高的网络请求优先级)、网络探测组件(弱网主动探测能力)、网络诊断模块(<span style="color: black;">包含</span> https,ping,dns 的校验)、HTTPDNS 组件(《百度 App 网络深度优化系列《一》DNS 优化》里<span style="color: black;">仔细</span>讲解)、网络监控模块(客户端的打点机制,服务端的例行和突发监控)、HttpURLConnection 封装层、URLSession 封装层。</p>
    <span style="color: black;">基本</span>网络库 <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><span style="color: black;">基本</span>网络库<span style="color: black;">包括</span>两部分,一部分是基于 cronet 二次订制的统一网络库,一部分是 WebSocket <span style="color: black;">基本</span>库(Android 的 JavaWebSocket,iOS 的 SocketRocket)。统一网络库内部<span style="color: black;">包括</span>连接优化的内容(在《百度 App 网络深度优化系列《二》连接优化》里<span style="color: black;">仔细</span>讲解),弱网优化的内容(上面<span style="color: black;">说到</span>的被动采集)。<span style="color: black;">经过</span> AOP 的方式将底层协议栈注入进 HttpURLConnection(利用 URLStreamHandlerFactory)和 URLSession(利用 URLSessionConfiguration 的 protocolClasses 属性),两者都是系统<span style="color: black;">供给</span>的 URL Loading 机制。</p>
    <span style="color: black;">&nbsp; 收益&nbsp;&nbsp;</span>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><strong style="color: blue;">弱网优化的收益<span style="color: black;">咱们</span><span style="color: black;">重点</span>从上面讲到的进入弱网状态后的手段来看,<span style="color: black;">包含</span>开启 QUIC,QUIC 预连接,开启复合连接</strong>。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">1)弱网下开启 QUIC 后,网络连接成功率<span style="color: black;">提高</span> 0.01%,平均耗时降低 23.5%。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">2)弱网下开启 QUIC 预连接后,QUIC 协议的 pv 从 37 万涨到 90 万。</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">3)弱网下开启复合连接后,bad 状态下耗时降低 2.5%,offline 状态下耗时降低 7.7%。</p>
    <span style="color: black;">&nbsp; 结语&nbsp;&nbsp;</span>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">系列一到系列三的内容到今天<span style="color: black;">所有</span>完成,<span style="color: black;">期盼</span>能对<span style="color: black;">大众</span>的工作和学习有所<span style="color: black;">帮忙</span>,感谢<span style="color: black;">大众</span>的<span style="color: black;">连续</span>关注和鼓励。<strong style="color: blue;">生命不息,优化不止,做技术<span style="color: black;">咱们</span>是认真的</strong>。</p>
    作者介绍 <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">蔡锐,9 年移动端<span style="color: black;">研发</span>经验,在百度先后主导过订制 ROM <span style="color: black;">行业</span>、多屏互动<span style="color: black;">行业</span>、Hybrid 跨平台<span style="color: black;">行业</span>等多个技术<span style="color: black;">行业</span>的<span style="color: black;">研发</span>,<span style="color: black;">日前</span>担任百度 App 的客户端资深工程师,参与<span style="color: black;">基本</span>技术的<span style="color: black;">科研</span>,专攻动态化、性能和网络优化方向。</p>
    参考资料 <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">https://chromium.googlesource.com/chromium/src/+/HEAD/docs/android_build_instructions.md</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">https://chromium.googlesource.com/chromium/src/+/HEAD/docs/ios/build_instructions.md</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">https://www.wolfcstech.com/2019/03/27/quic_2019_03_27/</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">https://www.wolfcstech.com/2017/03/09/QUIC%E5%8A%A0%E5%AF%86%E5%8D%8F%E8%AE%AE/</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">https://tools.ietf.org/html/rfc1918</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;">https://github.com/Tencent/mars</p>
    <p style="font-size: 16px; color: black; line-height: 40px; text-align: left; margin-bottom: 15px;"><img src="data:image/svg+xml,%3C%3Fxml version=1.0 encoding=UTF-8%3F%3E%3Csvg width=1px height=1px viewBox=0 0 1 1 version=1.1 xmlns=http://www.w3.org/2000/svg xmlns:xlink=http://www.w3.org/1999/xlink%3E%3Ctitle%3E%3C/title%3E%3Cg stroke=none stroke-width=1 fill=none fill-rule=evenodd fill-opacity=0%3E%3Cg transform=translate(-249.000000, -126.000000) fill=%23FFFFFF%3E%3Crect x=249 y=126 width=1 height=1%3E%3C/rect%3E%3C/g%3E%3C/g%3E%3C/svg%3E" style="width: 50%; margin-bottom: 20px;"></p>




飘雨的姑娘 发表于 2024-9-9 19:45:46

说得好啊!我在外链论坛打滚这么多年,所谓阅人无数,就算没有见过猪走路,也总明白猪肉是啥味道的。

星☆雨 发表于 2024-9-24 12:02:54

感谢楼主分享,祝愿外链论坛越办越好!

b1gc8v 发表于 2024-10-5 02:26:11

顶楼主,说得太好了!

4lqedz 发表于 2024-10-6 22:07:14

一看到楼主的气势,我就觉得楼主同在社区里灌水。

wrjc1hod 发表于 2024-11-9 23:58:35

我赞同你的看法,你的智慧让人佩服,谢谢分享。
页: [1]
查看完整版本: 百度App弱网优化实践:为性能而发烧,网络请求平均耗时降低超20%!