大师兄

开篇词 | 一次搞定计算机网络,高效修炼程序员内功

你好,发现求知的乐趣,我是你的老朋友林䭽。

第一次和大家见面,是 2020 年 9 月,我在拉勾教育平台推出的《重学操作系统》专栏,并且收到了一致好评。通过留言区、社群和大家交流后发现,很多同学对网路这块知识比较匮乏,形不成体系化概念。

于是我就萌生了再出一门面向程序员的基础课程——《计算机网络》的想法,带你用 300 分钟系统地建立计算机网络相关知识体系,内容可以覆盖大厂架构师岗位面试以及实际工作中所需的网络知识。

为什么要学习计算机网络

记得我还在阿里工作的时候,午餐期间和几个面试官聊起了上午发生的一起事故。因为 TCP 队头阻塞,没有预备方案,导致分布式集群中部分服务发生延迟,最后有一个系统雪崩。于是大家就开始罗列自己遇到的各种网络问题,比如:

  • 有的遇到 DDoS

  • 有的遇到 DNS 劫持

  • 有的遇到跨机房通信问题

  • ……

既然网络可以作为面试官们的饭后谈资,那么在面试中肯定也经常被问到,说实话,我自己作为面试官,也很喜欢考察候选人关于网络的问题。

原因很简单,网络是一种工作技能,我需要通过几个网络知识的问答,确认求职者未来是否会给我带来很大“麻烦”。而据我观察,大部分求职者都不能游刃有余地应对:

  • 很多候选人在回答“TCP 为什么要 3 次握手”这样简单的问题时,就像背经文一样,没有自己的理解;

  • 当面对“HTTPS 协议的 TTFB 传输时间”这类需要将 TCP 的原理和 HTTPS 结合起来思考的问题,就更加束手无策。

此外,工作当中也经常要用到计算机网络的知识,而且一旦用错就容易造成灾难性的后果,给公司直接带来经济损失。

但实际情况是,很多程序员对网络相关的知识一知半解,不足以应对日常的工作需求。我自己做团队 Leader 时,就深有体会:

  • 团队里多数成员遇到网络故障(如 DNS 故障)时,由于没有系统性地学习过网络相关的知识,对Linux 下,诸如 nslookup、telnet、lsof、netstat 等网络相关的指令一知半解,导致不知道如何定位问题;

  • 很多人使用 TCP 连接时,只考虑收发数据,不能考虑到队头阻塞、多路复用等问题,导致经常出现系统负载不高,但是吞吐量很低的情况。

看到上面这些场景,我相信大部分同学定会感同身受。作为过来人,我可以负责任地说:一名程序员,无论是应对日常开发、日常排查,还是解决突发的网络问题(网络调试、网络优化)都离不开计算机网络。而要想成为优秀的工程师、架构师,朝着更高阶、更高薪的岗位去晋升,补足编程必备基础知识——计算机网络是绕不过去的一关

对程序员来说,计算机网络解决的是常识问题,有了这些常识,你才能更好地利用工具解决工作中的问题。比如用 telnet 调试远程服务、用 Whireshark 抓包定位网络故障;再比如把 ulimit 设置成多少?Dubbo 异步单一连接扛不住了该怎么办?用 HTTP 协议的 Keep-Alive 维持心跳可不可行?等等。

在工作中,当你想快速进入一个领域开发程序,马上就会面临诸如:我用哪个协议?用哪个网络框架?如果计算机网络知识不扎实,很容易选错;另外,你也没有办法优化参数,或者当你承接了系统优化的工作时,由于计网知识不扎实,会陷入无穷无尽的学习。比如今天碰到 TCP 队头阻塞,明天碰到滑动窗口,后天碰到 ARP 和路由算法。

其实计网不是难,而是知识点太多!系统性地学习计网需要花很多时间,直接看面试题的解答又不能理解其精髓。 因此,很多概念往往需要反反复复学习。这就导致你时常陷入一个时间黑洞,重复学习却仍然不会解决工作中遇到的常见问题和应对面试。

所以我觉得,你确实有必要拿出一小部分时间,补足计算机网络这块知识

我是如何设计这门课程的

