date comments categories tags permalink title
2020/4/18
true
软件架构
架构
开源项目
5.42
如何高效学习开源项目

工作当中会经常使用到开源项目,例如nginx,redis,Netty等。对于开源项目,不能只知其然,还要知道其所以然。 这样做的目的,一方面是为了能够更好的运用开源项目,另一方面学习开源项目也是很好的提高自己能力的方法。

很多人其实都是想要学习开源项目的,但是在真正实践的过程中往往会误入各种各样的歧途,例如:

  • 只有开发这些开源项目的人才能真正理解,我没法参与这个项目开发,因此我很难深入理解。
  • 我的项目没有用 Redis,不用的话很难深入理解。
  • 数据结构和算法很重要,所以我只要研究其数据结构和算法就够了,例如 Nginx 用的红黑树。
  • “Talk is cheap, show me the code”,一头扎进源码逐行阅读。

建议使用下面的方法来学习开源项目

首先,需要树立正确的观念:不管你是什么身份,都可以从开源项目中学到很多东西

例如,要理解 Redis 的网络模型,我们不需要成为 Redis 的开发者,也不需要一定要用到 Redis,只要具备一定的网络编程基础,再通过阅读 Redis 的源码,都可以学习 Redis 这种单进程的 Reactor 模型。

其次,不要只盯着数据结构和算法,事实上这两点在学习开源项目的时候并没有那么重要

例如,Nginx 使用红黑树来管理定时器,对于绝大部分人来说,只要知道这点就够了,并不需要去研究 Nginx 实现红黑树的源码是如何写的,除非你需要修改这部分,但我认为极少人会有这个需求。

第三,采取“自顶向下”的学习方法,源码不是第一步,而是最后一步

不要一上来就去看源码,而是要基本掌握了功能、原理、关键设计之后再去看源码,看源码的主要目的是为了学习其代码的写作方式,以及关键技术的实现。例如,Redis 的 RDB 持久化模式“会将当前内存中的数据库快照保存到磁盘文件中”,那这里所谓的“数据库快照”到底是怎么做的呢?在 Linux 平台上其实就是 fork 一个子进程来保存就可以了;那为何 fork 子进程就生成了数据库快照了呢?这又和 Linux 的父子进程机制以及 copy-on-write 技术相关了。

通过这种方式,既能够快速掌握系统设计的关键点(Redis 的 RDB 模式),又能够掌握具体的编程技巧(内存快照)。

自顶向下学习的详细步骤

第一步 安装

很多人看到“安装”这个步骤都可能会觉得有点不以为然:“不就是对照手册执行一下命令么,没什么技术含量,用的时候装一下就可以了”。事实上,安装步骤远远不止这么简单,通过具体的安装过程,你可以获取到如下一些关键信息:

  • 这个系统的依赖组件,而依赖的组件是系统设计和实现的基础 以 Nginx 为例,源码安装 Nginx 依赖的库有 pcre、pcre-devel、openssl、openssl-devel、zlib,光从名字上看都能够了解一些信息,例如 openssl 可能和 https 有关,zlib 可能和压缩有关。

    再以 Memcache 为例,最大的依赖就是 libevent,而根据 libevent 是一个高性能的网络库,我们就能大概推测 Memcache 的网络实现应该是 Reactor 模型的。

  • 安装目录也能够提供一些使用和运行的基本信息

    例如,Nginx 安装完成后,目录如下:

nginx安装目录

这个目录提供的信息有:conf 是存放配置文件的,logs 是存放日志的,sbin 是运行程序,但是 html 是什么呢?这个疑问会促使你继续去研究和学习。

再来看看 Redis,安装完成后,目录下只有一个 bin 目录,具体如下:

Redis Bin目录

我相信大部分人看到这目录都会感到有点惊讶:这也太简单了吧,尤其是与 Nginx 相比!因此也会自然而然的有一些疑问,例如 Redis 如何配置?Redis 日志保存在哪里?这些疑问同样会促使你继续去研究和学习,带着问题去学习效率是最高的。

  • 系统提供了哪些工具方便我们使用 同样以 Redis 为例,你可以看到 redis-benchmark、redis-check-aof 等程序,从名字能够大概猜出这些工具的基本使用场景,而这些工具在后面故障定位和处理、性能测试等场景可能非常方便。

第二步 运行

安装完成后,我们需要真正将系统运行起来,运行系统的时候有两个地方要特别关注:命令行和配置文件,它们主要提供了两个非常关键的信息:系统具备哪些能力和系统将会如何运行。这些信息是我们窥视系统内部运行机制和原理的一扇窗口。例如,下面是 Memcache 的启动参数一部分:

Memcache参数

