开源项目:如何选择、使用以及二次开发

张开发
2026/4/20 10:21:48 15 分钟阅读

分享文章

开源项目:如何选择、使用以及二次开发
软件开发领域有一个流行的原则DRYDon’t repeat yourself。翻译过来更通俗易懂不要重复造轮子。开源项目的主要目的是共享其实就是为了让大家不要重复造轮子然而现实往往没有那么美好开源项目虽然节省了大量的人力和时间但带来的问题也不少相信绝大部分技术人员都踩过开源软件的坑小的影响可能是宕机半小时大的问题可能是丢失几十万条数据甚至灾难性的事故是全部数据都丢失。除此以外虽然 DRY 原则摆在那里但实际上开源项目反而是最不遵守 DRY 原则的重复的轮子好多你有 MySQL我有 PostgreSQL你有 MongoDB我有 Cassandra你有 Memcached我有 Redis你有 Gson我有 Jackson你有 Angular我有 React……总之放眼望去其实相似的轮子很多架构需要更加聪明地选择和使用开源项目。形象点说不要重复发明轮子但要找到合适的轮子选如何选择一个开源项目1. 聚焦是否满足业务 架构师在选择开源项目时一个头疼的问题就是相似的开源项目较多而且后面的总是要宣称比前面的更加优秀。有的架构师在选择时有点无所适从总是会担心选择了 A 项目而错过了 B 项目。这个问题的解决方式是聚焦于是否满足业务而不需要过于关注开源项目是否优秀。Tokyo Tyrant 的教训 在开发一个社交类业务时我们使用了 TT(Tokyo Tyrant)开源项目觉得既能够做缓存取代 Memcached又有持久化存储功能还可以取代 MySQL觉得很强大于是就在业务里面大量使用了。但后来的使用过程让人很郁闷主要表现为不能完全取代 MySQL因此有两份存储设计时每次都要讨论和决策究竟什么数据放 MySQL什么数据放 TT。功能上看起来很高大上但相应的 bug 也不少而且有的 bug 是致命的。例如所有数据不可读后来是自己研究源码写了一个工具才恢复了部分数据。功能确实强大但需要花费较长时间熟悉各种细节不熟悉随便用很容易踩坑。简单来说如果你的业务要求 1000 TPS那么一个 20000 TPS 和 50000 TPS 的项目是没有区别的。有的架构师可能会担心 TPS 不断上涨怎么办其实不用过于担心架构是可以不断演进的等到真的需要这么高的时候再来架构重构这里的设计决策遵循架构设计原则中的“合适原则”和”演化原则”。2. 聚焦是否成熟 很多新的开源项目往往都会声称自己比以前的项目更加优秀性能更高、功能更强、引入更多新概念……看起来都很诱人但实际上都有意无意地隐藏了一个负面的问题更加不成熟不管多优秀的程序员写出来的项目都会有 bug千万不要以为作者历害就没有 bug Windows、Linux、MySQL 的开发者都是顶级的开发者系统一样有很多 bug。不成熟的开源项目应用到生产环境风险极大轻则宕机重则宕机后重启都恢复不了更严重的是数据丢失都找不回来。所以在选择开源项目时尽量选择成熟的开源项目降低风险。你可以从这几个方面考察开源项目是否成熟版本号除非特殊情况否则不要选 0.X 版本的至少选 1.X 版本的版本号越高越好。使用的公司数量一般开源项目都会把采用了自己项目的公司列在主页上公司越大越好数量越多越好。社区活跃度看看社区是否活跃发帖数、回复数、问题处理速度等。3. 聚焦运维能力 大部分架构师在选择开源项目时基本上都是聚焦于技术指标例如性能、可用性、功能这些评估点而几乎不会去关注运维方面的能力。但如果要将项目应用到线上生产环境则运维能力是必不可少的一环否则一旦出问题运维、研发、测试都只能干瞪眼求菩萨保佑了可以从这几个方面去考察运维能力开源项目日志是否齐全有的开源项目日志只有寥寥启动停止几行出了问题根本无法排查。开源项目是否有命令行、管理控制台等维护工具能够看到系统运行时的情况。开源项目是否有故障检测和恢复的能力例如告警、切换等。如果是开源库例如 Netty 这种网络库本身是不具备运维能力的那么就需要在使用库的时候将一些关键信息通过日志记录下来例如在 Netty 的 Handler 里面打印一些关键日志。用如何使用开源项目1. 深入研究仔细测试 很多人用开源项目其实是完完全全的“拿来主义”看了几个 Demo把程序跑起来就开始部署到线上应用了。Elasticsearch 的案例 我们有团队使用了 Elasticsearch基本上是拿来就用倒排索引是什么都不太清楚配置都是用默认值跑起来就上线了结果就遇到节点 ping 时间太长剔除异常节点太慢导致整站访问挂掉。MySQL 的案例 很多团队最初使用 MySQL 时也没有怎么研究过经常有业务部门抱怨 MySQL 太慢了。但经过定位发现最关键的几个参数(例如innodb_buffer_pool_size、 sync_binlog、innodb_log_file_size 等)都没有配置或者配置错误性能当然会慢。2. 小心应用灰度发布 做了“深入研究、仔细测试”发现没什么问题是否就可以放心大胆地应用到线上了呢别高兴太早即使研究再深入测试再仔细还是要小心为妙因为再怎么深入地研究再怎么仔细地测试都只能降低风险但不可能完全覆盖所有线上场景。3. 做好应急以防万一 即使我们前面的工作做得非常完善和充分也不能认为万事大吉尤其是刚开始使用一个开源项目运气不好可能遇到一个之前全世界的使用者从来没遇到的 bug导致业务都无法恢复尤其是存储方面一旦出现问题无法恢复可能就是致命的打击。MongoDB 丢失数据 某个业务使用了 MongoDB结果宕机后部分数据丢失无法恢复也没有其他备份人工恢复都没办法只能接一个用户投诉处理一个导致 DBA 和运维从此以后都反对我们用 MongoDB即使是尝试性的。虽然因为一次故障就完全反对尝试是有点反应过度了但确实故障也给我们提了一个醒对于重要的业务或者数据使用开源项目时最好有另外一个比较成熟的方案做备份尤其是数据存储。例如如果要用 MongoDB 或者 Redis可以用 MySQL 做备份存储。这样做虽然复杂度和成本高一些但关键时刻能够救命改如何基于开源项目做二次开发1. 保持纯洁加以包装 当我们发现开源项目有的地方不满足我们的需求时自然会有一种去改改的冲动但是怎么改是个大学问。一种方式是投入几个人从内到外全部改一遍将其改造成完全符合我们业务需求。但这样做有几个比较严重的问题投入太大一般来说Redis 这种级别的开源项目真要自己改至少要投入 2 个人搞 1 个月以上。失去了跟随原项目演进的能力改的太多即使原有开源项目继续演进也无法合并了因为差异太大。所以我的建议是不要改动原系统而是要开发辅助系统监控、报警、负载均衡、管理等。以 Redis 为例如果我们想增加集群功能则不要去改动 Redis 本身的实现而是增加一个 proxy 层来实现。2. 发明你要的轮子 其实选与不选开源项目核心还是一个成本和收益的问题并不是说选择开源项目就一定是最优的项目最主要的问题是没有完全适合你的轮子软件领域和硬件领域最大的不同就是软件领域没有绝对的工业标准大家都很尽兴想怎么玩就怎么玩。除此以外开源项目为了能够大规模应用考虑的是通用的处理方案而不同的业务其实差异较大通用方案并不一定完美适合具体的某个业务。比如说 Memcached通过一致性 Hash 提供集群功能但是我们的一些业务缓存如果有一台宕机整个业务可能就被拖慢了这就要求我们提供缓存备份的功能。但 Memcached 又没有而 Redis 当时又没有集群功能于是我们投入 2~4 个人花了大约 2 个月时间基于 LevelDB 的原理自己做了一套缓存框架支持存储、备份、集群的功能后来又在这个框架的基础上增加了跨机房同步的功能很大程度上提升了业务的可用性水平。如果完全采用开源项目等开源项目来实现是不可能这么快速的甚至开源项目完全就不支持我们的需求。上一章: 架构重构技术下一章: App架构演化归类: 从0开始学架构

更多文章