萌生了设计一门网络的课程后,我又花了大量时间去研究目前市场上相关的学习资料,大致可以总结为四类:

  • 第一类是大学课程和经典教材,优势是全面,缺点是 4/5 的内容不会直接在工作和面试中使用。因此你们都不愿意花时间。

  • 第二类是面经类资料(帖子、博文),对于基础薄弱的人来说,东一榔头、西一棒槌地自学,很难形成知识体系,在工作和面试时无法应对自如。

  • 第三类是专业图书,由于网络相关的知识非常多而繁杂,相应的专业书籍数量非常多而且体量大,对网络初学者和应对面试者来说并不友好。

  • 最后一类便是付费类在线课程,基本上也是内容覆盖面较广,不够聚焦。

显然,这些浅尝辄止的工具类资料只能辅助你做日常知识积累,并不能让你在工作中出类拔萃、在面试过程中脱颖而出。

随着和你们的交流越来越多,我渐渐发现,对于一些“有技术追求”的开发人员来说,他们会更关注底层原理,而网络便是编程必备的底层基础知识。

因此我想专门为程序员设计一门课程,从基础结构、工作原理、应用场景三个维度,帮你系统性地梳理和讲解计算机网络知识,学完之后,足以应对互联网大厂研发岗位“计网”相关的面试题目,解决日常工作场景中遇到的网络问题。专栏所讲知识覆盖了大学内容的 1/5,但是工作、面试只需要用这 1/5 就能很出彩。为了方便你理解,我整理了一份计算机网络知识地图,如下图所示:

图片1.png

下面我会从以上三个维度逐一和你说叨说叨。

第一个维度:网络的基础结构

这块内容是为了带你了解计算机网络的生态和基础设施。我会和你讨论日常生活和工作中常见的东西,比如路由器、交换机、终端、基站等,介绍它们背后隐含的网络,比如公司网络、家庭网络、网络边界等,以及组织它们工作的网络协议栈,TCP/UDP/IP 等。

你可能会说:老师你讲的这些东西,只有后端面试才会用到,我是前端工程师,平时只用 HTTP 协议就够了。说到这,我想和你分享一个曾经发生在我团队里的故事。

8 年前我负责过一个首页日 PV 在百万级别的电商类网站。团队里有一个前端工程师,看到首页有 100 多个卡片,突发奇想地做前端组件化,本来是想解决组件和服务间依赖的问题,让每个卡片自己发请求到服务端。由于上线比较晚,代码 Review 的时候并没有发现,结果变更提交到了线上。

可想而知,当天半夜,睡梦中的我被电话吵醒了,客服说:“服务器挂了。”

这是什么原因导致的呢?要知道每个卡片单独发请求,我们每次打开网站首页,都会发送上百个请求到服务端。这位前端同学的处理方式,直接把服务器的请求数量提升到亿级别,相当于做了一次压力测试和人肉 DDoS。

有同学说,不知者无罪,毕竟 HTTP 协议里没有讲“不能发送这么多请求”。可是,网络是有吞吐量限制的,这是一个常识问题。所谓常识,就是作为工程师本应掌握的知识

听完这个故事,服务端同学可能很开心,暗自窃喜:“我们服务端,肯定不会犯这种常识性错误。”

那我只能再次用事实“说话”了。原来团队里有一个服务端同学,负责维护一个中间层。请求到达中间层,还需要去其他内部服务请求数据,然后组装统一返回。结果中间层很不稳定,经常出现延迟很高,而且内存使用很高的情况。

我 DUMP 了一下内存,发现大量连接对象。经过排查,是因为接收每个请求,系统都会建立很多个到其他服务的连接。在网络波动期,连接持续积压,导致频繁创建 Socket 文件,最终超过操作系统的限制崩溃。

你可能会说,这是一个技术问题,可以用多路复用、长连接、队列等方式解决。但是抛开这些专业的网络 + IO 技术问题,这是不是一个常识问题呢?答案当然是。因为网络连接是有成本的,而且网络是不稳定的。不稳定的情况下,连接数应当有所限制。

第二个维度:工作原理

这块内容将介绍网络的工作原理,里面会涉及一些算法问题,比如滑动窗口、路由和寻址。还会涉及细节问题,比如讲解一些封包格式,但更多的是让你理解网络的工作原理,比如多路复用、缓存设计、Socket、I/O 模型等。

有同学说,网络库一大堆,用就好了,还有必要理解原理吗?是啊,年轻的“萌新”可能都有这个想法。

记得在前两年,团队里有个同学发布了一个数据量千万级资源仓库,用 RPC 公布了一个开放服务给大家用。本地集群压测报告 QPS 3000,于是这位同学找领导汇报,领导也很高兴。

服务上线之前,幸好有另一位工程师对这个 3000 QPS 的设计很感兴趣。自己又写了一个压测程序,远程调用测试集群压测,结果在 1000 QPS 就打挂了。

