千兆级 LTE 指的是蜂窝网络在理论上的速度能够达到光纤级别的 1Gbps(125MB/s)。html
关于 5G 的原理:文章。java
此为手机厂商的网络优化,例如华为最近在荣耀 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
Linux 内核会把全部外部设备都看做一个文件来操做。在网络 I/O 中系统对一个 Socket 的读写也会有相应的描述符,称为 socket fd(Socket 描述符)。算法
整个 I/O 流程分为两个阶段:spring
等待 Socket 数据准备好。 将数据从内核拷贝到应用进程。编程
在 《UNIX 网路编程》 中,将 UNIX 网络 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 有数据来了,可是这个处理会很是轻量,耗时的操做被移到软终端处理函数中慢慢处理。
网卡收发包的流程:
延迟:数据从信息源发送到目的地所需的时间。 带宽:逻辑或物理通讯路径最大的吞吐量。
弱网的特色:
指标:
Linux 提供了大量的网络性能分析工具,比较适用 Android 的有如下几种。
能够直接查看 /proc/net,它里面包含了许多网络统计信息的文件。例如 Android 的 TrafficStats 接口,就是利用 /proc/net/xt_qtaguid/stats 和 /proc/net/xt_qtaguid/iface_stat_fmt 文件来统计应用的流量信息。
网络优化的核心三问题:
除了这三个问题,还须要关心:耗电、流量。
整个网络请求,主要分几个步骤:
一个网络库的核心做用主要有如下三点:
比较好的网络库:
商业软件的应用:
对比:
对于不用 OkHTTP,主要缘由在于不支持跨平台。对于大型应用来讲,跨平台是很是重要的。
对于 Mars,它是一个跨平台的 Socket 层解决方案,并不支持完整的 HTTP 协议,因此 Mars 从严格意义上来讲,并非一个完整的网络库。可是它在弱网和链接上作了大量的优化,而且支持长链接。参考:Wiki。
Chromium 没有太大的缺点,而且还能够享受 Google 后续网络优化的成功,相似 TLS 1.三、QUIC 支持等。可是它针对弱网没有作太多定制的华油,也不支持长链接。一般基于 Chromium 的二次开发,都是为了解决这两个问题。
大网络平台 对于大公司,不知足于客户端优化,还会在服务端上作双端优化。
一、HTTPDNS
DNS 的解析是咱们网络请求的第一项工做,默认使用运营商的 LocalDNS 服务,这块的耗时,在 3G 网络下多是 200~300ms,4G 网路也须要 100ms。
LocalDNS 慢不是最大的问题,还存在一些其余的问题:
参考百度的 《DNS 优化》
二、链接复用
建立链接须要通过:
创建链接的代价很是大,这里的优化思路主要是复用链接,这样不用每次请求都创建链接。
链接复用主要是利用 HTTP 协议里的 keep-alive,而且 Http 2.0 的多路复用则能够进一步提高链接复用率。它复用的这条链接支持同时处理多条请求,全部请求均可以并发在这条链接上进行。
HTTP 2.0 的多路复用的问题:
为了解决这两个问题,一般会在统一接入层作改造,接入层将数据转换到 HTTP/1.1 再转发到对应域名的服务器。
HTTP 2.0 的多路复用,本质上依然是同一条 TCP 链接,若是全部的域名的请求都集中在某一条链接中,在网路拥塞的时候,容易出现 TCP 队首阻塞问题。
对于客户端网络库,OkHttp 和 Chromium 对于 HTTP/2.0 的链接,同一个域名只会保留一条链接。如遇到第三方请求,特别是文件下载以及视频播放等场景,可能会遇到对方服务器单链接限速的问题,此处能够经过修改网络库,或者简单禁用掉 HTTP/2.0 协议解决。
三、压缩与加密
压缩能够减小传输的数据量,对于 HTTP 请求来讲,数据主要包括三部分:
对于 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 的优点:
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 获取本身应用的流量信息。
手机的网络测试模式:
对于厂商,能够拿到更多的网络信息:
网络问题的监控存在的问题:
监控主要从几个方面考量: