扩展一个PoC的方法介绍

120 阅读10分钟

这是不可能的--从PoC到生产就绪的过程

你需要采取的步骤,以确保你的产品达到生产水平

所以,你已经准备好了你的PoC,并且正在运行,你已经成功地向企业证明了你的想法是可行的。他们说:"太棒了!"他们还说:"让我们下周把它部署到生产中去。"你突然意识到他们并没有真正理解你所说的任何事情。

当然,这种情况并不是在每一种情况下都会发生,有时我们能够正确地传达重构的需要,并在我们真正将一个想法部署到生产中之前继续工作。但在有些情况下,潜力是如此之大,以至于在一个非技术人员的脑海中,唯一的问题是 "为什么我们不现在就把它卖掉,以后再修复代码?"。

作为一个关心产品和公司的负责任的软件开发人员,你的工作是解释一个软件的 "可扩展性 "需要发生什么,以及--在某些情况下--"可扩展性 "在这里也意味着什么。

我们所说的可扩展是什么意思?

对于一个软件来说,它需要处理一定的工作量,一定数量的并发用户,并且它应该能够很容易地从1个用户上升到这个上限。如果我们需要监控它,并在它因内存耗尽而崩溃时重新启动服务,那么我们就没有做对。

如果我们正在考虑拥有一个大规模的上限(我说的是每天数百万用户),那么我们肯定需要开始考虑优化我们利用资源的方式,以及我们如何能够从一台服务器中扩展出来--鉴于我们会受到一台计算机的物理资源的限制,不管它有多大的灵活性。

这就是横向扩展发挥作用的地方。我们不是在服务器上添加更多的内存或更好的CPU,而是添加更多的服务器并在它们之间分担负载。

这样一来,你就不会受到你可以添加到单个服务器的内存数量的限制,相反,你可以根据你的需要添加尽可能多的服务器,只要他们能够在他们收到的那块蛋糕上工作,那么你就没有问题。

诚然,这是你扩展的方式,但它也带来了自己的一系列困难。

  • 在服务器之间分担负载。这可以通过像负载平衡器这样的东西来实现,它将集中流量到你的服务,但它将在你的服务器集群中 "平衡 "它。如果与你的代码的交互已经是无状态的,这很好,但如果你把客户/用户信息保存在内存中,那么后续的请求将到达不同的服务器。而不同的计算机之间并不共享内存,因此每次有新的请求到来时,就像一个新的用户开始使用你的软件。当然,也有办法将用户锁定在你的服务器的单一实例上,但这也削弱了负载均衡器的好处。
  • 服务器可能还是会出现资源耗尽的情况。 如果你唯一的解决方案是尽可能多地复制你的PoC,你可能仍然会遇到同样的缺乏资源的情况,这让你在第一时间陷入困境。这可能表明,你的单体服务可能更适合作为一组相互独立运行的微服务。

扩展并不容易,但如果你想让一个软件经受住时间的考验,它是必须的。如果你的产品是成功的,那么它需要的资源数量就会增加,因为使用它的人的数量会增加。如果你不做计划,那么你将无法应对需求,你的用户将承受后果(即糟糕的用户体验,糟糕的性能,缺乏稳定性,等等)。

如何扩展一个PoC?

这是一个要问自己的关键问题,因为如果你真的展示了一个PoC,那么你可能写得非常快,很少注意到质量和未来。相反,你只关注你想证明你的想法是可以做到的。

这是完全正确的,对于一个PoC来说,你通常最终会削减一些角落和硬编码一些行为。毕竟,你想让它背后的主要想法脱颖而出,其余的将被扔掉并重新编码。

为什么呢?看看我们到目前为止一直在谈论的情景:一个单一的软件,现在需要扩展。这并不是说你可以说。"让我们把它放在AWS的lambda上",或者 "我把它部署在Azure上,它就可以扩展"。

这些都是很好的想法,也是扩展应用程序的绝佳方法,但前提是代码允许。而在一个单一的PoC上,有可能:它不会。

让我们来看看你要做什么来开始了解你前面有多少工作。

理解你的系统的痛点在哪里

在你开始将你的PoC分割成多个服务之前,你必须了解的第一件事是它的哪些部分使用了最多的资源。无论是内存、I/O还是CPU,任何资源密集型的东西都可能需要自己的服务器,这样它就可以使用所有的资源,而不需要与其他部分共享。

你应该在有压力的情况下测量这一点。换句话说,找一个负载测试仪,把你的代码用到极限。了解这个极限是什么样子的,以及它为什么会达到这个极限。是请求的数量吗?或者是收到的并发请求的数量?或者他们只是一个接一个地来,但彼此之间太接近了。不管是什么原因,这将给你一个提示,说明你的应用程序的哪些部分受到的影响最大,因此必须提取出来并进行优化。

规划你的服务和它们的通信协议

好了,现在你明白了问题出在哪里,是时候来点有趣的了:把事情拆开。

这意味着把你之前确定的每个部分变成一个独立的服务。

这就是问题所在,也是为什么扩展不是 "我让它在lambda上运行 "那么简单。你正在使用本地内存来处理从一个函数到另一个函数的数据和参数。你从数据库中提取数据并将其存储在本地内存中(即 bigDataSet 变量),然后你将该内存作为参数传递给 processTheData 函数。这种情况不能再发生了,因为一旦你把这些函数变成外部服务,你就必须处理在网络上发送数据的问题。

这里就是通信协议部分发挥作用的地方。你让你的服务相互交谈的方式将决定你的架构是否成功。有很多 通信服务方式 ,这完全取决于你想从它们身上得到什么。你是否需要一个开放的通道来不断地活动并来回发送数据?还是异步通信是最好的方法?

不管是什么,你都要考虑以下几个方面来决定:

  • 延迟。它对你的服务有多重要?有些通信协议比其他的更重。在HTTP上使用REST和让2个服务在网络套接字上说话是不一样的。
  • 数据序列化。回到我上面的例子,bigDataSet变量可以是任何东西,它可以是一个拥有多个方法和其他不可序列化属性的DataSet类对象。然而,这个数据集必须通过电线一直传递到你创建的新服务。你打算怎么做呢?
  • 数据的去序列化。和以前一样,但方向相反。如果你从 grabALOTOfDataFromTheDataBase 的新服务中得到结果,该服务将不能通过电线向你发送数据集对象,但你的代码需要它是一个对象。因此,你必须知道如何将数据集变成一个对象。
  • 本地文件。你是否在你的PoC上使用本地文件?这是一个通常的角落,我们倾向于削减,因为对于PoC,我们可以处理本地CSV而不是一个完整的数据库,但现在我们不能。我们需要一种有效的方式来加载数据,而磁盘I/O不是一种方式。因此,考虑将所有这些本地的重型文件转移到一个适当的存储介质中。

如果你在自己的项目上开始工作,你可能还能想出几个问题。这可能是一个非常令人头痛的问题,虽然这可能是你能可靠地将PoC扩展到生产就绪状态的少数方法之一,但它也是一个很大的工作。

说服企业给你更多的时间和资源

实施前的最后一步是获得企业的批准。他们想用你的PoC投入生产,记得吗?而现在,在仔细测量性能和规划新的架构和重构工作之后,你有了一个拟议的时间表。

现在是推销的时候了。这里是有趣的开始,因为除非你精通商业谈判,否则你会花10分钟的时间去解释为什么你的解决方案在技术上是如此健全,并且完美地满足了他们的需求,但没有人会听你的。他们可能会说 "我不明白 "或 "为什么我们不能担心代码之后看起来很好?",虽然这可能让你觉得你一直在和一堵砖墙说话;这不是他们的错,是你的错。

他们不是傻子,不不,不要犯这个错误。他们只是心中有不同的目标。你的工作是确保解决方案在技术上是合理的,而他们的工作是确保公司赚钱,而根据他们的说法,你有一个完美的产品,你已经展示过了,现在你不想部署它,直到你使它 "完美"。

我曾经参加过这种类型的对话,相信我,我明白你的挫折感。

你必须明白的第一件事是,你必须做出妥协。你的计划不能是 "让我们建立这个6个月,然后担心部署问题"。这意味着他们在很长一段时间内看不到任何真正的好处,相反,要尝试计划一个更迭的方法,先计划最关键的变化,并部署你目前的代码,想法是在2-3周内用一个稍好的版本来取代它。

然后在下个月计划第二个里程碑,用一个更好的代码库和架构。继续这样做,直到你达到你最初想要达到的地方。

当然,这可能会包括其他活动,如生产支持、部署等,这将会延迟你的时间表,但至少你会得到更快的批准,产品将能够不断发展。

然后你就完成了!如果你做了上述工作,并且你已经成功地向企业推销了实施计划,那么现在是时候把你的钱放在你的嘴里并开始编码了。

希望你也包括了测试时间和紧急情况下的时间估计的东西。总有一些事情会--而且由于我们的朋友墨菲,会--时常出错,所以确保你为它们留下一些空间。

你以前有过这样的经历吗?你是怎么做的?你是否能够推销你的想法和实施计划?请在下面留言,分享你的经验!