平台诞生



世界已经改变。 我在水中感觉到它,在地下看到它,在空中感觉到它。 曾经存在的一切都消失了,没有更多的人记住它了。
出自电影《指环王:指环王》

互联网上有100500篇关于“我们如何看待整体”的文章和报告,我不想再写另一篇。 我尝试更进一步,讲述技术变化如何导致全新产品的出现(破坏者:我们写了盒子,写了平台)。 本文主要是回顾,没有技术细节。 详细信息将在以后。

这将涉及控制面板站点和Vepp服务器。 这是我负责开发的ISPsystem产品。 此处的另一篇文章中了解新面板的功能-仅关于技术。 但是首先,像往常一样,有一点历史。

第1部分。有必要进行一些更改


我们公司已编写用于托管服务自动化的软件已有15年以上。 在这段时间内,我们的产品几代发生了变化。 当我们从第二种切换到第四种时,我们将Perl更改为C ++并开始免费销售我们的软件...当我们从第四种切换到第五种时,为了追求速度,我们从单线程应用程序切换到多线程(从包含我们所有产品的整体程序框架)。

但是,不仅我们在变化,我们的客户和竞争对手也在变化:如果10到15年前,网站所有者在技术上很精通(其他人对Internet的兴趣不强),那么现在它可能是一个与IT毫无联系的人。 有许多竞争解决方案。 在这样的条件下,仅对产品进行加工是不够的,因此必须易于使用。

英勇重新设计


在所有意义上,这种变化都变得最为明显。 一直以来,我们产品的界面几乎保持不变和统一。 我们已经分别写过有关UX的视图。 在第五代产品中,API定义了表单和列表的外观。 一方面,这使得无需前端开发人员即可实现许多事情成为可能;另一方面,它引起了非常复杂的调用,有时会影响整个系统的大部分时间,并且极大地限制了更改接口的能力。 毕竟,任何更改都不可避免地是API的更改。 就是这样,向集成问好!

例如:在ISPmanager中创建用户还可以导致创建FTP用户,邮件域,邮箱,DNS记录,站点。 所有这些工作都是原子完成的,因此阻止了所列组件的更改,直到操作完成。

在新的API中,我们切换到了简单的原子操作,并且前端开发人员不得不执行复杂的复杂操作。 这使您可以实现复杂的接口并对其进行更改,而不会影响核心API,因此不会破坏集成。

对于前端开发人员,我们实现了批处理查询执行机制,该机制可以在发生错误时执行反向操作。 如实践所示,在大多数情况下,复杂查询是创建某些内容的请求,通过执行删除操作很容易取消创建。

减少响应时间和即时通知


我们拒绝了长时间修改请求。 我们的产品的早期版本可能会挂起很长时间,以尝试满足用户的要求。 我们认为,对于每个操作而言,微不足道地更改数据库中的数据都更加困难,我们将在系统中创建一个任务并尽快响应客户端,从而使他能够继续工作,而不必关注无休止的加载过程。

但是,如果您需要结果,现在和现在该怎么办? 我想当您一次又一次地重新加载页面时,很多人都熟悉这种情况,希望操作将结束。

在新一代产品中,我们使用websocket进行即时事件传递。

第一个实现使用longpoll,但是前端开发人员对该方法不满意。

HTTP内部通讯


HTTP作为一种传输方式获得了成功。 现在,无论使用哪种语言,HTTP服务器都可以在几秒钟内实现(如果您使用google,那么只需几分钟即可实现)。 即使在本地,形成HTTP请求也比阻止协议容易。

在上一代中,扩展(插件)是一些应用程序,如有必要,它们可以作为CGI启动。 但是为了编写一个长期存在的扩展,我不得不努力:用C ++编写一个插件,并在每次产品更新时对其进行重建。

因此,在第六代中,我们切换到了通过HTTP进行内部交互的方式,而这些扩展实际上变成了小型WEB服务器。

新的(不是完全REST)API


