网络优化

网络基础知识

一、无线网络

千兆级 LTE 指的是蜂窝网络在理论上的速度能够达到光纤级别的 1Gbps(125MB/s)。html

关于 5G 的原理:文章java

二、Link Turbo

此为手机厂商的网络优化,例如华为最近在荣耀 V20 推出的 Link Turbo 网络聚合加速技术linux

双通道技术,能够在 WiFi 网络不稳定的时候,自动切换到移动网络。相似的技术有:iPhone 的无限网络助理、小米和一加的自适应 WLAN。android

可是双通道技术,同时依然只能使用单一通道,只是会根据网络状况自动切换。而 Link Turbo 硬核的地方在于,能够同时使用两条通道传输数据,并且支持 TCP 和 UDP。其中 TCP 使用开源的 MultiPath TCP(iOS 7 也在引用),而 UDP 则是华为自研的 MultiPath UDP。git

Link Turbo 的缺点:github

  • 覆盖用户比较少。
  • 须要后台服务器同步支持。

Link Turbo 的意义:web

  • 流量愈来愈便宜,用户会更愿意追求体验。
  • 华为能够直接和云服务商以及 CDN 服务商合做,屏蔽应用后台服务器的改造,下降集成成本。

网络 I/O

一、I/O 模型

Linux 内核会把全部外部设备都看做一个文件来操做。在网络 I/O 中系统对一个 Socket 的读写也会有相应的描述符,称为 socket fd(Socket 描述符)。算法

整个 I/O 流程分为两个阶段:spring

等待 Socket 数据准备好。 将数据从内核拷贝到应用进程。编程

在 《UNIX 网路编程》 中,将 UNIX 网络 I/O 模型分为如下五种。

在开发中,比较经常使用的有:

  • 阻塞 I/O
  • 非阻塞 I/O
  • 多路复用 I/O

关于 UNIX 网络 I/O 模型,能够参考:

关于网络,存在的几个问题:

多路复用 I/O 必定比阻塞 I/O 更好?

和文件 I/O 同样,最简单的 I/O 并发方式就是多线程 + 阻塞 I/O。若是同时活动的网络链接很是多,使用多路复用 I/O 性能的确会更好。可是对于客户端来讲,这个假设不必定成立,对于多路复用 I/O 来讲,整个流程会增长大量的 select/epoll 这样的系统调用,不必定比阻塞 I/O 更快。

epoll 必定比 select/poll 要好?

若是同一时间的链接数很是少的状况,select 的性能不会比 epoll 好,可是更多的状况下,epoll 更好。

epoll 使用了 mmap 减小内核到用户空间的拷贝?epoll 并无使用 mmap 技术,参考 epoll 实现。而且也不会如此设计,由于直接共享内存可能会引起比较大的安全漏洞。

二、数据处理

网络 I/O 也使用了终端,不过网络 I/O 的终端更加复杂一些,同时使用了软中断和硬中断。经过硬中断通知 CPU 有数据来了,可是这个处理会很是轻量,耗时的操做被移到软终端处理函数中慢慢处理。

  • 软终端:经过 /proc/softirqs 文件
  • 硬中断:经过 /proc/interrupts 文件。

网卡收发包的流程:

网络性能评估

一、延迟与带宽

延迟:数据从信息源发送到目的地所需的时间。 带宽:逻辑或物理通讯路径最大的吞吐量。

弱网的特色:

二、性能测量

指标:

  • 吞吐量:接收和传输的每秒字节数。
  • 延迟:发送/接收延迟、链接延迟、首包延迟、网络往返时间等。
  • 链接数:每秒的链接数。
  • 错误:丢包计数、超时等。

Linux 提供了大量的网络性能分析工具,比较适用 Android 的有如下几种。

能够直接查看 /proc/net,它里面包含了许多网络统计信息的文件。例如 Android 的 TrafficStats 接口,就是利用 /proc/net/xt_qtaguid/stats 和 /proc/net/xt_qtaguid/iface_stat_fmt 文件来统计应用的流量信息。

