哈Ha! 我叫Sergey Lezhnin,我是Sbertekh的高级建筑师。 我工作的方向之一是统一战线系统。 该系统具有配置参数管理服务。 许多用户,服务和应用程序都使用它,这需要高性能。 在这篇文章中,我将介绍该服务如何从第一个(最简单的)发展到当前版本,以及为什么我们最终将整个架构部署为180度。

这是我们开始的地方-这是参数管理服务的第一个实现:

客户端从服务请求配置参数。 该服务将请求转换为数据库,接收响应并将其返回给客户端。 同时,管理员可以使用其单独的服务来管理参数:添加新值,更改当前值。
这种方法有一个优势-简单。 尽管存在以下所有缺点,但还有更多缺点:
- 通过网络频繁访问存储,
- 对数据库的访问竞争激烈(我们将其放在一个节点上),
- 表现不佳。
为了通过负载测试,该体系结构所提供的负载不得超过直接访问数据库所产生的负载。 结果,该电路的负载测试没有通过。
第二阶段:我们决定在服务端缓存数据。

在这里,请求处的数据最初会加载到共享缓存中,并在下一个请求时从缓存中返回。 服务管理员不仅可以管理数据,还可以在缓存中标记数据,以便在更改数据时对其进行更新。
因此,我们减少了对存储库的访问次数。 同时,由于管理员服务可以访问内存中的缓存并控制重置,因此数据同步非常简单。 另一方面,如果发生网络故障,客户端将无法接收数据。 通常,获取数据的逻辑很复杂:如果高速缓存中没有数据,则需要从数据库中获取数据,将其放入高速缓存中,然后才将其返回。 需要进一步发展。
开发的第三阶段是客户端数据缓存:

客户端具有用于访问服务的外壳(“客户端模块”),该外壳隐藏了本地数据缓存。 如果请求时请求的数据不在缓存中,则调用该服务。 该服务从数据库请求参数并返回它们。 与以前的方案相比,这里的缓存管理很复杂。 要重置参数,服务必须通知客户这些参数已更改。
在这种体系结构中,我们减少了对服务和数据库的调用次数。 现在,如果已经请求了该参数,即使服务或数据库不可用,它也将返回到客户端,而无需访问网络。 另一方面,最大的缺点是与客户端交换数据的逻辑很复杂,您必须通过某种服务(例如,消息队列)另外通知他。 客户端必须订阅该主题,他会收到有关参数更改的通知,并且客户端必须在其缓存中将其重置以获取新值。 相当复杂的方案。
最后,我们现在进入最后阶段。 在这方面,我们得到了《反应式宣言》中制定的基本原则的帮助。
- 响应:系统尽快响应。
- 弹性:即使发生故障,系统也可以继续响应。
- 弹性:系统根据负载使用资源。
- 消息驱动:提供系统组件之间的异步和免费消息传递。
与此方法相对应的方案非常简单:

一般原则是这样的:客户端订阅配置参数,并且当其值更改时,服务器将其通知给客户端。 上面的方案略有简化:它不反映客户注册后,他需要初始化并获取初始值。 但是,其中最主要的是:箭头改变了方向。 以前,客户端或缓存主动向服务请求数据更改,但是现在该服务本身发送有关数据更改的事件,并由客户端对其进行更新。
该体系结构具有几个重要的优点。 由于客户端没有主动请求服务和存储,因此减少了对该服务和存储的调用次数。 实际上,订阅每个所需参数的吸引力仅发生一次。 然后,客户已经简单地收到了变更流。 数据可用性不断提高,因为客户端始终具有一个值-已对其进行缓存。 通常,这种交换参数的方案非常简单。
这种架构的唯一缺点是数据初始化的不确定性。 在第一次按预订更新之前,参数值仍未定义。 但这可以通过设置客户端默认参数值来解决,该默认值在首次更新期间将由实际参数值替换。
技术选择
批准该计划后,我们开始寻找实施方案的产品。 在
Vertx.io ,
Akka.io和
Spring Boot之间
进行选择 。

下表总结了我们感兴趣的特征。 Vertx和Akka拥有参与者,而Sping Boot拥有一个微服务库,该库实际上与参与者非常接近。 与反应性类似:Spring Boot具有自己的WebFlux库,该库实现相同的功能。 我们估计亮度大约在表内。 至于语言,在这三个选项中,Vertx被认为是多种语言:它支持Java,Scala,Kotlin和JavaScript。 Akka有Scala和Java。 Kotlin可能也可以使用,但没有直接支持。 Spring有Java,Kotlin和Groovy。
结果,Vertx赢了。 顺便说一句,他们在JUG会议上谈论了很多关于他的事,实际上许多公司都在使用它。 这是开发者网站的屏幕截图:

在Vertx.io上,我们的解决方案的实现方案如下:

我们决定将参数不存储在数据库中,而是存储在Git存储库中。 由于客户端不主动请求参数,并且命中次数减少了,因此我们可以很好地使用这个相对较慢的数据源。
读取器(垂直)将数据从Git存储库读取到应用程序的内存中,以加快用户对数据的访问。 例如,在订购参数时,这一点很重要。 此外,读取器还处理更新-重新读取并标记数据,将旧数据替换为新数据。
事件总线是一种Vertx服务,可在垂直之间以及通过网桥发送事件。 包括通过websocket桥,在这种情况下使用。 当参数更改事件到达时,事件总线将它们发送给客户端。
最后,在客户端上,这里实现了一个简单的Web客户端,该客户端订阅事件(参数更改)并在页面上显示这些更改。
如何运作
我们展示了一切如何通过Web应用程序工作。
我们在浏览器中启动应用程序页面。 我们订阅关键数据更改。 然后,我们转到本地GitLab的项目页面,以JSON格式更改数据并将其保存到存储库中。 该应用程序显示我们需要的相应更改。
仅此而已。 您可以在我的
git存储库中找到该演示的源代码,并在评论中提出问题。