2017-04-14 56 views
0

新手提醒。Vertx |集群中Verticle的全局状态

我试图写Vertx一个简单的模块轮询数据库(Postgres的)每10秒和推动的结果给客户端。我想在工作者Verticle中限制阻塞代码(通过JDBC查询数据库),其余的上述层完全是非阻塞和异步的。

此模块将被打包为一个罐和分配到一个不同的应用程序(通常是webapps),它可以通过的JavaScript桥订阅事件总线。

我在这里的问题是,在集群环境中,我与vertx模块运行Web应用程序的5个进程,我怎么能确保只有一个vertx verticle查询数据库。我不希望所有的Verticle查询数据库并增加更多的负载。还是有不同的思维方式来解决这个问题。我使用Vertx版本3.4.1

+0

如果您使用的是相同的事件总线名称,则在其上发布消息。只有一名工人会消耗它并开始工作。 –

+0

当然,我明白这一点。我这里的用例是我需要每10秒轮询一次数据库(意思是每隔10秒向事件总线发出一条消息,触发处理程序执行查询)。但我不希望所有的verticle在不同的进程中触发消息,从而在多个进程中触发jdbc调用。 – user1189332

+0

首先,为什么在Vert.x提供非阻塞PostGreSQL实现时使用JDBC?其次,如果你想要做的唯一事情是每x个secons查询数据库,为什么不为它创建一个单独的Verticle?你可以调用'ResultSet :: toJson'来将结果查询转换成Json并将其发布到'EventBus'的保留地址上。 –

回答

0

因此,有2种方式你如何verticle可以乘:

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

您可以尝试控制执行查询的Verticle实例的数量。意味着你确保Verticle只存在于你的一个Vert.x实例中,而你的Verticle只部署一个实例。

但是这有几个缺点:

  • 部署是不是透明的,意味着你的群集节点部署中的结构不同。
  • 如果群集节点死亡,查询verticle运行的位置,那么你有没有回退。

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

我看到3个possibilites:

  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.String-

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

  4. 您使用redis和https://redis.io/commands/getset 功能。你可以存储在米利斯的时间在一个关键和保证 与GETSET方法,即时间升级是原子。所以只有可以在redis中设置密钥的轮询模块才会执行轮询。

+0

下面是你的用例的redis getset的一个例子https://github.com/swisspush/gateleen/blob/master/gateleen-scheduler/src/main/java/org/swisspush/gateleen/scheduler/Scheduler.java# L94 – haschibaschi

0

我在这里给出了我的天真解决方案,我不知道它是否会完全解决您的问题,但这里是我的思考过程。

1)轮询位,是的,你确实可以有一个工作者verticle阻止呼叫[或者你也可以在这里使用异步位,因为你已经有Async Postgress JDBC client]每10secs部分。像这样的代码片段可以帮助你

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 

如果你真的想要非常喜欢,你可以抛出Service Discovery来确保如果Verticle的服务已经注册,那么其他部署将不会触发注册。

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