通过这几个启动参数,你可以获取如下一些信息:

  • Memcache 支持 UNIX socket 通信和 TCP 通信。
  • Memcache 可以指定内存大小。
  • lock memory 看起来和内存有关,但具体是什么意思?配置和不配置有什么区别么?

通常情况下,如果我们将每个命令行参数和配置项的作用和原理都全部掌握清楚了的话,基本上对系统已经很熟悉了。我的一个习惯是不管三七二十一,先把所有的配置项全部研究一遍,包括配置项的原理、作用、影响,并且尝试去修改配置项然后看看系统会有什么变化。例如,将 Memcache 的“–conn-limit”改为 1 后,查看多个连接请求时 Memecache 会返回什么错误、记录什么日志等。

第三步 研究原理

完成前两个步骤后,我们对系统已经有了初步的感觉和理解,此时可以更进一步去研究其原理。其实在研究命令行和配置项的时候已经涉及一部分原理了,但是还不系统,因此我们要专门针对原理进行系统性的研究。这里的关键就是“系统性”三个字,怎么才算系统性呢?主要体现在如下几个方面:

  • 关键特性的基本实现原理 每个流行的开源项目之所以能够受到大众的欢迎,肯定是有一些卖点的,常见的有高性能、高可用、可扩展等特性,那到底这些项目是如何做到其所宣称的那么牛的呢?这些牛 X 的技术实现就是我们要学习的地方。

    例如,Memcache 的高性能具体是怎么做到的呢?首先是基于 libevent 实现了高性能的网络模型,其次是内存管理 Slab Allocator 机制。为了彻底理解 Memcache 的高性能网络模型,我们需要掌握很多知识:多路复用、Linux epoll、Reactor 模型、多线程等,通过研究 Memcache 的高性能网络模型,我们能够学习一个具体的项目中如何将这些东西全部串起来实现了高性能。

    再以 React 为例,Virtual DOM 的实现原理是什么、为何要实现 Virtual DOM、React 是如何构建 Virtual DOM 树、Virtual DOM 与 DOM 什么关系等,通过研究学习 Virtual DOM,即使不使用 React,我们也能够学习如何写出高性能的前端的代码。

  • 优缺点对比

这是我想特别强调的一点,只有清楚掌握技术方案的优缺点后才算真正的掌握这门技术,也只有掌握了技术方案的优缺点后才能在架构设计的时候做出合理的选择

优缺点主要通过对比来分析,即:我们将两个类似的系统进行对比,看看它们的实现差异,以及不同的实现优缺点都是什么。

典型的对比有 Memcache 和 Redis,例如(仅举例说明,实际上对比的点很多),Memcache 用多线程,Redis 用单进程,各有什么优缺点?Memcache 和 Redis 的集群方式,各有什么优缺点?

即使是 Redis 自身,我们也可以对比 RDB 和 AOF 两种模式的优缺点。

在你了解了什么是“系统性”后,我来介绍一下原理研究的手段,主要有三种:

  • 通读项目的设计文档:例如 Kafka 的设计文档,基本涵盖了消息队列设计的关键决策部分;Disruptor 的设计白皮书,详细的阐述了 Java 单机高性能的设计技巧。
  • 阅读网上已有的分析文档:通常情况下比较热门的开源项目,都已经有非常多的分析文档了,我们可以站在前人的基础上,避免大量的重复投入。但需要注意的是,由于经验、水平、关注点等差异,不同的人分析的结论可能有差异,甚至有的是错误的,因此不能完全参照。一个比较好的方式就是多方对照,也就是说看很多篇分析文档,比较它们的内容共同点和差异点。
  • Demo 验证:如果有些技术点难以查到资料,自己又不确定,则可以真正去写 Demo 进行验证,通过打印一些日志或者调试,能清晰的理解具体的细节。例如,写一个简单的分配内存程序,然后通过日志和命令行(jmap、jstat、jstack 等)来查看 Java 虚拟机垃圾回收时的具体表现。

第四部 测试

通常情况下,如果你真的准备在实际项目中使用某个开源项目的话,必须进行测试。有的同学可能会说,网上的分析和测试文档很多,直接找一篇看就可以了?如果只是自己学习和研究,这样做是可以的,因为构建完整的测试用例既需要耗费较多时间,又需要较多机器资源,如果每个项目都这么做的话,投入成本有点大;但如果是要在实践项目中使用,必须自己进行测试,因为网上搜的测试结果,不一定与自己的业务场景很契合,如果简单参考别人的测试结果,很可能会得出错误的结论。例如,开源系统的版本不同,测试结果可能差异较大。同样是 K-V 存储,别人测试的 value 是 128 字节,而你的场景 value 都达到了 128k 字节,两者的测试结果也差异很大,不能简单照搬。

