给团队内的年轻人灌了一大碗鸡汤

团队来了不少年轻人,水平却参差不齐,有些干了好几个年头还不知道什么是 进程间通信IPC )。

最近突发奇想,准备搞一搞技术分享,带他们阅读一些经典的技术书。《Unix环境高级编程》是后端必读书目,我问了一圈竟无一人读过,因而被我选中。学习模式大致是这样的:大家轮流学习某个知识点,然后讲给其他人听,每周一次。

第一次我原本准备亲自讲,给他们吹吹水,灌灌鸡汤。无奈这周身体抱恙,有点小感冒讲话不方便,遂写成文字分享给他们,乃有此篇。

技术视野

有本叫《性能之巅》的技术书很出名,作者在前言中引用美国国防部长拉姆斯菲尔德说的一句话,很有意思。他说世界上的事物可以分为三种:

  • A 已知的已知 ,比如我会 Go 语言;
  • B 已知的未知 ,比如我知道有一门语言 Rust 最近很火,但我不会;
  • C 未知的未知 ,……

年轻时,只要学会了一丁点技术,就沾沾自喜,以为老子天下第一;历经岁月蹉跎后,才发现原来自己掌握的只是皮毛,学得越多不知道的也越多,永远没有止境!如果总是浅尝辄止,对未知世界没有好奇心,最终可能要沦为井底之蛙。

那么,怎么开拓自己的技术视野,避免沦为井底之蛙呢?其实很简单,我们只需做好两件事情:

  • 制定学习计划,将 B 变成 A
  • 拓宽知识渠道,广泛涉猎,将 C 变成 B 甚至变成 A
    • 读读书
    • 看看博客
    • 参加技术交流
    • etc

当前水平

你可能会有疑问,虽然自己在技术上还有很多盲区,但也足以胜任现在的工作,盲区也就无所谓了吧?但你有没有想过,自己做的东西大概是什么水平呢?

我们团队目前做的东西,从技术角度看,大概只有 本科生课程设计 这样的水平,甚至还达不到。为什么呢?

  • 绝大部分工作都是常规 CURD 操作,没有特别的技术挑战;
  • 数据规模很小小,工程实现方面也没有任何难度;
  • 产品不是核心系统,公司对稳定性、安全性、用户体验等要求极低;

举个例子,我们的系统主要面向公司内部用户,使用频率不高,有些场景半年的数据量也就 3000 左右;而我当年在网易游戏落地的监控系统,一天的数据量就超过 40 亿!两者相差 100 万倍!想设计数据密集型系统,在数据库技术方面没有两下子肯定是不行的。

那么,我在一个比较舒服的环境,是不是就可以选择安逸了呢?

显然不是。古人云,“生于忧患,死于安乐”,又云“天下虽安,忘战必危”。

在安逸的环境容易温水煮青蛙,这是你我都要警惕的。万一未来项目做大,然后遇到比较棘手的挑战呢?我们准备好了吗?还是只能临时抱佛脚?感叹书到用时方恨少?

人贵有自知之明,能认识到自己的不足,才能为未来的挑战做好准备。

工程挑战

那么,一个工业级的产品,技术上会遇到哪些挑战呢?这简直太多了,我只能列举几个例子:

稳定性

你的系统是否能够保证 $7\times24$ 小时不间断提供服务呢?理想是美好的,但现实是骨感的:没有任何一个软件系统可以达到 100% 稳定,我们只能追求 N 个九。

N个九 正常服务时间百分比 一年可停机时间
四个九 99.99% 52分钟
五个九 99.999% 5.2分钟
六个九 99.9999% 31秒

如果我有个系统数据库故障了,需要从备份中恢复数据,恢复时长可能要几十分钟,那么它可能就跟上面这几个九都无缘了。另一方面,从历史备份恢复数据意味着最近的新数据丢失了!

因此,要保证一个系统的稳定性,工程上的挑战有多大可想而知。

性能

我们在做的系统,每秒请求数( QPS )有多少?——看接口日志,大概在 10 以内。那并发数有多少呢?——大概也是在 10 以内。这么低的请求压力,基本只要将需求翻译成代码就能撑住,技术上没有任何挑战。

