0

新手提醒。

我正在尝试在 Vertx 中编写一个简单的模块,该模块每 10 秒轮询一次数据库(PostGres)并将结果推送给客户端。我正在考虑将阻塞代码(通过 JDBC 查询数据库)限制在 worker verticle 中,并且上述层的其余部分完全是非阻塞和异步的。

该模块将打包为 jar 并分发到不同的应用程序(通常是 webapps),这些应用程序可以通过 javascript 桥订阅事件总线。

我的问题是在集群环境中,我有 5 个使用 vertx 模块运行的 webapp 进程,如何确保只有一个 vertx verticle 查询数据库。我不希望所有 Verticle 都查询数据库并增加更多负载。或者是否有不同的思考方式来解决这个问题。我正在使用 Vertx 版本 3.4.1

4

2 回答 2

0

我在这里给出我幼稚的解决方案,我不知道它是否能完全解决你的问题,但这是我的思考过程。

1)轮询位,是的,您确实可以有一个用于阻塞调用的工作节点[或者您也可以在这里使用异步位,恕我直言,因为您已经有异步 Postgress JDBC 客户端] 用于每 10 秒部分。像这样的代码片段可以帮助你

vertx.setPeriodic(10000, id -> {
  // This handler will get called every 10 seconds
  JsonObject jdbcObject = fetchFromJdbc();
  eventBus.publish("INTRESTED_PARTIES", jdbcObject); 
});

2) 对于监听部分,所有其他 verticles 都可以订阅事件总线并监听该地址,并且只要有事情发生,就会收到消息

3)这是为了确保不是所有运行的 jar 实例都开始轮询数据库,为此我认为最好的处理方法是不在任何 jar 中部署 verticle 并使用运行时 vertx 以独立方式运行 verticle命令之类的

vertx run DatabasePoller.java -cluster

如果你真的想要非常漂亮,你可以投入服务发现以确保如果垂直的服务已经注册,那么没有其他部署会触发注册。

但我想给你竖起大拇指考虑事件以获得更好的信息处理方式来处理系统间通信。

于 2017-04-22T14:39:48.290 回答
0

因此,有两种方法可以使您的 Verticle 相乘:

  1. 如果在部署 Verticle 时实例化多个实例
  2. 如果您开始将 vert.x 实例集群在不同的 jvm 或不同的主机中

您可以尝试控制执行查询的 Verticle 实例的数量。意味着您确保该 verticle 仅存在于您的 vert.x 实例之一中,并且您的 verticle 仅部署了一个实例。

但这有几个缺点:

  • 您的部署不透明,这意味着您的集群节点的部署结构不同。
  • 如果您的集群节点在运行查询垂直的位置死亡,那么您将没有后备。

所以最好的事情是,在所有实例上部署 Verticle 并同步它。

我看到了 3 种可能性:

  1. 使用hazelcast(vert.x的clustermanager)同步 http://vertx.io/docs/apidocs/io/vertx/spi/cluster/hazelcast/HazelcastClusterManager.html#getLockWithTimeout-java.lang.String-long-io。 vertx.core.Handler -
    还有可用的数据结构,它们在集群 http://vertx.io/docs/apidocs/io/vertx/spi/cluster/hazelcast/HazelcastClusterManager.html#getSyncMap-java.lang 上同步。细绳-

  2. 使用您的数据库作为同步点。您可以添加一个简单的表,以毫秒为单位存储上次执行时间。轮询模块将首先检查是否该执行下一次轮询。如果轮询模块执行轮询,它也会更新时间。这必须在一个事务中完成,并在时间表上显式锁定。

  3. 您将 redis 与https://redis.io/commands/getset 功能一起使用。您可以将时间以毫秒为单位存储在密钥中,并使用 getset 方法确保时间的升级是原子的。所以只有可以在 redis 中设置 key 的轮询模块才会执行轮询。

于 2017-04-15T05:52:08.117 回答