测试阶段需要特别强调的一点就是:测试一定要在原理研究之后做,不能安装完成立马就测试!原因在于如果对系统不熟悉,很可能出现命令行、配置参数没用对,或者运行模式选择不对,导致没有根据业务的特点搭建正确的环境、没有设计合理的测试用例,从而使得最终的测试结果得出了错误结论,误导了设计决策。曾经有团队安装完成 MySQL 5.1 后就进行性能测试,测试结果出来让人大跌眼镜,经过定位才发现 innodb_buffer_pool_size 使用的是默认值 8M。

第五步 源码研究

源码研究的主要目的是学习原理背后的具体编码如何实现,通过学习这些技巧来提升我们自己的技术能力。例如 Redis 的 RDB 快照、Nginx 的多 Reactor 模型、Disruptor 如何使用 volatile 以及 CAS 来做无锁设计、Netty 的 Zero-Copy 等,这些技巧都很精巧,掌握后能够大大提升自己的编码能力。

通常情况下,不建议通读所有源码,因为想掌握每行代码的含义和作用还是非常耗费时间的,尤其是 MySQL、Nginx 这种规模的项目,即使是他们的开发人员,都不一定每个人都掌握了所有代码。带着明确目的去研究源码,做到有的放矢,才能事半功倍,这也是源码研究要放在最后的原因。

对于一些基础库,除了阅读源码外,还可以自己写个 Demo 调用基础库完成一些简单的功能,然后通过调试来看具体的调用栈,通过调用栈来理解基础库的处理逻辑和过程,这比单纯看代码去理解逻辑要高效一些。例如,下面是 Netty 4.1 版本的 telnet 服务器样例调试的堆栈,通过堆栈我们可以看到完整的调用栈:

调用堆栈

时间分配

前面介绍的“自顶向下”5 个步骤,完整执行下来需要花费较长时间,而时间又是大部分技术人员比较稀缺的资源。很多人在学习技术的时候都会反馈说时间不够,版本进度很紧,很难有大量的时间进行学习,但如果不学习感觉自己又很难提升?面对这种两难问题,具体该如何做呢?

通常情况下,以上 5 个步骤的前 3 个步骤,不管是已经成为架构师的技术人员,还是立志成为架构师的技术人员,在研究开源项目的时候都必不可少;第四步可以在准备采用开源项目的时候才实施,第五步可以根据你的时间来进行灵活安排。这里的“灵活安排”不是说省略不去做,而是在自己有一定时间和精力的时候做,因为只有这样才能真正理解和学到具体的技术。

如果感觉自己时间和精力不够,与其蜻蜓点水每个开源项目都去简单了解一下,还不如集中精力将一个开源项目研究通透,就算是每个季度只学习一个开源项目,积累几年后这个数量也是很可观的;而且一旦你将一个项目研究透以后,再去研究其他类似项目,你会发现自己学习的非常快,因为共性的部分你已经都掌握了,只需要掌握新项目差异的部分即可。


http://www.taodudu.cc/news/show-2899416.html

相关文章:

  • 如何在项目中学习
  • Springboot 项目学习
  • Pdf自动增加页码
  • C#使用iTextSharp合并pdf,添加页码
  • PDF添加页码的工具有什么 PDF添加页码的小窍门
  • pdf工具类之添加页码
  • java pdf设置页码_Java 添加页码到PDF文档
  • 简单图文解释冯诺依曼体系结构(通俗易懂版)
  • 冯诺依曼计算机体系结构
  • [Linux]基本体系结构
  • GPU体系架构
  • 网络体系结构
  • 通俗解释乔姆斯基文法体系
  • Hadoop的体系结构
  • java的体系结构_java体系结构介绍
  • 软件体系结构(三)名词解释
  • Storm体系结构和概念解释
  • 计算机体系结构——名词解释
  • 项目初期如何确定项目的进度计划和资源需求?
  • 「项目进度管理」如何编制有效的进度计划?
  • 瞬时速度信号分析
  • 刚体的瞬时螺旋运动
  • 瞬时带宽简略
  • 瞬时频率函数matlab,瞬时频率估计的相位建模法及Matlab的实现
  • 【Java常用类】Instant:瞬时
  • 瞬时转速 matlab,基于瞬时转速的发动机故障诊断研究
  • 瞬时测频接收机matlab_瞬时测频接收机
  • 希尔伯特谱、边际谱、包络谱、瞬时频率/幅值/相位——Hilbert分析衍生方法及MATLAB实现
  • Prometheus:Java调用PromQL工具类(瞬时数据查询)
  • dq坐标系下无功功率表达式_基于瞬时电流分解的谐波电流检测方法研究