如果是面向海量用户的系统,请求压力会有多大呢?技术挑战会有多大呢?如果你的系统面向亿万数量级的用户请求,应该采用什么技术手段来支撑呢?

举个例子,早年间我在网易游戏开发监控系统,监控线上超过 3 万服务器。控制模块必须支撑每台服务器连上来的长连接,总共超过 3 万个。

当时采用 Python 技术栈,在高并发网络处理领域是短板。调研过一些开源的类库,单进程只能支撑一两百个连接。没办法只能自己封装类库,单进程可支撑的连接数提高到 2000 以上。再配合 多进程多机部署 技术,成功支撑 3 万长连接。

当然了,这个数字其实也受限于 Python 的短板,采用比如 Golang 技术栈应该可以轻松做得更好。但话说回来,如果不懂网络编程,不具备网络类库开发能力,情况一定更糟!

另一个挑战是监控时序数据存储,线上 3 万台服务器每分钟都会定期上报大量的指标数据。当时我们测算过,每台服务器每次要上报大概 1000 个指标值,3 万台服务器就是 3 千万,平均每秒钟要写入 50 万个数值!

如果数据库应用不当,写入速度跟不上,数据堆积压垮消息队列,最后就是奔溃……因此,我们对写库逻辑进行了大量优化:

首先,将指标数据分门别类后合并存储。举个例子,内存指标数据可以分为一类,只写一次,这样数据库写操作的次数就可以大大降低——降到每秒写入 5 万个文档左右。

5 万每秒挑战依然不小,我们又采用 MongoDB 分片集群进行水平扩展,还采用数据冷热分离等手段进行优化,才撑住了写入压力。

这就是工业级应用对性能的要求,如果写出来的程序性能不行,那也是枉然。而想要追求极致的性能,扎实的计算机基本功是少不了的:

  • 计算机组成原理(CPU架构、缓存优化)
  • 操作系统(多进程、多线程)
  • 分布式原理(多机部署、高可用架构、水平扩展)
  • 数据库(索引技术、调优)
  • etc

安全性

我们公司有很多从其他下三滥厂商买来的垃圾系统,用的技术栈都老旧不堪,有些不知道埋了多少雷在里面。有个系统肉眼都能看出很可能有 XSS 攻击隐患,有一天我好奇的试了一下,果然!

我在那个系统上面发了一个评论,内容如下:

1
2
3
<script>
  window.alert('XXXX is SB');
</script>

那个系统没有做前后端分离,渲染前端 html 模板时也没做转义,结果相当于我在 html 里面插入了一段 JS 代码!所以每个看到我评论的人,网页都会弹框输出 XXXX is SB 。还好我只是恶作剧,如果我是一个黑客,插入代码调用某个敏感接口呢?

今时今日,很难想象还有软件厂商会踩 XSS 的坑,带有 XSS 致命漏洞的产品居然还能卖得出去!只能说不懂技术就容易被忽悠,这里面的水也比较深。哎呀,扯远了……

遥想当年刚毕业入职网易游戏,部门安排了好多技术培训,其中有一个就是 Web 开发培训。培训上就重点讲解了常见的安全问题的来龙去脉,包括:

  • SQL 注入
  • XSS 攻击
  • CSRF 攻击
  • etc

培训后还留了一个小作业,老师给了一个带有安全漏洞的 Web 站点,要求我们找出这些漏洞进行攻击,还要制定漏洞修复方案。最后还有一个迷你项目——从零实现一个线上商城,如果作品带有这些安全隐患就直接劝退……

通过培训,每个新人对安全问题都形成条件反射,这也是大厂的基本要求。虽然我们现在的公司是传统行业,不少领导不懂技术要求也低。但我们对技术还是要时刻保持敏感,因为我们是做技术的,这是我们的 核心竞争力

学习

那问题又来了,后端工程师都应该学习哪些核心技能呢?又该如何入手呢?

其实,后端工程师的必备技能,无非就是本科计算机专业那几门基础课:

  • 编程语言( C 语言)
  • 数据结构与算法
  • 计算机组成原理
  • 操作系统
  • 计算机网络协议
  • 数据库

你可能觉得这些课程很枯燥乏味,当初怎么学也学不会,甚至不知道学了有什么用。你如果大学专业都不是计算机相关的,没接触过这些可能,就更加一点概念都没有。不管怎样,还是要花精力打好这些基本功,对提升技术水平大有裨益。

