You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

184 lines
15 KiB
Markdown

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# 15 | 网络优化(上):移动开发工程师必备的网络优化知识
专栏前面我们已经学习过文件I/O和存储优化相信你已经掌握了文件I/O和存储的性能分析以及优化思路。今天我们就再接再厉继续学习系统中另外一种常见的I/O——网络I/O。
我在写今天的文章时回想了一下大学期间学的那本几百页厚的《计算机网络》当时学得也是云里雾里网络的确涉及了方方面面太多的知识。那我们作为移动开发者来说都需要掌握哪些必备的网络知识呢文件I/O跟网络I/O又有哪些差异呢
今天我们不谈“经典巨著”,一起来解决移动开发工程师面对的网络问题。
## 网络基础知识
现在已经很难找到一款完全不需要网络的应用,即使是单机应用,也会存在数据上报、广告等各种各样的网络请求。既然网络已经无处不在,我们必须要掌握哪些基础知识呢?
**1\. 无线网络**
在过去十年,移动互联网的高速增长离不开无线网络的普及。无线网络多种多样,而且各有各的特点,并且适合使用的场景也不同。
下图是iPhone XS支持的无线网络类型你可以看到WiFi、蜂窝网络、蓝牙、NFC这些都是我们日常经常使用的无线网络类型。
![](https://static001.geekbang.org/resource/image/36/87/36fb4b91a718766075c2fae70c08ba87.png)
“千兆级LTE”指的是蜂窝网络在理论上速度可以达到光纤级别的1Gbps125MB/s。虽然基于4G标准但通过[MIMO](https://zh.wikipedia.org/wiki/MIMO)(多输入多输出)、使用载波聚合的[LAA](https://www.qualcomm.cn/invention/technologies/lte/laa)等技术,现在已经发展到[千兆级LTE](http://rf.eefocus.com/article/id-332405)。2020年我们也即将迎来5G的商用它的理论传输速率可以达到20Gbps。目前5G的标准还没有完全release关于5G的原理我推荐你看看[这篇文章](https://mp.weixin.qq.com/s/bPNuEbwZZS9uS5bKmHskTw)。
![](https://static001.geekbang.org/resource/image/75/7f/7506643f3368cbf1737f8e2e7e44be7f.png)
“802.11ac无线网络”指的是我们经常使用的WiFi。WiFi由IEEE定义和进行标准化规范跟任何流行的技术一样IEEE也一直在积极地发布新的协议。目前最常用的是[802.11ac](https://zh.wikipedia.org/wiki/IEEE_802.11ac)标准它的理想速率可以达到866.7Mbps。
从硬件维度上来看所有的无线网络都通过基带芯片支持目前高通在基带芯片领域占据了比较大的优势。之前由于苹果和高通的专利诉讼iPhone XS选用了英特尔的基带芯片但同时也出现大量的用户投诉网络连接异常。
市面上有那么多的无线网络标准和制式还有双卡双待等各种特色功能因此基带芯片对技术的要求非常高。随着未来5G的商用与普及国内也会迎来新的一波换机潮。这对各大芯片厂商来说是机遇也是挑战目前高通、MTK、华为都已经发布了5G基带芯片。如果你对当前的5G格局感兴趣可以阅读[《全世界5G格局》](https://mp.weixin.qq.com/s?src=11&timestamp=1580647446&ver=2134&signature=8h5fb0NUiU4OKOcr-GPNgb4yexcVWJ4OGy6ve8Mqb*ZkNEDFhWwotq*SSrIaktLcvwnxsgaItbDwHK1khe*c2FpwTvi3y8ySBcGNczBd8*REqgAeQyqrufMYvVAjgYD6&new=1)。
**2\. Link Turbo**
像5G这种新的标准可以极大地提升网络速度但缺点是它需要新的基站设备和手机设备支持这个过程起码需要几年的时间。
手机厂商为了提升用户的网络体验也会做各种各样的定制优化华为最近在荣耀V20推出的[Link Turbo 网络聚合加速技术](https://www.pingwest.com/a/181911)就是其中比较硬核的一种“黑科技”。
![](https://static001.geekbang.org/resource/image/85/0f/851e2bdcfe129a629aecc61828e27a0f.png)
从硬件角度来说WiFi和蜂窝网络属于基带芯片的不同模块我们可以简单的把它们理解为类似双网卡的情形。所谓的Link Turbo就是在使用WiFi的同时使用移动网络加速。
可能有人会疑惑我都已经连接WiFi了为什么还要使用收费的移动网络呢有这个疑问的人肯定没有试过使用公司网络打“王者”团战卡成狗的情形其实WiFi可能会因为下面的一些原因导致很不稳定。
![](https://static001.geekbang.org/resource/image/6a/d1/6aad8d120185866e098281e5546025d1.png)
事实上双通道的技术也并不是华为首发。类似iPhone的无线网络助理、小米和一加的自适应WLAN它们都能在侦测到WiFi网络不稳定时自动切换到移动网络。iPhone在连接WiFi的时候移动网络也是依然可以连接的。
而Link Turbo硬核的地方在于可以同时使用两条通道传输数据而且支持TCP与UDP。其中TCP支持使用的是开源的[MultiPath TCP](http://www.multipath-tcp.org)iOS 7也有引入而UDP则是华为自研的MultiPath UDP。
当然这个功能目前比较鸡肋主要是由于一是覆盖的用户比较少当前只有V20一台机器支持而且还需要用户手动开启二是改造成本双通道需要我们的后台服务器也做一些改造才能支持。
![](https://static001.geekbang.org/resource/image/87/a8/87b11d3e2ae67e4048e5164f9f73a2a8.png)
但是这项技术还是有一定的价值一方面流量越来越便宜很多用户不再那么care流量资费的问题。另一方面华为可以直接跟阿里云、华为云、腾讯云以及CDN服务商合作屏蔽应用后台服务器的改造成本。目前爱奇艺、斗鱼和映客这些应用都在尝试接入。
![](https://static001.geekbang.org/resource/image/ee/d6/ee643cc2a974ad530230274dd8c6e0d6.png)
讲到这里你可能会问为什么今天我会花这么多时间来讲Link Turbo技术并不是因为我收了广告费而是我发现很多时候在优化到一定程度之后单靠应用本身很难再有大的突破。**这个时候可能要考虑跟手机厂商、芯片厂商或者运营商合作,因此我们要随时关注行业的动态,并且清楚这些新技术背后的本质所在。**
## 网络I/O
在前面的专栏里我讲了文件I/O的处理流程以及不同I/O方式的使用场景今天我们再一起来看看网络I/O跟文件I/O有哪些差异。
**1\. I/O模型**
“一切皆文件”Linux内核会把所有外部设备都看作一个文件来操作。在网络I/O中系统对一个 Socket的读写也会有相应的描述符称为socket fdSocket描述符
如下图以Socket读取数据recvfrom调用为例它整个I/O流程分为两个阶段
* 等待Socket数据准备好。
* 将数据从内核拷贝到应用进程中 。
![](https://static001.geekbang.org/resource/image/f8/20/f872176205d997f30753ab87a276fa20.png)
在《UNIX网络编程》中将UNIX网络I/O模型分为以下五种。
![](https://static001.geekbang.org/resource/image/e9/39/e9278a9e4e35f28c0272757f280ea339.png)
在开发过程中比较常用的有阻塞I/O、非阻塞I/O以及多路复用I/O。关于UNIX网络I/O模型的更多资料你可以参考《UNIX网络编程》第六章、[《聊聊Linux五种I/O模型》](https://www.jianshu.com/p/486b0965c296)、[《Unix网络I/O模型及Linux的I/O多路复用模型》](http://matt33.com/2017/08/06/unix-io/)。
在查资料的时候我发现网上有很多文章的描述还是存在问题的,我们需要辩证地看。
* 多路复用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的技术但是我查看了Linux与Android的[epoll实现](http://androidxref.com/9.0.0_r3/xref/external/libevent/epoll.c),并没有找到相关的实现。而且我个人认为也不太可能会这样实现,因为直接共享内存可能会引发比较大的安全漏洞。
**2\. 数据处理**
在下一期我还会跟你一起分析当前一些热门网络库的I/O模型现在我们再往底层走走看看底层收发包的流程是怎么样的。
![](https://static001.geekbang.org/resource/image/08/43/08f8dba5e1a23bbefd6ea91fd254fd43.png)
跟文件I/O一样网络I/O也使用了中断。不过网络I/O的中断会更加复杂一些它同时使用了[软中断和硬中断](https://www.mayou18.com/detail/pdt0EOHM.html)。通过硬中断通知CPU有数据来了但这个处理会非常轻量。耗时的操作移到软中断处理函数里面来慢慢处理。其中查看系统软中断可以通过/proc/softirqs文件查看硬中断可以通过/proc/interrupts文件。
关于网卡收发包的流程网上的资料不多,感兴趣的同学可以参考下面几篇文章:
* [网卡收包流程](https://mp.weixin.qq.com/s/UhF2KCASoIhTiKXPFOPiww)
* [Linux网络 - 数据包的接收过程](https://segmentfault.com/a/1190000008836467)
* [Linux网络 - 数据包的发送过程](https://segmentfault.com/a/1190000008926093)
* [Illustrated Guide to Monitoring and Tuning the Linux Networking Stack: Receiving Data](https://blog.packagecloud.io/eng/2016/10/11/monitoring-tuning-linux-networking-stack-receiving-data-illustrated/)
**考虑到这块比较复杂,我在专栏里提供给你参考资料,有兴趣的同学可以进一步深入研究。**
## 网络性能评估
我们常说的网络性能优化,通常都优化哪些方面呢?有的同学可能会关注网络的带宽和服务器成本,特别是直播、视频类的企业,这部分的成本非常高昂。虽然有的时候会做一些取舍,但是用户的访问速度与体验是所有应用的一致追求。
**1\. 延迟与带宽**
如果说速度是关键,那对网络传输速度有决定性影响的主要有以下两个方面:
* 延迟:数据从信息源发送到目的地所需的时间。
* 带宽:逻辑或物理通信路径最大的吞吐量。
回想一下文件I/O性能评估似乎已经很复杂了但是它至少整个流程都在手机系统内部。对于网络来说整个流程涉及的链路就更加复杂了。一个数据包从手机出发要经过无线网络、核心网络以及外部网络互联网才能到达我们的服务器。
![](https://static001.geekbang.org/resource/image/3b/de/3b27d9692bfc276aa16ac2e4c6effede.png)
那延迟和带宽又跟什么因素有关呢这里面涉及的因素也非常多例如信号的强度、附近有没有基站、距离有多远等还跟使用的网络制式正在使用3G、4G还是5G网络有关并且网络的拥塞情况也会产生影响比如是不是在几万人聚集的大型活动场所等。
下面是不同网络制式的带宽和延迟的一般参考值,你可以在脑海里建立一个大致的印象。
![](https://static001.geekbang.org/resource/image/36/83/368f97424661e9ee3295b8c610fb9b83.png)
当出现上面说到的那些因素时,网络访问的带宽要大打折扣,延迟会加倍放大。而高延迟、低带宽的网络场景也就是我们常说的“弱网络”,它主要特点有:
![](https://static001.geekbang.org/resource/image/77/d8/773fa40290c39c0f7e402414273c8fd8.png)
关于“弱网络”如何进行优化我在微信时针对弱网络优化投入了大量的精力这也是我在下一期所要讲的重点。不过我想说的是即使未来5G普及了但是各种各样的影响因素依然存在弱网络优化这个课题是有长期存在的价值。
另外一个方面,不同的应用对延迟和带宽的侧重点可能不太一样。对于直播类应用或者“王者荣耀”来说,延迟会更重要一些;对腾讯视频、爱奇艺这种点播的应用来说,带宽会更加重要一些。**网络优化需要结合自己应用的实际情况来综合考虑。**
**2\. 性能测量**
正如文件I/O测量一样有哪些方法可以帮助我们评估网络的性能呢
对于网络来说,我们关心的是下面这些指标:
* 吞吐量:网络接口接收和传输的每秒字节数。
* 延迟:系统调用发送/接收延时、连接延迟、首包延迟、网络往返时间等。
* 连接数:每秒的连接数。
* 错误:丢包计数、超时等。
Linux提供了大量的网络性能分析工具下面这些工具是Android支持并且比较实用的这些工具完整的功能请参考文档或者网上其他资料这里就不再赘述了。
![](https://static001.geekbang.org/resource/image/25/2a/250ae9961286f6c29629767fdf40aa2a.png)
如果你对Linux底层更加熟悉可以直接查看/proc/net它里面包含了许多网络统计信息的文件。例如Android的[TrafficState](https://developer.android.com/reference/android/net/TrafficStats)接口就是利用/proc/net/xt\_qtaguid/stats和/proc/net/xt\_qtaguid/iface\_stat\_fmt文件来统计应用的流量信息。
## 总结
从网络通信发展的历程来说从2G到4G经历了十几年的时间这背后离不开几百万个基站、几亿个路由器以及各种各样的专利支持。虽然网络标准不停地演进不过受限于基建它的速度看起来很快但是又很慢。
那对我们自己或者应用会有哪些思考呢HTTP 2.0、HTTP 3.0QUIC等网络技术一直在向前演进我们需要坚持不懈地学习思考它们对我们可以产生哪些影响这是对网络“快”的思考。TCP和UDP协议、弱网络等很多东西在这二十多年来依然没有太大的改变网络的基础知识对我们来说还是非常重要的这是对网络“慢”的思考。
## 课后作业
在讲Link Turbo的时候我说过iPhone的无线网络助理、小米和一加的自适应WLAN它们在检测WiFi不稳定时会自动切换到移动网络。那请你思考一下它们是如何实现侦测如何区分是应用后台服务器出问题还是WiFi本身有问题呢今天的作业是在留言区写写你对这个问题的看法欢迎留言跟我和其他同学一起讨论。
今天我推荐一本必读的网络书籍:**《Web性能权威指南》**,它里面第一句话就讲得非常好,我把它分享给你:“合格的开发者知道怎么做,而优秀的开发者知道为什么那么做”。
对于想进一步深入研究的同学,你可以研读这些书籍:
* 《UNIX网络编程》
* 《TCP/IP详解 卷1协议》
欢迎你点击“请朋友读”,把今天的内容分享给好友,邀请他一起学习。最后别忘了在评论区提交今天的作业,我也为认真完成作业的同学准备了丰厚的“学习加油礼包”,期待与你一起切磋进步哦。