5.42如何高效的学习开源项目相关推荐

  1. 如何高效地学习开源项目 |“华仔,放学别走”

    你好,我是华仔.今天这期"特别放送",我想和你聊聊如何高效地学习开源项目,一方面澄清开源项目学习过程中的几个误区,另一方面谈谈我自己具体实践时的一套方法论. 得益于开源运动的蓬勃发 ...

  2. 如何高效地学习开源项目

    转载于:https://time.geekbang.org/column/article/10022 你好,我是华仔.今天这期"特别放送",我想和你聊聊如何高效地学习开源项目,一方 ...

  3. 如何高效地学习开源项目-以ShardingSphere学习为例

    在今年的上旬,有幸学习了李运华老师的<从0开始学架构>,碰巧最近参加技术群组织的ShardingSphere的源码的分享小组.所以想结合运华老师的学习方法结合我在项目中的经历复盘一下当时我 ...

  4. 谈谈如何高效学习开源项目

    谈谈如何高效学习开源项目 本文首发于51CTO技术栈公众号 作者 陈彩华 文章转载交流请联系 caison@aliyun.com 随着蓬勃发展的开源时代的到来,为了减少开发成本,提高开发效率,越来越多 ...

  5. 学习开源项目Halo(1) - 初步了解与运行Halo

    文章目录 学习开源项目Halo(1) - 初步了解与运行Halo 0.前言 1.Halo简介 2.Halo项目运行 3.Halo项目涉及到的技术栈 学习开源项目Halo(1) - 初步了解与运行Hal ...

  6. 如何更加安全、高效地利用开源项目?

    GitChat 作者:周猛 原文: 如何更加安全.高效地利用开源项目? 关注微信公众号:「GitChat 技术杂谈」 一本正经的讲技术 [不要错过文末彩蛋] 在平时的开发过程中,难免会遇到这样那样的难 ...

  7. 一周焦点 | 李彦宏:如果谷歌回来,有信心再赢一次;GitHub深度学习开源项目Top200...

    ▌业界焦点 瞄准超算皇冠:神威E级超算原型机正式启用 运算速度达每秒百亿亿次的 E 级计算机,被称作"超级计算机界的下一顶皇冠".8 月 5 日,国产超算研制向着这一皇冠又迈进了一 ...

  8. 《开源思索集》一如何更有效地学习开源项目的代码?

    本节书摘来异步社区<开源思索集>一书中的第2章,第2.1节,作者: 庄表伟 责编: 杨海玲, 更多章节内容可以访问云栖社区"异步社区"公众号查看. 如何更有效地学习开源 ...

  9. 如何学习开源项目及Ceph的浅析

    摘要:开源技术的学习和采用确实存在着一定门槛,然而学习各种开源项目已经成为许多开发者不可回避的工作内容.那么,对于类似OpenStack的大型开源项目,开发者该如何着手,这里我们看章宇的分享. [编者 ...

最新文章

  1. 通过正则表达式查找一个模式的所有实例
  2. 【cocos2d-x 手游研发小技巧(3)Android界面分辨率适配方案】
  3. android CMake开发
  4. 你也能与AlphaGo谈笑风生:AlphaGo教学工具上线,2万多变化,37万多步棋
  5. python startswitch_python学习第四天
  6. 单元测试之—JUnit与SpringTest的完美结合
  7. 基于sklearn的LogisticRegression二分类实践
  8. 取磁碟名稱 c++_安徽CDCSCONT PLUS/R/C/E生产厂家,联锁板生产厂家
  9. 一文看懂机器视觉工业相机与普通相机的区别
  10. 工厂模式的思想主要为
  11. 监督学习、无监督学习、半监督学习、弱监督学习、强化学习
  12. 编程实现英语句子反转python_Python字符串处理实现单词反转
  13. Excel做曲线拟合
  14. 串口接反会不会烧IO
  15. 我和数据类型抗争的血泪史(二十五分钟)
  16. 如何为Win10开启DoH(DNS over HTTPS)
  17. linux 对称加密命令,linux安全和加密篇(三)—openssl工具和CA证书
  18. 华为日历登录qq邮箱的解决方案
  19. 利用STM32CubeMX来设置精确到微妙(us)的定时器
  20. 英语dyamaund钻石

热门文章

  1. Phpcms黄页yp如何添加企业模板
  2. {ResponseInfo:com.qiniu.http.Response@62bd765,status:400, reqId:d4kAAACMt2hWMSEW, xlog:X-Log, xvia:,
  3. 仿迅雷播放器遇到的字符串处理函数
  4. 牵手中关村,这里脱胎换骨引凤来
  5. 一首经典的情歌 - 天涯歌女
  6. 怎么将mov格式的视频转换成MP4?
  7. 工业相机及镜头的选型
  8. 史记十表-卷十六-秦楚之际月表第四
  9. ​LeetCode刷题实战371:两整数之和
  10. opencv_contrib安装笔记