可为啥这些课都那么枯燥呢?

其实,你可能是被一些杂七杂八的烂教材给坑了……垃圾教材不仅表达生硬,缺少铺垫,甚至复制粘贴拼凑字数,错漏百出。如果看这样的教材,你能学好吗?

课程没学好有时还真不是你的锅,而怪垃圾教材——它不仅没将知识讲明白,还打击你的自信心,消磨你的兴趣,简直就是罪魁祸首!

因此,建议选一些国外的 经典教材 来看,如果有英文阅读能力直接上原版。再配个 有道翻译笔 ,简直巴适!

技术分享

学习是孤独的,有时需要团队的力量来战胜个人的惰性。团队组织技术分享,可以促进技术氛围,让所有人受益。

我刚参加工作时在网易游戏,有幸跟着一位对技术很有追求的领导,我们都叫他“教主”。当时我们团队只有四个人,主要是做一些运维类的内部系统,技术栈主要是 Python 后端方向。

我们四个人是教主招的第一批人,入职后他就在团队内组织技术分享,定了四个课题:

  • Python 源码剖析;
  • Linux 内核;
  • 网络协议;
  • MySQL

现在回过头来看,这四个课题教主选得颇为讲究,由衷佩服:

  • Python 为我们的主力编程语言,研究源码是为了更好地认识手中的工具;
  • Linux 是最流行的服务端操作系统,掌握它的设计原理对写好后端服务至关重要;
  • 网络协议和网络编程技术也是分布式系统中绕不开的一环;
  • MySQL 是我们的主流数据库,了解数据库内部原理有利于将其用好用溜!

不得不说,参加这些技术分享,受益匪浅!特别是自己讲的那部分!

以我负责 Python 源码部分为例,为了分享我系统看了 Python 的大部分源码,对它的内部设计基本烂熟于胸。写代码时,脑海自发推演 Python 内部的执行过程,权衡代码怎么写比较优雅高效,几乎形成了条件反射。

看书若看不细致,以为自己懂了,但其实可能没懂。但如果要将自己学到的知识讲给别人听就不同了:每个知识点你都必须理解到位,烂熟于胸之后,才有可能将别人教明白。这就是技术分享的好处。

去年,我将阅读 Python 源码的一些心得体会,整理成一个技术专栏,发表在慕课网上。截至今天,总共卖了两千份左右。现在还陆陆续续有新读者订阅,每月多了一笔零花钱。这也是教主组织技术分享带来的缘分,哈哈。

良师益友

有句老话说的好,“近朱者赤,近墨者黑”。

人类是群居动物,我们免不了要跟周围的人交流,被他们影响。如果你周围的人都是吃饭睡觉,那你很可能也是吃饭睡觉;如果你周围的人都在研究新技术,那你很有可能也会感兴趣。可以毫不夸张地说,一人的圈子决定了他的一切。

举个例子,我大学有个大神级的同学,人称小虾。小虾很早就接触计算机,初三暑假就开始折腾着自己搞一个操作系统,非常入迷。大一时我们都忙着上课,他在宿舍给自己的操作系统加上图形界面。

有一次吃晚饭时,他说要帮朋友写个 Linux 内核模块来转发流量,回去要看看内核模块怎么写。第二天他告诉我们内核模块已经写完了,部署到朋友的服务器,效果很不错,还收了几千块钱。我们听得目瞪口呆,既崇拜又好奇。

在他的影响下,我们几个人对 LinuxC 语言、 Python 和网络编程技术方向产生兴趣,开始研究。我们一起写过网络代理工具,一起研究如何通过网络协议蹭网,还研究了如何刷票……只要好玩的东西,我们都折腾过,哈哈~

我们就这样一边玩乐折腾,技术基础自然就有了一些积累,最后几个人都拿到 BATOffer 。这就是榜样的力量!

  • 挖掘周边朋友的优点,学习之;
  • 识别周边朋友的缺点,警惕之;
  • 结识优秀的新朋友;
  • 与志同道合的人,干一些有趣的事;

订阅更新,获取更多学习资料,请关注我们的公众号:

【随笔】系列文章首发于公众号【小菜学编程】,敬请关注: