基于开源构建自己的产品
从 2017.12
开始,我们就一直在基于 SpringCloud
(下称SC) 这套产品在构建我们自己的商业产品,说不起有一些成功,但却有一些反思。
如何基于开源做产品
如何基于开源做产品,让我们聊一聊这个话题。在大部分的中小型公司,我们都会基于某一个开源产品进行二次开发,直到最后这个开源产品被吸收殆尽,融入我们的产品,但这是一个漫长的过程。
找到方向
无论你怎么在技术市场中嗅探到一股新技术的清香味,比如 Docker
或SpringCloud
,我们最应该了解的都是这个技术背后是怎么样的需求在推进它前进。
Hadoop
的背后是企业对于海量数据需要存储的需求,更深层的是企业的IT从功能化向数据化转型。Docker
的背后是大规模虚拟机集群管理的困难,更深层是企业的IT的规模化,不再是以前几台机器跑天下的时代。SpringCloud
的背后是企业应用巨型化,迭代困难导致。
而这些技术的背后的内驱力,我们的方向,那我们找的方向显然应该是
以海量数据为方向
:为企业提供可以简单运维的集群,更大的存储量,更快的查询速度……以海量机器为方向
:为企业提供不可变基础设施,完善的监控体系,简化的部署……以巨大应用为方向
:为企业提供敏捷开发,应用的拆分化方案,基础设施的模式化……
划定自己的范围
上述说的每一块都是巨大的市场,如若非巨头实难将这一切都啃下来,因此我们下一步是划定自己的范围。假设我们是以以巨大应用为方向
为产品的方向,我们可以将产品拆解为
应用框架
:客户既有代码如何使用我们的整个产品。平台支撑
:我们所提供的产品的范围服务发现
:如何进行服务发现服务注册
:服务注册的信息包含哪些服务管理
:是否包含服务的管理属性服务下线
:是否能够手动将服务下线
配置中心
:如何进行配置管理配置侧
:是否需要进行数据隔离读取侧
:读取侧是否需要进行缓存等
系统监控
:如何进行系统监控其他
正如上文的列表,我们需要将系统的功能点列出来,这里有着整个产品最大的一个陷阱 反思1:忘记你的开源实现,此时的你应该可以输出产品的功能清单,尽可能的详尽,在后续的迭代中也也是至为重要的指导纲领。
慎重考察你的开源实现
开源实现的代码质量都算不上太差,而我们最为重要的是考察开源的代码里的关于设计理念部分,如果你需要一个 CP
的系统,自然就不要考虑 AP
的Eureka这样的事情,为了要把这一步放在设计之后,也是因为千万不要因为别人的实现干扰了你自己对于产品的理解。
设计你的架构
也没什么值得要说的,尽可能的在你的代码和开源之间增加一层适配层,重度的耦合只会让你摔的更疼。
哪怕你只有一个实现的时候也是值得的。至少让你们的开发者更容易理解你们自己的设计。
tips: 大部分的时候你都会适配其他的实现,如果这个市场只有一家产品,那很可能并不是一个好消息
坚持你的设计
哪怕是你发现底层的开源实现无法满足你的需求的时候,你可以使用很复杂的方式实现你的设计,也不要轻易的改变你的设计。改变那些无关紧要的部分,对于核心的理解是切记不能改变的,不然你就很快会变成下面这样
1 | 你的产品:100% 别人的产品: 0% |
此时的你需要增加自己的设计的时候,你就会发现你自己的概念是极其难以加入的,为什么?因为这个产品的主体已经不是你设计的产品了,已经变成一个开源产品的发行版 (注:反思2:你究竟做的是发行版还是产品)
专注
每个产品都可能包含很多组件,在刚开始的阶段,我们可能处处完善,更应该专注于某一块,对于一个商业产品可以先从数据的展示的方面进行设计,比如在微服务设计中,对于监控数据的展示,投入更多的精力在 APM
,切莫贪大导致的每一块都做的不怎么样。
Tips: 对于我们的组件是可以融合的,更应该能够拆分,产品的某一部分都是独立的产品,用开源的方式去做一个独立的产品会让你的产品走的更远。
保持关注
在一个新的方向上,经常会出现全面性的风向转变,就比如容器技术就经历了 Swam
转至 K8S
,因为上面的概念解耦,我们也需要耗费一些精力进行下层的适配,而有些技术可能天生就是冲突的,比如 SpringCloud
所基于的 REST
和 Dubbo
所基于非透明的 RPC
在使用的过程就是完全不一样的,在选择的过程中可能会面领着市场的完全方向转变,甚至于被 ServicsMesh
这样的新的技术革命掉。因此产品在自己的概念中也时刻关注是否有一些已经 outdate
了。
比如说在传统的微服务领域中的给服务外挂Sidecar的方式完全在后续的迭代版本中会被 isito
此类的方案取缔,甚至于服务发现也会随之消失。
反思
反思1:忘记你的开源实现
这大概是我们在这两年内犯过最大的错误,这个错误的影响一直至今。此话怎么讲,且听我细细分析。
因为我们这套产品是基于 SpringCloud
此时便有 SpringCloud
先入为主的印象,这就让我们在后续的设计中,很多都因实现而设计。
举个例子:我们在设计服务发现的时候,因为SC
在实现之处是基于Eureka
,Eureka
对于服务的分组的非常的简单只有服务
和实例
这两个维度,因此我们在后续的系统设计中,我们便按照服务
和实例
这两个维度进行诸多的设计,比如流量的监控,服务的转发等等功能,而这些功能在实现的过程中,也作为了HardCode
部分存在,直至后期我们需要增加额外的维度的时候就吃了一个大亏。因此在这两年的摸索中,渐渐明白了一个道理,你在实现自己的产品的时候,首先应该满足是自己产品的特性!就比如在 Spring 的实现中,WebMVC
可以基于 Tomcat
Netty
Jboss
其中任一种实现,Spring将那些他所需要的特性功能比如 server.port
作为了产品的属性,而 tomcat.max-connect
是作为额外的配置项存在的。
反思2:你究竟做的是发行版还是产品
Linux
有发行版的概念,不同的发行版之间可能是有不同的包管理工具,不同的启动机制等等,但是大部分是一直的,但是产品不一样,产品不应该将自己的内核实现暴露给用户,因此Windows只有Windows,并没有Windows的发行版,一部分是自己没有开源,另外一方面产品的内核逻辑是产品的主要竞争力。
比如某竞品的设计如此 当你融入自己的想法之后,你可以清晰的将原来所开源产品的组件转为你所拥有的概念,可能这样说起来有些不清晰,在我看来,一个产品如果在客户在使用的过程中,不是非常明显的感受你的实现是基于某个产品的就算是成功了。