• 深入理解Linux网络:修炼底层内功,掌握高性能原理
  • 深入理解Linux网络:修炼底层内功,掌握高性能原理
  • 深入理解Linux网络:修炼底层内功,掌握高性能原理
21年品牌 40万+商家 超1.5亿件商品

深入理解Linux网络:修炼底层内功,掌握高性能原理

正版保障 假一赔十 电子发票

58.45 5.0折 118 全新

仅1件

河北廊坊
认证卖家担保交易快速发货售后保障

作者张彦飞

出版社电子工业出版社

ISBN9787121434105

出版时间2022-06

装帧平装

开本16开

定价118元

货号E47509A5E25A497D906

上书时间2024-12-12

瀚东书店

已实名 已认证 进店 收藏店铺

   商品详情   

品相描述:全新
商品描述
前言

从大厂的面试说起

 

互联网大厂是当今很多开发人员,尤其是应届毕业生们所向往的公司。但大家应该都听过关于大厂面试候选人的一句调侃的话,“面试造火箭,工作拧螺丝”。这虽然有一点儿夸张的成分,不过也确实描述得比较形象。在面试中,尤其是互联网大厂的面试,对技术的考查往往都很深。但是到了工作中,可能确实又需要花不少时间在写各种各样的重复 CRUD 上。

 

那为啥会出现这种情况,是大厂闲得没事非得为难候选人吗?其实不是,这是因为扎实的底层功力确实对大厂来说很重要。

 

互联网大厂区别于小公司的一个业务特点就是海量请求,随便一个业界第二梯队的App,每天的后端接口请求数过亿很常见,更不用提微信、淘宝等头部应用了。在这种量级的用户请求下,业务能7×24小时稳定地提供服务就非常重要了。哪怕服务故障出现十分钟,对业务造成的损失可能都是不容小觑的。

 

所以在大厂中,你写出来的程序不是能跑起来就行了,是必须能够稳定运行。程序在运行期间可能会无法避免地遭遇各种线上问题。应用都是跑在硬件、操作系统之上的,因此线上的很多问题都和底层相关。如果遇到线上问题,你是否有能力快速排查和处理?例如有的时候线上访问超时是因为TCP的全连接队列满导致的。如果你对这类底层的知识了解得不够,则根本无法应对。

 

另外,大厂招聘高水平程序员的目的可能不仅仅是能快速处理问题,甚至希望程序员能在写代码之前就做出预判,从而避免出故障。不知道你所在的团队是否进行过Code Review(代码评审,简称CR)。往往新手程序员自我感觉良好、觉得写得还不错的代码给资深程序员看一眼就能发现很多上线后可能会出现的问题。

 

大厂在招人上是不怕花钱的,怕的是业务不稳定和不可靠。如果以很低的价钱招来水平一般的程序员,结果导致业务三天两头出问题,给业务收入造成损失,那可就得不偿失了。所以,要想进大厂,扎实的内功是不可或缺的。

 

谈谈工作以后的成长

 

那是不是说已经工作了,或者已经进入大厂了,扎实的内功、能力就可有可无了呢?答案当然是否定的,工作以后内功也同样的重要!

 

拿后端开发岗来举例。初接触后端开发的朋友会觉得,这个方向太容易了。我刚接触后端开发的时候也有这种错觉。我刚毕业做Windows下的C 开发的时候,项目里的代码编译完生成的工程都是几个GB的,但是转到后端后发现,一个服务端接口可能100行代码就搞定了。

 

由于看上去的这种“简单性”,许多工作三年左右的后端开发人员会陷入一个成长瓶颈,手头的东西感觉已经特别熟练了,编程语言、框架、MySQL、Nginx、Redis都用得很溜,总感觉自己没有啥新东西可以学习了。

 

他们真的已经掌握了所有了吗?其实不然,当他们遇到一些线上的问题时,排查和定位手段又极其有限,很难承担得起线上问题紧急救火的重要责任。当程序性能出现瓶颈的时候,只是在网上搜几篇帖子,盲人摸象式地试一试,各个一知半解的内核参数调一调,对关键技术缺乏足够深的认知。

 

反观另外一些工作经验丰富的高级技术人员,他们一般对底层有着深刻的理解。当线上服务出现问题的时候,都能快速发现关键问题所在。就算是真的遇到了棘手的问题,他们也有能力潜入底层,比如内核源码,去找答案,看看底层到底是怎么干的,为啥会出现这种问题。

 