移动端优化

网络优化的核心三问题:

除了这三个问题,还须要关心:耗电、流量。

整个网络请求,主要分几个步骤:

  • DNS 解析。经过 DNS 服务器,拿到对应域名的 IP 地址。比较关注:DNS 解析耗时状况、运营商 LocalNDS 的劫持、DNS 调度等问题。
  • 建立链接。和服务器创建链接,包括 TCP 三次握手、TLS 密钥协商等工做。多个 IP/端口该如何选择、是否要使用 HTTPS、可否能够减小甚至省下建立链接的时间,这些问题是优化的关键。
  • 发送/接收数据。关键点:组装数据、发送数据、接收数据、解析数据,主要关注如何根据网络情况,将带宽利用好,怎样快速检测到网络延迟,在弱网下如何调整包大小等问题。
  • 关闭链接。关注:主动关闭和被动关闭两种状况。

一个网络库的核心做用主要有如下三点:

  • 统一编程接口。
  • 全局网络控制。统一的网络调度、流量监控以及容灾管理等。
  • 高性能。关注:速度、CPU、内存、I/O 的使用,以及失败率、崩溃率、协议兼容性等方面。

比较好的网络库:

  • OkHttp
  • Chromium 的 Cronet
  • 微信的 Mars

商业软件的应用:

  • Chromium:蘑菇街、头条、UC 浏览器。
  • Mars:微信、拼多多、虎牙、链家、美丽说。

对比:

对于不用 OkHTTP,主要缘由在于不支持跨平台。对于大型应用来讲,跨平台是很是重要的。

对于 Mars,它是一个跨平台的 Socket 层解决方案,并不支持完整的 HTTP 协议,因此 Mars 从严格意义上来讲,并非一个完整的网络库。可是它在弱网和链接上作了大量的优化,而且支持长链接。参考:Wiki

Chromium 没有太大的缺点,而且还能够享受 Google 后续网络优化的成功,相似 TLS 1.三、QUIC 支持等。可是它针对弱网没有作太多定制的华油,也不支持长链接。一般基于 Chromium 的二次开发,都是为了解决这两个问题。

大网络平台 对于大公司,不知足于客户端优化,还会在服务端上作双端优化。

一、HTTPDNS

DNS 的解析是咱们网络请求的第一项工做,默认使用运营商的 LocalDNS 服务,这块的耗时,在 3G 网络下多是 200~300ms,4G 网路也须要 100ms。

LocalDNS 慢不是最大的问题,还存在一些其余的问题:

  • 稳定性。UDP 协议,无状态。容易域名劫持,每一年至少几百万个域名被劫持,一年至少十次大规模事件。
  • 准确性。LocalNDS 调度常常不许确。
  • 及时性。运营商会修改 DNS 的 TTL。致使 DNS 修改生效延迟。
  • HTTPDNS 就是为了解决 LocalDNS 的这些问题。

参考百度的 《DNS 优化》

二、链接复用

建立链接须要通过:

  • TCP 三次握手
  • TLS 密钥协商

创建链接的代价很是大,这里的优化思路主要是复用链接,这样不用每次请求都创建链接。

链接复用主要是利用 HTTP 协议里的 keep-alive,而且 Http 2.0 的多路复用则能够进一步提高链接复用率。它复用的这条链接支持同时处理多条请求,全部请求均可以并发在这条链接上进行。

HTTP 2.0 的多路复用的问题:

  • 同一条 Http 2.0 链接,只支持同一个域名。
  • 后端须要为了支持 HTTP 2.0 额外改造。

为了解决这两个问题,一般会在统一接入层作改造,接入层将数据转换到 HTTP/1.1 再转发到对应域名的服务器。

HTTP 2.0 的多路复用,本质上依然是同一条 TCP 链接,若是全部的域名的请求都集中在某一条链接中,在网路拥塞的时候,容易出现 TCP 队首阻塞问题。