在前几代产品中,我们通过GET或POST传递了所有参数。 如果GET没有特殊问题-它的大小很小,则在POST的情况下,直到完全读取请求之前,无法检查访问或重定向请求。

想象一下有多难过:接受几百兆或千兆字节,然后发现它们是由未经授权的用户倒出的,或者现在需要将它们转移到该服务器上!

现在,函数的名称在URI中传递,而授权仅在标头中。 这样一来,您可以在阅读请求正文之前执行部分检查。

此外,API函数变得更加简单。 是的,现在我们不保证创建用户,邮件,网站等的原子性。 但是我们有机会根据需要组合这些操作。

我们已经实现了批量查询执行的功能。 实际上,这是一个单独的服务,接受请求列表并按顺序执行。 如果发生错误,他还可以回滚已经完成的操作。

SSH万岁!


根据以前的经验,我们做出的另一个决定是仅通过SSH使用服务器(即使它是本地服务器)。 最初,我们使用VMmanager和ISPmanager中的本地服务器,然后才添加其他远程服务器成为可能。 这导致需要支持两个实现。

当我们拒绝使用本地服务器时,使用用户操作系统本机库的最后原因就消失了。 自公司成立以来,与他们在一起我们一直受到折磨。 不,本机库有其优点,但缺点更多。

绝对的优势是减少了磁盘和内存的消耗,对于在VDS中工作,这可能非常重要。 缺点-使用您不控制版本的库可能会导致意外结果,从而大大增加了开发和测试的负担。 另一个缺点是无法使用最新版本的库和现代C ++(例如,在CentOS 6上,甚至不完全支持C ++ 11)。

旧习惯


改变方法并转向新技术,我们继续以旧的方式行事。 这导致了困难。

微服务的炒作话题没有被我们忽略。 我们还决定将应用程序划分为单独的服务组件。 这样就可以加强对交互的控制,并对应用程序的各个部分进行测试。 为了更紧密地控制交互,我们将它们布置在容器中,但是可以始终将它们放在一起。

在整体应用程序中,您可以轻松访问几乎所有数据。 但是,即使将产品划分为几个应用程序并将它们放置在附近,它们作为活的应用程序也可以形成链接。 例如,以共享文件或彼此直接请求的形式。

切换到微服务并不容易。 “编写库并在需要时连接它”的旧模式困扰了我们很长时间。 例如,我们有一个服务负责执行“长时间”操作。 最初,它被实现为连接到需要它的应用程序的库。

另一个习惯可以描述如下:如果可以教现有的服务,为什么还要编写另一个服务。 我们从整体中获得的第一件事就是授权机制。 但是随后,这种诱惑似乎将所有通用组件推向了这项服务,就像COREmanager(第五代产品的基本框架)一样。

第2部分。组合不兼容


首先,读写请求是通过单个过程执行的。 通常,写请求是阻止请求,但它们的速度非常快:我写了数据库,创建了一个任务,然后回答了。 有了阅读请求,故事就不同了。 在上面创建任务很困难。 它可能会产生相当大的响应,如果客户端之后没有返回,该答案怎么办? 存储多少? 但是同时,阅读请求的处理也可以完全并行化。 这些差异导致重新启动此类进程的问题。 他们的生命周期简直是不相容的!

我们将应用程序分为两个部分:阅读和写作。 没错,从开发的角度来看,这很快变得很不方便。 在一个地方阅读您所做的列表,在另一个地方进行编辑。 最主要的是-如果您更改了第二个,别忘了修复第二个。 是的,并且在文件之间切换至少令人讨厌。 因此,我们来到了以两种模式运行的应用程序:读取和写入。

我们上一代产品广泛使用线程。 但是,正如实践所示,它们并没有为我们节省很多。 由于有许多锁,CPU上的负载很少超过100%。 大量单独的相当快速的服务的出现允许放弃多线程,而支持异步和单线程工作。

