盘点 2021 | 技术十年 - 记录十年技术经历
大家好,我是雨乐。
毕业十年有余,一直从事后端工作,做过网络传输项目,曾经负责推荐引擎,目前负责广告投放引擎和广告结算引擎。主要使用语言是 c/c++,python 和 shell 作为辅助开发。
欢迎沟通交流,一起进步。
写在前面
在某一天的某一个时候,突然意识到,自己已经毕业工作十年了,是该写篇东西,来记录下自己的十年,算是给自己一个心理的慰藉,亦算是给自己入职场以来,第一个十年的总结。
大学生活
我是 03 年上的大学,上大学之前,完全没有接触过计算机。大学报志愿也是懵懵懂懂,那个时候,最火的两个专业,一是计算机,一是生物工程。电视上经常说的已经话就是:21 世纪,是生物科学的世纪。而我呢,因为没有摸过电脑,所以比较好奇,就在填报志愿的时候,写上了对于现在来说最内卷的一个行业专业:计算机科学与技术。
于是乎,在 9 月份的某一天,坐着穿越近半个中国的火车,来到了北方某个城市,开始了所谓的大学生活。现在还清楚的记得,第一次上机课,在机房打开电脑,双击点开网上邻居,输入网址,听的第一首歌,就是刘若英的“很爱很爱你”,以至于很多年以后,每次听到这首歌熟悉的旋律,都会回忆起自己大一的第一次上机课的情景。
那个时候,刚刚脱离了压抑的高中生活,就像长了翅膀的鸟儿,自由自在的翱翔在空中,秉持着“六十分万岁,多一分浪费”的学习心态,得过且过,基础课和专业课都均分通过,也算是没留丁点遗憾把。
就这样,度过了大一的懵懂,大二的彷徨,大三的沉沦,直至大三下的时候,才开始考虑自己的未来,跟随自己的内心,选择了考研。
研究生生活
慕名来到了以学习刻苦出名的华东某校,开始了自己的内卷生活。吃了不少专业课的苦,也算是对自己本科期间的一个惩戒。每天的三点点一线生活,宿舍、食堂、图书馆,开始了自己专业技术的学习。买的第一步编程方面的书,就是 c++ primer,在图书馆借阅了 c++大学教程,开始学习编程,随着对专业书籍的广泛接触,开始更加深入的去了解底层原理,c++模型深度探索,effective c++,more effective c++,c++沉思录等等,好多书都是在那个时候开始接触,也算是给自己后面进入本行业,打下了坚实的基础。
实习生活
那个时候,对自己就业开始有了危机感,周围的同学都拿到了阿里云、讯飞等公司的实习 offer。终于,自己在快要崩溃的时候,拿到了中科院某所的实习 offer,记得同宿舍哥们的第一句话就是:恭喜你,多年的媳妇熬成婆。
来到了北京,住在了所里安排的宿舍,跟着 mentor 做一个国家 863 项目,ddos 攻击相关的。因为是实习生,所以接触的是一些优化类的,比如内存池等。
在所里实习的同时,自己开始接触 csdn 网站,除了项目,就是整天泡在 c++版块回答问题,当初的积分很高,排名也很不错,不过因为其他原因,工作后,也不再登录该论坛了,算是一个不小的遗憾吧,在里面还是能学到不少东西,犹记里面有个技术很牛的群(音译 饼子堂),自己有幸也加入了,后面还是退出了。
随着所里项目的终结,选择去了另外一个大外企实习,该企业在西二旗(大家应该能猜出来是哪家吧),项目组是做一整套 Linux 下的办公系统,类似于 Windows 下的 word,基于 openoffice 来做的。整个项目百万行,光编译就得两三个小时,自己在里面负责解决内存泄漏,在此需要提的是,当时的 mentor 是个大牛,基本上整个公司的难题都会去找他,使得自己对技术的理解更加深入。
初入职场
进入传统行业
第一家公司,是个传统行业,有幸进入了公司技术最厉害的技术研究院,做网络相关的研发工作,也就是在这家公司,开始了研究 TCP,把 TCP/IP 详解看了一遍又一遍,不懂的就去查资料,甚至把源码下载下来进行分析研究。也是在这家公司,第一次接触 Linux 系统。
由于公司的业务面向的是国企,主要运行在 Windows 系统,第一要求就是稳定,所以更新迭代很慢,有时候一个功能几年都没进行优化。后面随着 Linux 系统在国内用的越来越多,部门的业务也需要运行在 Linux 系统上,当时有两个选择,一个是重新在 Linux 系统上写一份代码,一个就是现有的代码可以完全移植到 Linux 系统,即同一份代码可以在 Windows 和 Linux 两大系统,最终为了效率,还是选择了第二种方案。
大家都知道,虽然 c++是跨平台的语言,但是 API 名称,以及底层实现却是依赖于系统的,就比如 WaitForSingleObject 函数,在 Linux gcc 下就是 std::lock,这就要求同一个函数,比如 WaitForSingleObject,在 Windows 下使用的系统自带 API,而在 Linux 下是重新开发的一个函数,其功能与 Windows 下类似。当初这块是我来负责完成的,第一次出现了 coredump,第一次使用 gdb 进行调试。
入职互联网
那几年,正式互联网行业开始火的时候,自己内心也蠢蠢欲动,于是几经坎坷,进入了一家互联网行业,也算是自己第一次接触互联网。
刚入职的时候,确实很不习惯里面的快节奏,经常一个需求从提出到上线就几天,这在之前的传统行业是万万不可能的,第一次上线就导致线上服务 coredump,饭吃一半就跑上去解决。。。,在这家公司学到很多,对业务越来越熟练,开始负责整个推荐引擎,为后面接触广告奠定了基础。
接触广告
由于公司的业务发展遇到了瓶颈,再加上其他一些原因,又开始看机会。由于推荐引擎和广告引擎无论在架构上还是功能上都很类似(index->filter->rank 等等)。所以有幸进入了广告行业。
在这家公司,对我的影响很大,如果说上一家公司给了我进入互联网的机会,那么在这家公司,我开始了思考,怎样能让服务性能更优,怎样在系统设计上更加具有前瞻性,也算是逐步接触架构,开始从架构去了解整个业务,又从业务去反推架构的合理性。
众所周知,广告对 rt(Response Time)要求很高,rt 每增加几毫秒,广告展示折算率就会变大,所以对于每天请求百亿次的服务来说,对业务处理性能非常高,某一个子服务的性能都会影响整个广告链路。比如:
广告候选集过大,导致处理时间变长
某块代码耗 CPU 过高
传输链上无用参数过多
其它
记忆比较深刻的,实现了一个 DMP 服务,因为性能原因,所有的操作都在内存里面进行。里面用到了大量的内存分配以及释放,上线后,发现了一个现象,就是内存利用率一直很高。从表面现象看,就是内存没有被释放,即使程序显示调用了 delete 或者 clear,其内存占用仍然居高不上。为了解决这个问题,用了各种内存检测工具,加上了日志(申请内存和释放内存都加上),发现仍然没有问题,于是就去调研底层库,去研究内存分配的原理,通过研究源码,调研 new 和或者 malloc 的原因,最终发现,在底层 API 中,即使调用了 delete 或者 free,内存都不会被立即释放给操作系统,而是被放在缓冲区中(这就是内存占用比较高的原因),等间隔一段时间,才会被操作系统回收,如果想立即被操作系统回收,需要 malloc_trim(0)。
还是同一个 DMP 服务,由于其内存占用过大,导致性能不是很高,大量的 Misscache,最终,通过将系统中 page 大小从默认的 4k 变为 32k,解决了这个问题(这是因为 page 过小的话,导致大量的缺页中断,具体可参考<深入理解操作系统>)。
编程能力
作为程序员,编程能力是我们的立身之本,就我自己的感受而言,我觉得编程能力的成长主要有这么几个部分。
初级
初级编程能力,就是 「会用」。也就是说 使用各种系统 API,能够达到我们的目的就行。
编程,首先是从学习该门语言的语法开始的,比如 if/else while 等,作为初级程序员,建议在入门的时候,使用入门级别的书,而不是去看一些比较高阶的书。(对于 c++而言,<c++ primer>并不适合入门级的读者去看,反而适合有一定 c++基础知识的人去阅读,这本书的名字起的太具有诱惑性)。
除了看文档以外,编程是个超级实践的活,所以一定要多写代码,只有这样才能真正熟练起来,有句话"无他,唯手熟尔",很适合入门级程序员。作为入门级程序员,尽量不要使用 IDE,这种会使得对 IDE 具有依赖性,导致手写很难,希望尽量做到所有的 API 名称都能敲出来,久而久之,就会越来越熟练。
在初级阶段,核心就是多写,勤学苦练,这个很重要,只有这样才能为以后奠定扎实基础。
中级
初级的目标是能够熟练使用编程语言实现功能,中级的的目标就是提升 「分析和解决问题的能力」。
作为程序员,写代码过程中出问题是非常正常的,而怎样去有效且高效的排查问题,这是个体程序员之间编程能力上最大的差距,解决问题能力强,那么很容易受到上级乃至其他部门同事的认可。
在查问题的能力上,首先要掌握的是一些基本的调试技巧,好用的调试工具,比如常用的 gdb,gperf,btrace 等。熟练掌握调试工具,对解决问题非常有利。有些时候大家在查问题时的能力差距,有可能仅仅是因为别人比你多知道一个工具而已,除了调试技巧和工具外,查问题的更高境界会和编程能力的高级阶段有非常大的关系,就是懂原理,一个懂原理的程序员在查问题的水平上是有明显差距的。多尝试给自己写一些会出问题的程序,多积极的看别人是怎么查问题的,多积极的去参与排查问题,很多最后查问题能力强的人多数仅仅是因为“无他,但手熟尔”。
除了查问题外,更厉害的程序员是在写代码的过程就会很好的去避免问题,他们会知道在这块怎样做才不会入坑,在这块会出现怎样的问题,需要加什么样的条件或者日志等。
在中级阶段,建议大家去主动分析和解决问题,成为一个能写出高质量代码、有效排查问题的优秀程序员。
高级
对于高级编程能力的程序员来说,一个标准就是 「懂的底层 API 的实现原理」,知其然,知其所以然。
在学习底层实现以及排查问题的过程中,越来越明白懂编程语言的运行原理是非常重要的。学习底层实现最直接的去看源码,但这对很多人来说很难,所以可以尝试着从文档或者一些书籍入手(<STL 源码剖析>),一边看书,一边找到对应的源码去分析,这样就能达到事半功倍的效果。
有人说过,语言只是一种工具,解决和分析问题,不要局限于语言,我很同意这种说法。比如虽然 c++性能很优,但是其实现过程比较麻烦,会出现很多坑。对于一些猛操快的需求,比如分析线上日志,可以使用 python 或者 shell 去解决。
架构能力
随着写的代码越来越多,不经意间,在写代码的时候,开始考虑性能上是否最优,架构上是否合理,是否能够做到日后灵活扩展。
完全搭建一个系统,是在五年前,也就是工作五年的时候,那个时候入职了现在的公司。刚开始要做商业化,什么都没有,所有的都要从 0 开始搭建。比如一个流量来了,该如何去请求各个业务线,一个广告订单来了,如果能够快速的进入广告系统。那么就需要合理的进行模块分配。
随着代码写的越来越多,解决问题越来越多,越来越难,设计的模块越来越多,在潜移默化中,架构能力也就有了,在设计一个系统的时候,就开始有前瞻性,考虑解耦,考虑扩展。
架构能力并不是一朝一些就能学会的,更多的需要从实践中来,到实践中去,久而久之,这种能力就会得到提升。
心得
团队精神
在一个各项流程都完善的公司,需求评审、开发、测试、上线几个流程缺一不可,缺少每一个环节都可能导致线上故障,所以一个需求的完成,是需要各个部门通力合作的。
线上有了问题,大家一起努力将其解决,这就是成长的过程。
不要炫技
代码,是需要传承的。大家都不希望自己的代码被后面接手的人骂吧,所以代码一定要简洁、清晰、明了。不要为了炫耀某些技术实力,而故意使用晦涩难懂的编程技巧,相信过不了多久,不止是别人,即使是本人,也有可能看不懂这块代码。
合理架构
架构方案千千万,选择一个合适的最重要,不要为了架构而去架构,要考虑效率以及功能需求。
做到架构和开发效率双平衡,再向后展望,看看现有架构设计能否满足需求。
攻守兼备
所谓的攻,即进攻,也可以理解为攻城。即实现产品目标,满足功能需求;所有的守,即守卫,也可以理解为守城。即对于线上问题,能够守卫,快速解决。
正所谓攻城容易,守城难。线上 bug 永远解决不完,需要有耐心,需要有攻守兼备的能力。
代码审查
codereview 是必不可少的,这需要团队精神,可以在上线前期,解决不少问题。
但是也有弊端,这就是可能会导致大家有矛盾,比如有个功能实现,A 说这样实现,B 说那样性能更好,久而久之,就会导致团队之间出现矛盾。这就需要找一个平衡点,对于可有可无的意见,可以不提。。。
代码注释
❝
代码是最好的注释。这是终极目标,但很多人达不到,当然也包括我。所以代码中要尽可能多的注释,原因:
❞
为了自己以后维护
方便他人接手
尤其是对于功能复杂的函数,可以用 1、2、3 等点写出来,必要的时候,写在 cf 上,函数注释处加上 url 链接。
代码结构
代码结构一定要清晰,简洁明了,通过看函数说明就知道其功能,通过类名就能其要做什么。
代码结构表现出来的其实是程序的一个模块逻辑思想。结构简单清晰,也就能说明程序实现逻辑简单。
代码风格
程序员都是团队协作的,每个人都有自己不同的编程风格,如果没有一个统一的风格,整个代码将会很乱。
现在业界都用的谷歌代码规范,同样推荐给大家。
开发效率
c++程序员有个特点,就是不喜欢用 IDE,也算是他们的一种特有的骄傲吧,喜欢用 vim(我就是),所有的代码开发都用 vim 操作,显得比较有 B 格。
技术之外
❝
学如逆水行舟,不进则退。程序员,是一个不断自我学习,自我进步的过程,需要一直坚持学习,学习新知识,方能不被技术所淘汰。
❞
不忘初心,坚持到底
面试了太多人,这些人不乏名校毕业,履历光鲜,但都有个特点,就是转行,有些从技术转到产品,有些从技术转到测试,慢慢在本行业失去了竞争力。
技术是我们的根本,这个一定不能放弃,即使已经做到了管理层,也请尽可能多的接触代码。
目标、理想
理想是 dream,可以实现不了,但它是支撑内心丰盈的信念。只有有了理想,才能设立目标,否则目标就总是在变,内心也有很多焦虑。
与君共勉。
关注公众号【高性能架构探索】,后台回复【pdf】,免费获取计算机必备经典书籍
版权声明: 本文为 InfoQ 作者【高性能架构探索】的原创文章。
原文链接:【http://xie.infoq.cn/article/755c8068877610e660a473e5c】。文章转载请联系作者。
评论