所以大厂不仅仅是在招聘时考察应聘者,在内部的晋升选拔中也同样注重考察开发人员对于底层的理解以及性能把控的能力。一个人的内功深浅,决定了他是否具备基本的问题排查以及性能调优能力。内功指的就是当年你曾经学过的操作系统、网络、硬件等知识。互联网的服务都是跑在这些基础设施之上的,只有你对它们有深刻的理解,才能够源源不断想到新的性能分析和调优办法。

 

所以说,扎实的内功并不是通过大厂面试以后就没有用了,而是会贯穿你整个职业生涯。

 

再聊聊中年焦虑

 

之前网络曾爆炒一篇标题为“互联网不需要中年人”的文章,疯狂渲染35岁码农的前程问题,制造焦虑。本来我觉得这件事情应该只是媒体博眼球的一个炒作行为而已,不过恰恰两三年前我们团队扩充,需要招聘一些级别高一点儿的开发人员,之后使我对此话题有了些其他想法。那段时间我面试了七十多人,其中有很多工作七八年以上的。

 

我面试的这些人里,有这么一部分人虽然已经工作了七八年以上,但是所有的经验都集中在手头的那点儿项目的业务逻辑上。对他们稍微深入问一点儿性能相关的问题都没有好的思路,技术能力并没有随着工作年限的增?而增?。换句话说,他们并不是有七八年经验,而是把两三年的经验用了七八年而已。

 

和这些人交流后,我发现共同的原因就是他们绝大部分的时间都是在处理各种各样的业务逻辑和bug,没有时间和精力去提升自己的底层技术能力,真遇到线上问题也没有耐心钻研下去,随便在网上搜几篇文章都试一试,哪个碰对了就算完事,或者干脆把故障抛给运维人员去解决,导致技术水平一直原地踏步,并没有随着工作年限而同步增长。我从那以后也确实认识到,码农圈里可能真的有中年焦虑存在。

 

那是不是说这种焦虑就真的无解了呢?答案肯定是“不是”。至少我面试过的这些人里还有一部分很优秀,不但业务经验丰富,而且技术能力出众,目前都发挥着重要作用。你也可以看看你们公司的高级别技术人员,甚至业界的各位技术大牛,相信他们会长期是你们公司甚至业界的中流砥柱。

 

那么工作了多年的这两类人中,差异如此巨大的原因是什么呢?我思考了很多,也和很多人都讨论过这个问题。后得出的结论就是大牛们的技术积累是随着工作年限的增长而逐渐增长的,尤其是内功,和普通的开发人员相差巨大。

 

大牛们对底层的理解都相当深刻。深厚的内功知识又使得他们学习起新技术来非常快。举个例子,在初级开发人员眼里,可能Java的NIO和Golang的net包是两个完全不同的东西,所以学习起来需要分别花费不少精力。但在底层知识深厚的人眼里,它们两个只不过是对epoll的不同封装方式,就像只换了一身衣服,理解起来自然就轻松得多。

 

如此良性迭代下去,技术好的和普通的开发人员相比,整体技术水平差距越拉越大。普通开发人员越来越焦虑,甚至开始担心技术水平被刚毕业的年轻人赶超。

 

修炼内功的好处

 

内功,它不帮你掌握的开发语言,不教会你时髦的框架,也不会带你走进火热的人工智能,但是我相信它是你成为“大牛”的必经之路。我简单列一下修炼内功的好处。

 

1)更顺利地通过大厂的面试。大厂的面试对技术的考查比较底层,而网上的很多答案层次都还比较浅。拿三次握手举例,一般网上的答案只说到了初步的状态流转。其实三次握手中包含了非常多的关键技术点,比如全连接队列、半连接队列、防syn flood攻击、队列溢出丢包、超时重发等深层的知识。再拿epoll举例,如果你熟悉它的内部实现方式,理解它的红黑树和就绪队列,就知道它高性能的根本原因是让进程大部分时间都在处理用户工作,而不是频繁地切换上下文。如果你的内功能深入触达这些底层原理,一定会为你的面试加分不少。

 

2)为性能优化提供充足的“弹药”。目前大公司内部对于高级和高级以上工程师晋升时考核的重要指标之一就是性能优化。在对内核缺乏认识的时候,大家的优化方式一般都是盲人摸象式的,手段非常有限,做法很片面。当你对网络整体收发包的过程理解了以后,对网络在CPU、内存等方面的开销的理解将会很深刻。这会对你分析项目中的性能瓶颈所在提供极大的帮助,从而为你的项目性能优化提供充足的“弹药”。

 