在开发过程中,我们尝试将流与异步一起使用(boost :: Asio允许这样做)。 但是,这种方法最有可能给您的项目带来两种方法的所有缺点,而不是带来任何明显的优点:访问共享对象时,您必须将对控制的需求与编写异步代码的难度结合起来。

第3部分。当我们写盒子并写平台时


所有服务都安排在容器中,并且可以与客户端服务器远程协作。 为何将应用程序放在客户端服务器上呢? 这是我问管理层何时将要包装的产品打包到服务器上的问题。

什么是平台? 首先,我们部署了SaaS,该服务在我们的服务器上运行,并允许您配置服务器。 如果您使用任何服务器控制面板并自己购买,则这是适合您的解决方案。 但这并不适合提供者:他们还没有准备好向第三方公司提供对客户服务器的访问权限,我非常了解它们。 这就提出了安全性和容错性的问题。 因此,我们决定为他们提供整个SaaS,以便他们可以在家中部署它。 就像亚马逊一样,您可以在自己的数据中心中运行它并连接到您的计费系统。 我们将此解决方案称为平台。

第一次部署进行得并不顺利。 对于每个活跃用户,我们提出了一个单独的容器。 Docker容器迅速崛起,但是服务发现不能立即起作用:它并非旨在在一秒钟之内动态地提升/停止容器。 从提升的时刻到可以使用该服务的时刻,有时几分钟就过去了!

我已经写道,托管用户在过去十年中发生了很大变化。 现在想象:它从您那里购买了主机-并可以访问Shell。 WTF?!?! 要使用它,首先他必须找到一些SSH客户端(在Windows中这可能会成为问题-默认情况下没有客户端,我通常对移动客户端保持沉默)。

在他仍然可以进入控制台之后,需要安装面板。 而且这个操作也不是很快。 如果出了什么问题? 例如,RosKomNadzor可能阻止从中下载OS软件包的服务器。 出现此类错误时,用户将面对面。



您可能会争辩说,在大多数情况下,用户会收到托管者已经安装的面板,而以上内容不适用于他。 可能吧 但是在服务器上运行的面板会消耗您所支付的资源(占用磁盘空间,占用处理器和内存)。 它的性能直接取决于服务器的性能(服务器崩溃-面板崩溃)。

可能还有一些人不使用任何面板而认为:这与我无关。 但是也许在您的服务器上,如果您拥有一个服务器,某种面板仍会站立并占用资源,但是您只是不使用它?

俄罗斯主持人说:“这真是太好了,您可以帮助我们出售资源。” 其他人补充说:“为什么我们要花资源来部署一个比独立面板消耗更多的平台?”

这个问题有几个答案。
  1. 服务质量得到改善:您可以控制面板版本-在出现新功能或检测到错误时快速更新面板版本; 您可以在面板中直接宣布股票。
  2. 在基础架构规模上,您可以节省磁盘,内存和处理器,因为某些进程只为服务活动用户而启动,而某些进程同时为许多客户端提供服务。
  3. 支持人员无需分析该行为是面板的特定版本的功能还是错误。 节省时间。

我们更多的客户购买了成批包装的许可证,然后将其打杂,然后转售给客户。 原则上,不再需要执行无意义的工作。 毕竟,现在这是一种产品。

此外,我们有机会使用笨重的解决方案,提供了以前无法访问的功能。 例如,获取网站截图的服务需要启动无头铬。 我认为,如果用户由于这种操作而用完内存并开枪自杀(例如MySQL),他不会感到非常高兴。

最后,我想指出的是,我们从他人的经验中学习,并正在积极发展自己的经验。 日志记录,泊坞窗,服务发现,各种延迟,重试和队列...现在您不记得要掌握或重新发明的所有内容了。 所有这一切并不能使开发变得更容易,但会带来新的机会并使我们的工作更加令人兴奋。

故事还没有结束,但是发生的事情可以在Vepp网站上查看。

Source: https://habr.com/ru/post/zh-CN467973/


All Articles