对于客户端网络库,OkHttp 和 Chromium 对于 HTTP/2.0 的链接,同一个域名只会保留一条链接。如遇到第三方请求,特别是文件下载以及视频播放等场景,可能会遇到对方服务器单链接限速的问题,此处能够经过修改网络库,或者简单禁用掉 HTTP/2.0 协议解决。

三、压缩与加密

压缩能够减小传输的数据量,对于 HTTP 请求来讲,数据主要包括三部分:

  • 请求 URL
  • 请求 Header
  • 请求 Body

对于 Header,HTTP 2.0 自己支持头部压缩技术,所以须要压缩的主要是 URL 和 请求 body。

压缩的优化主要思路,是把重复的内容都优化掉。对于 URL,通常会带不少公共参数,这些参数大部分是不变的,这样不变的参数客户端只要上传一次便可。

对于请求 Body 来讲,一方面是数据通讯协议的选择,在网络传输中目前最流行的两种数据序列化的方式是 JSON 和 Protocol Buffers。Protocol Buffers 在使用上会复杂一些,可是数据压缩率、序列化和反序列化速度上有很大的优点。

另一方面是压缩算法的选择:

其中,若是 Z-standard 经过业务数据样本训练处合适的字典,是目前压缩率表现最好的算法。

针对特殊的数据,还有一些针对性的压缩方法,例如图片有 webp、hevc、SharpP 等压缩率更高的格式。除此以外,还有基于 AI 的图片超清化也是一大神器。

安全

基于 HTTPS 和 HTTP/2 通道,已经有了 TLS 加密。参考《TLS 协议分析》

HTTPS 的优化思路:

  • 链接复用率。经过多个域名共用同一个 HTTP/2 链接、长链接等方式提高链接复用率。

  • 减小握手次数。TLS 1.3 能够实现 0—RTT 协商。0-RTT 在 TLS 1.3 以前已经被大厂所使用,例如微信的 mmtls、Facebook 的 fizz、阿里的 SlightSSL。

  • 性能提高。使用 ecc 证书代替 RSA,服务端签名的性能能够提高 4~10 倍,可是客户端校验性能下降了约 20 倍,从 10 微秒级下降到 100 微秒级。另一方面能够经过 Session Ticket 会话复用,节省一个 RTT 耗时。

若是客户端设置了代理,TLS 加密的数据能够被揭开并可能被利用,此时能够在客户端使用“证书锁定”。

还有一些方案,多是须要用钱堆出来,好比部署跨国的专线、加速点、多 IDC 就近接入等,除此以外,使用 CDN 服务P2P技术也是比较常见的手段。

QUIC 和 IPv6

QUIC 最先在 2013 年被 Google 实现,在 2018 年,基于 QUIC 的思想,又重写了一套 QUIC 协议,被 HTTP 确认为 HTTP 3.0 标准。

QUIC 能够简单理解为:HTTP 2.0 + TLS 1.3 + UDP。

QUIC 的优点:

  • 灵活控制拥塞协议。能够直接使用 Google 的 BBR 算法。
  • “真”链接复用。客户端切换网络时,不须要重连。

QUIC 现存的问题:

  • 建立链接成功率低。UDP 的穿透性,NAT 局域网路由、交换机、防火墙等会禁止 UDP 443 通讯,目前 QUIC 在国内建连的成功率大约在 95% 左右。
  • 运营商支持。运营商针对 UDP 通道支持不足,表现不稳定,例如 QoS 限速丢包,有些小运营商甚至不支持 UDP 包。

大厂的 QUIC 实践:腾讯微博阿里

IPv6 在中国一直很是沉寂,2017 年 IPv6 支持报告,中国只有 0.38% 的用户使用 IPv6。

2018 年,使用 IPv6 的中国用户已经增加到 3.15%,参考:《2018 年度 ipV6报告

IPv6 必定是从此的去世,推动 IPv6 后,大量的 IP 地址意味着能够告别各类 NAT、P2P、QUIC 的链接问题,阿里云和腾讯云,都作了大量 IPv6 的支持 工做。

微信客户端怎样应对弱网络

阿里以及日活网管通道架构演进

