基于开源构建自己的产品

2017.12 开始,我们就一直在基于 SpringCloud(下称SC) 这套产品在构建我们自己的商业产品,说不起有一些成功,但却有一些反思。

如何基于开源做产品

如何基于开源做产品,让我们聊一聊这个话题。在大部分的中小型公司,我们都会基于某一个开源产品进行二次开发,直到最后这个开源产品被吸收殆尽,融入我们的产品,但这是一个漫长的过程。

找到方向

无论你怎么在技术市场中嗅探到一股新技术的清香味,比如 DockerSpringCloud,我们最应该了解的都是这个技术背后是怎么样的需求在推进它前进。

  • Hadoop 的背后是企业对于海量数据需要存储的需求,更深层的是企业的IT从功能化向数据化转型。
  • Docker 的背后是大规模虚拟机集群管理的困难,更深层是企业的IT的规模化,不再是以前几台机器跑天下的时代。
  • SpringCloud 的背后是企业应用巨型化,迭代困难导致。

而这些技术的背后的内驱力,我们的方向,那我们找的方向显然应该是

  • 以海量数据为方向:为企业提供可以简单运维的集群,更大的存储量,更快的查询速度……
  • 以海量机器为方向:为企业提供不可变基础设施,完善的监控体系,简化的部署……
  • 以巨大应用为方向:为企业提供敏捷开发,应用的拆分化方案,基础设施的模式化……

划定自己的范围

上述说的每一块都是巨大的市场,如若非巨头实难将这一切都啃下来,因此我们下一步是划定自己的范围。假设我们是以以巨大应用为方向为产品的方向,我们可以将产品拆解为

  • 应用框架:客户既有代码如何使用我们的整个产品。
  • 平台支撑:我们所提供的产品的范围
    • 服务发现:如何进行服务发现
      • 服务注册:服务注册的信息包含哪些
      • 服务管理:是否包含服务的管理属性
        • 服务下线:是否能够手动将服务下线
    • 配置中心:如何进行配置管理
      • 配置侧:是否需要进行数据隔离
      • 读取侧:读取侧是否需要进行缓存等
    • 系统监控:如何进行系统监控
    • 其他

正如上文的列表,我们需要将系统的功能点列出来,这里有着整个产品最大的一个陷阱 反思1:忘记你的开源实现,此时的你应该可以输出产品的功能清单,尽可能的详尽,在后续的迭代中也也是至为重要的指导纲领。

慎重考察你的开源实现

开源实现的代码质量都算不上太差,而我们最为重要的是考察开源的代码里的关于设计理念部分,如果你需要一个 CP 的系统,自然就不要考虑 AP 的Eureka这样的事情,为了要把这一步放在设计之后,也是因为千万不要因为别人的实现干扰了你自己对于产品的理解。

设计你的架构

也没什么值得要说的,尽可能的在你的代码和开源之间增加一层适配层,重度的耦合只会让你摔的更疼。
lQBSyt.png
哪怕你只有一个实现的时候也是值得的。至少让你们的开发者更容易理解你们自己的设计。

tips: 大部分的时候你都会适配其他的实现,如果这个市场只有一家产品,那很可能并不是一个好消息

坚持你的设计

哪怕是你发现底层的开源实现无法满足你的需求的时候,你可以使用很复杂的方式实现你的设计,也不要轻易的改变你的设计。改变那些无关紧要的部分,对于核心的理解是切记不能改变的,不然你就很快会变成下面这样

1
2
3
4
5
6
7
你的产品:100%    别人的产品: 0%
------- 因为难以实现的功能 --------
你的产品: 80% 别人的产品: 20%
------- 因为难以实现的功能 * 2 --------
你的产品: 60% 别人的产品: 40%
------- 因为难以实现的功能 * 3 --------
你的产品: 40% 别人的产品: 60%

此时的你需要增加自己的设计的时候,你就会发现你自己的概念是极其难以加入的,为什么?因为这个产品的主体已经不是你设计的产品了,已经变成一个开源产品的发行版 (注:反思2:你究竟做的是发行版还是产品)

专注

每个产品都可能包含很多组件,在刚开始的阶段,我们可能处处完善,更应该专注于某一块,对于一个商业产品可以先从数据的展示的方面进行设计,比如在微服务设计中,对于监控数据的展示,投入更多的精力在 APM,切莫贪大导致的每一块都做的不怎么样。

Tips: 对于我们的组件是可以融合的,更应该能够拆分,产品的某一部分都是独立的产品,用开源的方式去做一个独立的产品会让你的产品走的更远。

保持关注

在一个新的方向上,经常会出现全面性的风向转变,就比如容器技术就经历了 Swam 转至 K8S,因为上面的概念解耦,我们也需要耗费一些精力进行下层的适配,而有些技术可能天生就是冲突的,比如 SpringCloud 所基于的 RESTDubbo 所基于非透明的 RPC 在使用的过程就是完全不一样的,在选择的过程中可能会面领着市场的完全方向转变,甚至于被 ServicsMesh 这样的新的技术革命掉。因此产品在自己的概念中也时刻关注是否有一些已经 outdate 了。

比如说在传统的微服务领域中的给服务外挂Sidecar的方式完全在后续的迭代版本中会被 isito 此类的方案取缔,甚至于服务发现也会随之消失。

反思

反思1:忘记你的开源实现

这大概是我们在这两年内犯过最大的错误,这个错误的影响一直至今。此话怎么讲,且听我细细分析。
因为我们这套产品是基于 SpringCloud 此时便有 SpringCloud 先入为主的印象,这就让我们在后续的设计中,很多都因实现而设计。

lQ1Tqs.png

举个例子:我们在设计服务发现的时候,因为SC在实现之处是基于EurekaEureka对于服务的分组的非常的简单只有服务实例这两个维度,因此我们在后续的系统设计中,我们便按照服务实例这两个维度进行诸多的设计,比如流量的监控,服务的转发等等功能,而这些功能在实现的过程中,也作为了HardCode部分存在,直至后期我们需要增加额外的维度的时候就吃了一个大亏。因此在这两年的摸索中,渐渐明白了一个道理,你在实现自己的产品的时候,首先应该满足是自己产品的特性!就比如在 Spring 的实现中,WebMVC 可以基于 Tomcat Netty Jboss 其中任一种实现,Spring将那些他所需要的特性功能比如 server.port 作为了产品的属性,而 tomcat.max-connect 是作为额外的配置项存在的。

反思2:你究竟做的是发行版还是产品

lQl23F.png Linux 有发行版的概念,不同的发行版之间可能是有不同的包管理工具,不同的启动机制等等,但是大部分是一直的,但是产品不一样,产品不应该将自己的内核实现暴露给用户,因此Windows只有Windows,并没有Windows的发行版,一部分是自己没有开源,另外一方面产品的内核逻辑是产品的主要竞争力。
比如某竞品的设计如此 lQMSEV.png 当你融入自己的想法之后,你可以清晰的将原来所开源产品的组件转为你所拥有的概念,可能这样说起来有些不清晰,在我看来,一个产品如果在客户在使用的过程中,不是非常明显的感受你的实现是基于某个产品的就算是成功了。