3)内功方面的技术生命周期长。Linux操作系统1991年就发布了,现在还是发展得如火如荼。对于作者 Linus,我觉得他也有年龄焦虑,但他可能焦虑的是找不到接班人。反观应用层的一些技术,尤其是很多的框架,生命周期能超过十年我就已经觉得它很牛了。如果你的精力全部押宝在这些生命周期很短的技术上,你说能不焦虑吗!所以我觉得戒掉浮躁,踏踏实实练好内功是你对抗焦虑的解药之一。

 

4)内功深厚的人理解新技术非常快。不用说业界的各位“大牛”了,就拿我自己来举两个小例子。我其实没怎么翻过Kafka的源码,但是当我研究完了内核是如何读取文件的、内核处理网络包的整体过程后,就“秒懂”了Kafka在网络这块为啥性能表现很突出了。还有,当我理解了epoll的内部实现以后,回头再看Golang的net包,才切切实实看懂了绝顶精妙的对网络IO的封装。所以你真的弄懂了Linux内核的话,再看应用层的各种新技术就犹如戴了透视镜一般,直接看到骨骼。

 

5)内核提供了优秀系统设计的实例。Linux作为一个经过千锤百炼的系统,其中蕴含了大量的世界的设计和实现方案。平时我们在自己的业务开发中,在编码之前也需要先进行设计。比如我在刚工作的时候负责数据采集任务调度,其中的实现就部分参考了操作系统进程调度方案。再比如,如何在管理海量连接的情况下仍然能高效发现某一条连接上的IO事件,epoll内部的“红黑树 队列”组合可以给你提供一个很好的参考。这种例子还有很多很多。总之,如果能将 Linux的某些优秀实现搬到你的系统中,会极大提升你的项目的实现水平。

 

时髦的东西终究会过时,但扎实的内功将会伴随你一生。只有具备了深厚的内功底蕴,你才能在发展的道路上走得更稳、走得更远。

 

为什么要写这本书

 

平时大家都是用各种语言进行业务逻辑的代码编写,无论你用的是PHP、Go,还是Java,都属于应用层的范畴。但是应用层是建立在物理层和内核层之上的。我把在应用层的技术能力称为外功,把 Linux 内核、设备物理结构方面的技术能力称为内功。前面已经说了,无论是在职业生涯的哪个阶段,扎实的内功都很重要。

 

那好,既然内功如此重要,那就找一些底层相关的资料加强学习就行了。但很遗憾,我觉得目前市面上的技术资料在内功方向上存在一些不足。

 

先说网上的技术文章。目前网上的技术文章、博客非常多。大家遇到问题往往先去搜一下。但是你有没有发现,网上入门级资料一搜一大把,而内功深厚、能深入底层原理的文章却十分匮乏。

 

比如,现在的互联网应用大部分都是通过TCP连接来工作的,那么一台机器多能撑多少个TCP 连接?按道理说,整个业界都在讲高并发,这应该算是很入门的一个问题了。但当年我产生这个疑问的时候,在搜索引擎上搜了个遍也没找到令我满意的答案。后来我干脆自己动手,花了一个多月时间边做测试,边扒内核源码,才算是把问题彻底搞明白了。

 

再比如,大部分的开发人员都搞过网络相关的开发。那么一个网络包是如何从网卡到达你的进程的?这个问题表面上看起来简单,但实际上很多性能优化方案都和这个接收过程有关,能不能深度理解这个过程决定了你在网络性能上有多少优化措施可用。例如多队列网卡的优化方案是在硬中断这一步开始将工作分散在多个 CPU 核上,进而提升性能的。我几年前想把这个问题彻底搞清楚,几乎搜遍了互联网,翻遍了各种经典书都没能找到想要的答案。

 

还比如,网上搜到的三次握手的技术文章都是在说一些简单的内容,客户端如何发起 SYN 握手进入 SYN_SENT 状态,服务端响应SYN并回复 SYNACK,然后进入 SYN_RECV……诸如此类。但实际上,三次握手的过程执行了很多内核操作,比如客户端端口选择、重传定时器启动、半连接队列的添加和删除、全连接队列的添加和删除。线上的很多问题都是因为三次握手中的某一个环节出问题导致的,能否深度理解这个过程直接决定你是否有在线上快速消灭或者避免此类问题的能力。网上能深入介绍三次握手的文章太少了。

 

你可能会说,网上的文章不足够好,不是还有好多经典书吗?首先我得说,计算机类的一些经典的书确实很不错,值得你去看,但是这里面存在几个问题。

 

一是底层的书都写得比较深奥难懂,你看起来需要花费大量的时间。假如你已经工作了,很难有这么大块的时间去啃。比如我刚开始深入探寻网络实现的时候,买来了《深入理解Linux内核》《深入理解Linux网络技术内幕》等几本书,利用工作之余断断续续花了将近一年时间才算理解了一个大概。

 

另外一个问题就是当你真正在工作中遇到一些困惑的时候,会发现很难有一本经典书能直接给你答案。比如在《深入理解 Linux 网络技术内幕》这本书里介绍了内核中各个组件,如网卡设备、邻居子系统、路由等,把相关源码都讲了一遍。但是看完之后我还是不清楚一个包到底是如何从网卡到应用程序的,一台服务器到底能支持多少个TCP连接。

 

还有个问题就是计算机技术不同于其他学科,除理论外对实践也有比较高的要求。如果只是停留在经典书里的理论阶段,实际上很多问题根本就不能理解到位。这些书往往又缺乏和实际工作相关的动手实验。比如对于一台服务器到底能支持多少个TCP连接这个问题,我自己就是在做了很多次的实验以后才算比较清晰地理解了。还有就是如果没有真正动过手,那你将来对线上的性能优化也就无从谈起了。

 

总的来说,看这些经典书不失为一个办法,但考量时间的花费和对工作问题的精准处理,我感觉效率比较低。所以鉴于此,我决定输出一些内容,也就有了这本书的问世。

 

创作思路

 

虽然底层的知识如此重要,但这类知识有个共同的特点就是很枯燥。那如何才能把枯燥的底层讲好呢?这个问题我思考过很多很多次。

 

商品简介

《深入理解Linux网络: 修炼底层内功,掌握高性能原理》通过先抛出一些开发、运维等技术人员在工作中经常遇见的问题,激发读者的思考。从这些问题出发,深入地对网络底层实现原理进行拆解,带领读者看清楚问题的核心,理解其背后的技术本质,提高大家的技术功力。例如网络包是如何被接收和发送的?阻塞到底在内部是如何发生的?epoll的底层工作原理又是啥?TCP连接在底层上是如何支持和实现的?书中对这些内容都有深度的阐述。本书旨在通过带领读者修炼底层内功,进而帮助大家深度掌握网络高性能原理。



作者简介

 
 

  
    作者介绍 
  
 

张彦飞,2010年硕士毕业于西北大学计算机学院,有十多年的大型互联网公司项目经验,目前就职于腾讯。他喜欢对技术进行深度思考,善于挖掘技术点背后的原理。他的技术公众号“开发内功修炼”一年便收到五万多读者的关注。
 


目录

 
 

  
    目录 
  
 