阿里巴巴 HTTP 2.0 实践及无线通讯协议的演进之路

移动端监控

一、如何监控网络

插桩的方式,360 开源的性能工具 ArgusAPM 就是利用 Aspect 切换插桩,实现监控系统和 OkHttp 网络库的请求。

系统网络库的插桩实现,能够参考 TraceNetTrafficMonitor,主要利用 Aspect 的切面功能,关于 OkHttp 的拦截器能够参考 OkHttp3Aspect,它会更加简单一些,由于 OkHttp 自己有代理机制。

@Pointcut("call(public okhttp3.OkHttpClient build())")
public void build() {
}

@Around("build()")
public Object aroundBuild(ProceedingJoinPoint joinPoint) throws Throwable {
    Object target = joinPoint.getTarget();
    if (target instanceof OkHttpClient.Builder &&    Client.isTaskRunning(ApmTask.TASK_NET)) {
        OkHttpClient.Builder builder = (OkHttpClient.Builder) target;
        builder.addInterceptor(new NetWorkInterceptor());
    }
    return joinPoint.proceed();
}
复制代码

插桩的缺点,主要在于不全面,非系统和 OkHttp 网络库,以及 Native 代码的网络请求,都没法被监控到。

Native Hook,相关方法:

链接相关:connect 发送数据相关:send 和 sendto 接受数据相关:recv 和 recvfrom

Socket 建连的堆栈以下:

java.net.PlainSocketImpl.socketConnect(Native Method)
java.net.AbstractPlainSocketImpl.doConnect
java.net.AbstractPlainSocketImpl.connectToAddress
java.net.AbstractPlainSocketImpl.connect
java.net.SocksSocketImpl.connect
java.net.Socket.connect
com.android.okhttp.internal.Platform.connectSocket
com.android.okhttp.Connection.connectSocket
com.android.okhttp.Connection.connect
复制代码

统一网络库。

二、如何监控流量

监控流量,能够经过 TrafficStats 类,它是 Android Api 8 加入的接口,用于获取整个手机或者某个 UID 从开机算起的网路流量。参考 Facebook 的开源库 network-connect-class

getMobileRxBytes()        // 从开机开始 Mobile 网络接收的字节总数,不包括 Wifi
getTotalRxBytes()         // 从开机开始全部网络接收的字节总数,包括 Wifi
getMobileTxBytes()        // 从开机开始 Mobile 网络发送的字节总数,不包括 Wifi
getTotalTxBytes()         // 从开机开始全部网络发送的字节总数,包括 Wifi
复制代码
// stats 接口提供各个 uid 在各个网络接口(wlan0, ppp0 等)的流量信息
/proc/net/xt_qtaguid/stats
// iface_stat_fmt 接口提供各个接口的汇总流量信息
proc/net/xt_qtaguid/iface_stat_fmt
复制代码

TrafficStats 的工做原理,是利用 Linux 内核的统计接口,/proc/net/xt_qtaguid/stats 和 /proc/net/xt_qtaguid/iface_stat_fmt 对这两个接口进行读取和分析。Android 7.0 以后,已经不让开发者直接去读取 stats 文件,只能经过 TrafficStats 获取本身应用的流量信息。

手机的网络测试模式:

  • iPhone:“3001#12345#”
  • Android:“##4636##”

对于厂商,能够拿到更多的网络信息:

  • 网卡驱动层信息。如射频参数,用来判断 WiFi 的新号强度;网卡数据包队列长度,用来判断网络是否拥塞。
  • 协议栈信息,获取数据包发送、接受、时延和丢包信息。

大网络平台监控

网络问题的监控存在的问题:

  • 实时性。容易流失现场。
  • 复杂性。不一样国家地区、运营商等都有可能不太。
  • 链路长。整个请求链路很是长,任何环节均可能出现问题。

监控主要从几个方面考量:

  • 客户端监控。时延、维度、错误。
  • 接入层监控。实时性、可靠性。
  • 监控报警。实时监控、离线监控。
相关文章
相关标签/搜索