当前位置: 首页 > 科技观察

很多人在网络学习中存在这两个问题

时间:2023-03-17 15:33:10 科技观察

很多人在线学习中都会遇到这两个问题。转载本文请联系内功修炼发展公众号。大家好,我是飞哥!在互联网时代,我认为互联网是最重要的技术。但是我认为国内计算机专业的学生到在职工程师的网络学习存在两个问题。一是对实践重视不够。这个问题在大学计算机课程中尤为突出。但这不仅仅是学生群体,还有很多在职工程师。学习一门新技术,止步于用眼睛看,不想手写,做个测试跑一下验证一下。二是抓落实不够。大多数人都愿意关注他们的代码可以达到的范围。一味相信工程上的黑盒依赖,把底层当作黑盒使用,不想花时间去了解底层实现,这对成长是非常不利的。以汽车为例,我们的工程师应该是优秀的赛车手,知道汽车的参数,而不是靠汽车谋生的出租车司机。今天,我就根据我们修炼内功技术文章的创作过程,跟大家聊聊这两点~1.对实践的重视程度不够对于大多数应用场景来说,计算机科学与技术专业所占的比例是很大的高于科学,这意味着它具有更多的技术属性。对于一个技术来说,动手是非常非常重要的。但是我们国内的教学模式过于理论化,以至于很多人认为网络技术的课程过于抽象。这不是学生的问题,而是教学方法的缺陷。您可能还没有听说过任何只看书就能学会的技术。根据1946年美国学者EdgarDale发现的金字塔学习理论,见下图。传统的理论学习,如听力和阅读,只能吸收10%左右的知识,而动手实践可以吸收75%以上的知识。在效率方面,实践学习的效率是理论学习的7-8倍。我认为正确的学习方式应该是边学理论边实践。动手的方法有两种,一种是使用一些命令行工具进行观察,一种是编写程序进行验证。如果你是计算机专业的学生,??我建议你先准备一台Linux电脑(别说工程师了,大部分应该都是用Linux的)。Linux下有很多成熟的网络相关工具可供你使用。现在国内互联网公司的服务器基本都是Linux。使用Linux的优势之一是源代码是公开的。如果真的遇到不懂的问题,可以更方便地搜索答案。这比Windows好得多。对于第一类动手观察的方法,我的建议是当你学习到某一层的时候,找一些相关的工具做几次实验。比如可以启动一个Nginx(或者干脆自己写一个Server),使用curl等工具发起TCP连接建立请求。这时候用tcpdump抓包,看看每次握手的时候包体是什么样子的。有资深工作经验的同学可以试试systemtab、perf等高级工具。简单整理了下linux下的各种网络工具,需要的可以收藏这张图。值得一提的是systemtab是一个可以跟踪内核中的函数,打印一些调试信息的工具。可以在内核函数中获取变量值,也可以打印调用栈。但是需要安装相应版本的内核调试包。另一个工具是perf,它可以计算和跟踪内核活动。您可以通过perflist查看当前系统支持的所有性能事件和检查点。第二种方法是动手编程。对于学生来说,可以从一些简单的开始,比如写一个tcpserver和tcpclient,让他们互相连接,传输一些简单的数据。然后你可以开始练习一些更复杂的东西。比如写一套FTPServer和Client,让它们之间可以实现简单的文件下载。或者写一个WebServer,支持通过浏览器在WebServer上下载静态文件。或者参考Libevent、Redis、SogouWorkFlow等项目包来打包一个简单的网络库。再比如模拟tcpdump写一个抓包工具。(可以参考我的这篇文章,里面提供了一个简单的demo)。工程师也是如此。当你学习一个新的技术方案时,试着去测试它并验证它。比如零拷贝,如果不使用零拷贝,单纯使用readfile+writetosend的性能恐怕要比直接使用sendfile的方式差很多。你能根据真实数据得出一些结论吗?比如使用bareepoll的最高QPS数据是多少,Golang中的net包用一个协程封装epoll一次能达到多少,完全不同步阻塞epoll的网络IO性能数据几何。如果通过实践检验得到验证,你对性能的理解会得到质的提升。就我个人而言,一直都是通过理论+实践的方式来学习知识,效果确实不错。比如我在网络中,想了解一个空的TCP连接消耗了多少内存。下班后花了很长时间翻内核源码,然后做实验。到实验完成时,我对TCP连接的内存开销的理解非常扎实。漫画|我测试了7天,彻底理解了TCP的这些内存开销!一直想搞清楚一个服务器在实践中能支持多少个TCP连接。我还通过动手实验学习了。那时候我来来回回至少用了半个月。参见:漫画|一台Linux服务器最多支持多少个TCP连接?好的。看一百遍不如多练,动手测试单机百万连接的保姆级教程!比如在内存和硬盘的性能方面,我也是通过理论+实测的方式深有体会。机械硬盘的随机IO比你想象的要慢。实际测试顺序IO和随机IO在访问延迟上的区别。如果你能坚持通过动手实践的方法学习,相信你的技术水平会远远超过其他同学。二是抓落实力度不够。大部分计算机网络相关的教材都是讲协议的(首先我不反对理解这些基本协议的重要性),那么如何实现协议呢?是的,似乎很少有人谈论这个。我们日常的开发都是在协议的基础上操作系统的实现。对实现的理解不够,会导致很多线上问题或者性能优化。虽然市面上有一些内核实现相关的资料,但是实在是太难嚼了。比如大家都知道,server先监听,accpet才能接收到连接请求。但是,似乎没有人告诉我们为什么要先听。如果不了解这一点,说明你对全连接队列和半连接队列的理解不深刻,处理问题也很困难。再比如,现在的互联网大部分都是通过TCP连接来工作的,那么一台机器最多能支持多少个TCP连接呢?按理说整个行业都在谈高并发,这应该算是一个很基础的问题了。但是当年我有这个问题的时候,google了一下,也没有找到满意的答案。再比如一个网络包是怎么从网卡到达你的进程的?这个问题表面上看起来很简单,但实际上很多性能优化方案都和这个接收流程有关。你能否深刻理解这个过程决定了你的网络性能。有多少优化措施可用。比如多队列网卡的优化方案,在硬中断这一步就开始把工作分散到多个CPU核上,从而提升性能。几年前,我想彻底弄清楚这个问题。我上网搜索,搜索各种经典书籍,都没有找到我想要的答案。比如为什么TCP握手时间过长,一次TCP连接消耗多少内存。为什么同步阻塞网络IO性能慢,为什么使用epoll后性能会高很多。这些与工程实践相关的问题,光知道网络协议的理论是没有用的。基于对网络实现的深刻理解,应该更好地处理它们。针对这个问题,我在执行层面搜索了网络,结果通过我们开发的内功修炼公众号发表。比如服务端程序为什么要先监听?其实是因为服务端在接收到客户端连接之前,已经准备好了半连接和全连接两个队列。一个用于保存第一次握手请求,另一个用于保存第三次握手。客户端在发起连接之前在内核中选择端口号。