这是怎么回事呢?因为 3000 的 QPS 是在最邻近的网络节点,用少量连接测试得到的结果。1000 QPS 则是模拟了一个延迟较高的网络,用较高的并发数连接测试的结果。

所以你凭直觉说,哪份测试报告更加靠谱?当然第二份报告更有意义,网络是一个不稳定的环境,服务端随时面临大量的并发连接。大家都使用网络库,但是如何根据自己的业务场景、网络特性、I/O 特性、计算资源特性,优化网络,这就需要你了解网络的工作原理了

第三个维度:应用场景

我相信这部分的意义并不需要我过多强调,这些就是你日常工作需要且每天都在用的东西,只不过你平时用得并不深,但是我要在课程中带你深挖一下这块内容。比如:

  • HTTPS 协议握手的过程?

  • RPC 是如何工作的?

  • IM 系统是如何工作的?

  • 抓包用什么工具?

  • 要注意什么安全攻防?

  • 网络出了问题怎么排查?

这部分的意义反而是最容易理解的,所以我就不再赘述了。

课程设置

我设计这门课的目的,是帮助你系统地解决计算机网络相关的面试问题,每个模块对应一个热门的面试方向,每一讲都会以高频面试题为引,介绍这个方向上涉及的重点内容,引出很多大家在工作中关心的问题和技术难点。深度不超过工程师必备的范畴,但是也不低于阿里、腾讯等一线大厂专家研发岗级别的面试要求。

基于以上思路,我把课程分为 5 个模块,共计 29 讲。为了方便你理解,我绘制了计算机网络的知识体系图:

图片1111.png

模块一:互联网和传输层协议

介绍互联网的体系和整体框架,参与的硬件设备,以及它们的作用。还会介绍传输层协议 TCP 和 UDP,重点讨论它们的工作原理、算法和优化策略。这部分知识是计算机网络的基础,也最能体现网络设计的精髓。

模块二:网络层协议

围绕局域网和 IP 协议展开,包括 ARP、IPv4、IPv6、NAT 等基本概念,探讨 IPv6 的工作原理,以及 IPv6 和 IPv4 的兼容策略。IP 协议几乎是网络层的唯一协议,是大厂面试最为热门的内容之一。模块一和模块二属于基础篇,是计算机网络最底层的基础知识。

模块三:网络编程

围绕 Socket 讨论网络编程,介绍各种网络 I/O 模型和编程方式的优缺点,并以 RPC 框架设计为题去落地学到的这些知识和实现。讨论在不同的并发量、针对不同服务特性选择不同的 I/O 模型,调整 TCP 关联的参数,等等,进而帮助你学习如何优化自己系统的网络。这部分内容会为企业带来实际价值,因此面试官会重点提问。

模块四:Web 技术

讨论平时使用最多且最重要的应用层协议——HTTP 协议(包括 HTTP 2.0),并扩大讨论范围到 Web 技术生态,比如从 DNS 看缓存、从 CDN 看负载均衡、从 HTTP 协议看开发规范、从流媒体技术看协议选择,以及从爬虫技术看网络安全。

模块五:网络安全

讨论网络安全技术,一部分是基础设施,比如证书、加解密、公私钥体系、信任链等;另一部分是具体的攻击手段,比如 DDoS、XSS、SQL 注入、ARP 攻击、中间人攻击等,以及它们的防御手段。安全是所有互联网公司的高压线,学完这块内容能够帮助你屏蔽掉一些高危操作,在工作中避免出现安全问题。

讲师寄语

现在技术迭代很快,而计算机网络相关的知识能帮助你更快适应新技术。很多同学时常感叹“怎么又有新技术了?现有的技术还没学明白呢”,出现这类困扰的根本原因是你的基础知识不牢固。

俗话说,练武不练功,到老一场空。计算机领域则不同,如果你的基础知识不扎实,学习速度就会跟不上新知识的出现速度,很快被行业淘汰。但对于计算机基础好的同学来说,新技术的出现是为了用更简单的技术解决更复杂的问题。这也是我开发《重学操作系统》和《计算机网络通关 29 讲》课程的最大初衷,让程序员不苦恼于频繁迭代的技术,抓住源头,认清本质。

学习计算机网络实际上是加强对未来的适应,有利于你扩宽自己的应用开发的面。而不是每当一个新技术出现,对你来说都是一个全新的技术。

发现求知的乐趣,我是林䭽。下一讲,我想和你聊聊程序员如何打牢基础。