Vertx |群集中的全局Verticle状态

时间:2017-04-14 05:25:08

标签: vert.x vertx-httpclient

新手警报。

我正在尝试在Vertx中编写一个简单的模块,每隔10秒轮询数据库(PostGres)并将结果推送到客户端。我正在考虑将阻塞代码(通过JDBC查询数据库)限制在工作者Verticle中,并且上面的其他层完全是非阻塞和异步的。

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

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

2 个答案:

答案 0 :(得分:0)

因此,有两种方法可以将Verticle乘以:

  1. 如果在部署Verticle时实例化多个实例
  2. 如果您开始将vert.x实例集中在不同的jvm或不同的主机
  3. 您可以尝试控制执行查询的Verticle实例的数量。意味着您确保Verticle仅存在于您的某个vert.x实例中,并且您的Verticle仅部署了一个实例。

    但这有几个缺点:

    • 您的部署不透明,意味着您的群集节点在部署结构上有所不同。
    • 如果您的群集节点死亡,正在运行查询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.String-

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

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

答案 1 :(得分:0)

我在这里给出了天真的解决方案,我不知道它是否能彻底解决你的问题,但这是我的思考过程。

1)轮询位,是的确你可以有一个工作者Verticle来阻止调用[或者你也可以在这里使用Async位恕我直言,因为你已经有了每个10secs部分的Async Postgress JDBC client]。像这样的代码片段可以帮到你

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

2)对于收听部分,所有其他Verticle都可以订阅事件总线并监听该地址,并在发生任何事情时收到消息

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

vertx run DatabasePoller.java -cluster

如果你真的想要非常喜欢,你可以投入Service Discovery以确保如果Verticle的服务已经注册,则没有其他部署会触发注册。

但是我想让你大胆地考虑一下这些信息,以便更好地处理系统间通信。