内容简介:框架组件,究竟要不要自研?
一、问题的提出
询问框架组件,是否需要自研?
18年规划系统介绍58到家的技术体系,15年加盟58到家后,架构部正好也是负责范围的一部分,故谈一谈自己的想法,个人观点:
- 如果公司业务不复杂,研发人数比较少,技术实力相对有限,一定不要自研框架组件
- 如果公司业务复杂,研发人数比较多,技术能力能够胜任,建议自研部分框架组件
二、为什么早期不建议自研?
早期研发人数较少,公司也不确定能走多远,业务相对简单,业务以“快速迭代”为最高优先级,此时一般会选择“自己熟悉的技术”作为选型:
- 研发语言:熟 PHP 选PHP,熟 Java 选Java
- 数据库:熟 MySQL 选MySQL,熟SQL-server选SQL-server
- 框架组件:熟Ruby on Rails选ROR,熟ThinkPHP选ThinkPHP,熟SSH选SSH
此时千万不要纠结选型,选自己熟悉的,业务以快速迭代为最优先,公司得先生存下来。
多说一句,此时对于技术合伙人的技术视野就有一定要求,如果早期方向不对,例如选择了IOE或者微软技术体系,等公司发展若干年,数据量并发量上涨很多倍,成本以及未来的技术应对恐怕会有麻烦。
58同城早期选型是微软技术体系,后来数据量增大,并发量增大,机器数据库越来越多,性能扛不住,成本也扛不住(你猜一个SQL-server的licence一年多少钱?),后来老崔带领大家转型开源阵营:
- Windows -> Linux
- SQL-server -> MySQL
- C# -> Java
虽然短痛了1-2年,但长远来说,绝对是正确的决策。
如今,如果你再创业,选云,选LAMP或者SSH,八成不会走太大的弯路。
三、随着规模的扩大,为什么要控制技术栈?
随着业务越来越复杂,研发人数越来越多,如果每个leader都选择自己擅长的框架,就会出现这样的情况:
- 站点框架,team A用着SSH,team B用着Spring+SpringMVC+Mybatis
- 服务框架,team C用着REST,team D用着dubbo,team E用着thrift
- 数据库访问,team X用着mybatis,team Y用着DAO,team Z用着jdbc
对于整体而言,跨部门的调用越来越麻烦,重复造的轮子越来越多,技术效率会逐步降低,研发+测试+运维成本都越来越高。
第一个观点:即使不自研,技术栈也请尽量统一。
四、统一了技术栈,为什么建议浅浅的封装一层?
统一了技术栈以后,如果不封装,redis官方Java客户端Jedis可能有这样一些接口:
String Memcache::get(String key) String Memcache::set(String key, Stringvalue) String Memcache::del(String key)
浅浅的封装一层,会变成这样:
String 58DaojiaKV::get(String key) {
String result = Memcache::get(key);
return result;
}
String 58DaojiaKV::set(String key, Stringvalue) {
String result = Memcache::set(key, value);
return result;
}
String 58DaojiaKV::del(String key) {
String result = Memcache::del(key);
return result;
}
这有什么好处呢?
- 对上游屏蔽底层实现的细节,调用方不用关注缓存是memcache还是redis,调用方只关注58DaojiaKV
- 底层变化的时候,对上游透明,当memcache不能满足需求,要切换为 redis 时,所有调用方不需要大的变化,升级一个最新的58DaojiaKV即可,58DaojiaKV的接口不变,实现变为:
String 58DaojiaKV::get(String key) {
String result = Jedis::get(key);
return result;
}
String 58DaojiaKV::set(String key, Stringvalue) {
String result = Jedis::set(key, value);
return result;
}
String 58DaojiaKV::del(String key) {
String result = Jedis::del(key);
return result;
}
String 58DaojiaKV::get(String key) {
Long startTime = now();
String result = Jedis::get(key);
Long endTime = now();
reportKVTime(startTime- endTime);
return result;
}
String 58DaojiaKV::set(String key, Stringvalue) {
Long startTime = now();
String result = Jedis::set(key, value);
Long endTime = now();
reportKVTime(startTime- endTime);
return result;
}
String 58DaojiaKV::del(String key) {
Long startTime = now();
String result = Jedis::del(key);
Long endTime = now();
reportKVTime(startTime- endTime);
return result;
}
同理,如果要实现统一的告警,调用链跟踪,SQL执行时间,也可以用类似的方法。
第二个观点:第三方库,不但要统一,还可以浅浅的封装一层,预留未来的扩展性。
五、随着规模的进一步扩大,为什么需要适当的造一些轮子?
业务进一步发展,研发团队进一步扩张,虽然使用了统一的技术栈,但不同研发团队的痛点是极其类似的:
- 有站点,监控服务的可用性,处理时间监控需求
- 有告警需求
- 有自动化发布,自动化运维需求
- 有服务治理,服务自动发现需求
- 有调用链跟踪需求
- 有 SQL 监控需求
- 有系统层面数据收集与可视化展现的需求
此时,开源的框架可能满足不了需求了:
- 开源框架/组件太重了,我们需要的可能只是一个轻量级的框架/组件
- 开源框架/组件,只能满足我们的一部分需求
- 不了解开源框架/组件的设计理念,要二次开发成本更高(维护dubboX的同学,维护数据库中间件Atlas的同学可以出来说两句)
- 有些通用的需求是和业务紧密结合的,开源框架/组件可能满足不了
此时,如果技术实力具备,可以统一研发一些框架和组件,解决所有技术团队的通用痛点,满足所有技术团队的通用需求。
未来介绍监控平台、服务治理、调用链跟踪系统、数据收集中心的时候,大家能够更深刻的理解到“造一些轮子”的好处。
第三个观点:适当造一些轮子。
六、58到家自研的框架组件有哪些?
通用框架+服务:
- WEB框架,Daojia-Web-Framework,DWF
- Service框架,Daojia-Service-Framework,DSF
- 消息队列,Daojia-Msg-Queue,DMQ
基础组件:
- 缓存访问组件DMemcache,DJedis
- 数据库访问组件DAO
- 分库分表组件DShard
还有一些日志,消息的组件,这些组件的架构与细节,未来再和大家细聊。
七、总结
框架组件,是否需要自研?
初期建议:不自研,用熟悉的,业务快速迭代为优先,需要一定技术视野。
长远建议:
- 统一技术栈
- 浅浅封装一层
- 适当造轮子
【本文为51CTO专栏作者“58沈剑”原创稿件,转载请联系原作者】
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Beautiful Code
Greg Wilson、Andy Oram / O'Reilly Media / 2007-7-6 / GBP 35.99
In this unique work, leading computer scientists discuss how they found unusual, carefully designed solutions to difficult problems. This book lets the reader look over the shoulder of major coding an......一起来看看 《Beautiful Code》 这本书的介绍吧!