第1章 绪论   / 1 

 1.1 我在工作中的困惑   / 2 

 1.1.1 过多的TIME_WAIT   / 2 

 1.1.2 长连接开销   / 2 

 1.1.3 CPU被消耗光了   / 3 

 1.1.4 为什么不同的语言网络性能差别巨大   / 4 

 1.1.5 访问127.0.0.1过网卡吗   / 4 

 1.1.6 软中断和硬中断   / 5 

 1.1.7 零拷贝到底是怎么回事   / 5 

 1.1.8 DPDK   / 5 

 1.2 本书内容结构   / 6 

 1.3 一些约定   / 7 

 1.4 一些术语   / 8 

 第2章 内核是如何接收网络包的   / 9 

 2.1 相关实际问题   / 10 

 2.2 数据是如何从网卡到协议栈的   / 11 

 2.2.1 Linux网络收包总览   / 12 

 2.2.2 Linux启动   / 13 

 2.2.3 迎接数据的到来   / 23 

 2.2.4 收包小结   / 33 

 2.3 本章总结   / 34 

 第3章 内核是如何与用户进程协作的   / 41 

 3.1 相关实际问题   / 42 

 3.2 socket的直接创建   / 43 

 3.3 内核和用户进程协作之阻塞方式   / 46 

 3.3.1 等待接收消息   / 47 

 3.3.2 软中断模块   / 52 

 3.3.3 同步阻塞总结   / 57 

 3.4 内核和用户进程协作之epoll   / 59 

 3.4.1 epoll内核对象的创建   / 60 

 3.4.2 为epoll添加socket   / 62 

 3.4.3 epoll_wait之等待接收   / 68 

 3.4.4 数据来了   / 71 

 3.4.5 小结   / 79 

 3.5 本章总结   / 80 

 第4章 内核是如何发送网络包的   / 84 

 4.1 相关实际问题   / 85 

 4.2 网络包发送过程总览   / 86 

 4.3 网卡启动准备   / 90 

 4.4 数据从用户进程到网卡的详细过程   / 92 

 4.4.1 send系统调用实现   / 92 

 4.4.2 传输层处理   / 94 

 4.4.3 网络层发送处理   / 99 

 4.4.4 邻居子系统   / 103 

 4.4.5 网络设备子系统   / 105 

 4.4.6 软中断调度   / 109 

 4.4.7 igb网卡驱动发送   / 111 

 4.5 RingBuffer内存回收   / 114 

 4.6 本章总结   / 115 

 第5章 深度理解本机网络IO   / 119 

 5.1 相关实际问题   / 120 

 5.2 跨机网络通信过程   / 120 

 5.2.1 跨机数据发送   / 120 

 5.2.2 跨机数据接收   / 125 

 5.2.3 跨机网络通信汇总   / 127 

 5.3 本机发送过程   / 127 

 5.3.1 网络层路由   / 127 

 5.3.2 本机IP路由   / 130 

 5.3.3 网络设备子系统   / 131 

 5.3.4 “驱动”程序   / 133 

 5.4 本机接收过程   / 135 

 5.5 本章总结   / 137 

 第6章 深度理解TCP连接建立过程   / 139 

 6.1 相关实际问题   / 140 

 6.2 深入理解listen   / 141 

 6.2.1 listen系统调用   / 141 

 6.2.2 协议栈listen   / 142 

 6.2.3 接收队列定义   / 143 

 6.2.4 接收队列申请和初始化   / 145 

 6.2.5 半连接队列长度计算   / 146 

 6.2.6 listen过程小结   / 148 

 6.3 深入理解connect   / 148 

 6.3.1 connect调用链展开   / 149 

 6.3.2 选择可用端口   / 151 

 6.3.3 端口被使用过怎么办   / 153 

 6.3.4 发起syn请求   / 155 

 6.3.5 connect小结   / 156 

 6.4 完整TCP连接建立过程   / 157 

 6.4.1 客户端connect   / 159 

 6.4.2 服务端响应SYN   / 160 

 6.4.3 客户端响应SYNACK   / 162 

 6.4.4 服务端响应ACK   / 164 

 6.4.5 服务端accept   / 167 

 6.4.6 连接建立过程总结   / 167 

 6.5 异常TCP连接建立情况   / 169 

 6.5.1 connect系统调用耗时失控   / 169 

 6.5.2 **次握手丢包   / 171 

 6.5.3 第三次握手丢包   / 176 

 6.5.4 握手异常总结   / 178 

 6.6 如何查看是否有连接队列溢出发生   / 179 

 6.6.1 全连接队列溢出判断   / 179 

 6.6.2 半连接队列溢出判断   / 181 

 6.6.3 小结   / 183 

 6.7 本章总结   / 183 

 第7章 一条TCP连接消耗多大内存   / 187 

 7.1 相关实际问题   / 188 

 7.2 Linux内核如何管理内存   / 188 

 7.2.1 node划分   / 189 

 7.2.2 zone划分   / 191 

 7.2.3 基于伙伴系统管理空闲页面   / 192 

 7.2.4 slab分配器   / 194 

 7.2.5 小结   / 197 

 7.3 TCP连接相关内核对象   / 198 

 7.3.1 socket函数直接创建   / 198 

 7.3.2 服务端socket创建   / 206 

 7.4 实测TCP内核对象开销   / 207 

 7.4.1 实验准备   / 207 

 7.4.2 实验开始   / 208 

 7.4.3 观察ESTABLISH状态开销   / 209 

 7.4.4 观察非ESTABLISH状态开销   / 211 

 7.4.5 收发缓存区简单测试   / 214 

 7.4.6 实验结果小结   / 215 

 7.5 本章总结   / 216 

 第8章 一台机器*多能支持多少条TCP连接   / 218 

 8.1 相关实际问题   / 219 

 8.2 理解Linux*大文件描述符限制

—  没有更多了  —

以下为对购买帮助不大的评价

此功能需要访问孔网APP才能使用
暂时不用
打开孔网APP