分布式集群管理
你当前正在浏览历史版本 Vert.x 4.5.35 的文档。 访问本页面的 最新版本。

Apache Ignite 集群管理器 (vertx-ignite)

该组件为 Vert.x 提供了基于 Apache Ignite 的集群管理器(Cluster Manager)实现。

在 Vert.x 中,集群管理器承担以下核心协作职责:

  • 集群中 Vert.x 节点的自动发现与成员拓扑维护

  • 维护全集群范围的 Event Bus 主题订阅者映射表(以便获知哪些节点对哪些 Event Bus 地址感兴趣)

  • 分布式映射(Distributed Map)支持

  • 分布式锁(Distributed Locks)

  • 分布式计数器(Distributed Counters)

请注意:集群管理器并不负责节点间的 Event Bus 实际消息传输;节点间的数据通信由 Vert.x 直接通过底层的 TCP 连接通道高效完成。

Vert.x 集群管理器是完全可插拔的可选组件,你可以根据基础设施环境自由选用最合适的实现,因此可以使用本模块无缝替换 Vert.x 默认的集群管理器。

使用 Ignite 集群管理器

若该 jar 包位于你的类路径(Classpath)中,Vert.x 在启动集群模式时将自动检测并将其激活为集群管理器。 请确保类路径中未引入其他集群管理器实现,以避免 Vert.x 误选其他集群组件。

或者,你也可以通过配置以下系统属性显式指示 Vert.x 使用该集群管理器: -Dvertx.clusterManagerFactory=io.vertx.spi.cluster.ignite.IgniteClusterManager

在命令行中使用 Vert.x

将 vertx-ignite-5.0.12.jar 放置在 Vert.x 安装目录下的 lib 目录中。

在 Maven 或 Gradle 工程中使用

在构建描述文件中添加以下依赖项:

  • Maven(在 pom.xml 中):

<dependency>
  <groupId>io.vertx</groupId>
  <artifactId>vertx-ignite</artifactId>
  <version>5.0.12</version>
</dependency>
  • Gradle(在 build.gradle 文件中):

compile 'io.vertx:vertx-ignite:5.0.12'

以编程方式指定集群管理器

你也可以完全通过代码以编程方式指定集群管理器,只需在创建 Vert.x 实例时将其配置在 Options 中即可:

ClusterManager clusterManager = new IgniteClusterManager();

VertxOptions options = new VertxOptions().setClusterManager(clusterManager);
Vertx.clusteredVertx(options, res -> {
  if (res.succeeded()) {
    Vertx vertx = res.result();
    // 集群实例启动成功
  } else {
    // 启动失败!
  }
});

配置集群管理器

提示:从 2.0 版本开始,Apache Ignite 引入了全新的堆外内存(Off-Heap Memory)架构,所有缓存默认均使用堆外内存。新内存架构的详细说明请参阅 Ignite 虚拟内存 (Ignite Virtual Memory) 文档。

使用配置文件

集群管理器默认加载打包在 jar 内部的 default-ignite.json 配置文件。

若需覆盖该默认配置,可以在类路径根目录下提供自定义的 ignite.json 文件。配置结构与 IgniteOptions 映射对应,你可以在该类的 API 文档中查看每个具体配置项的含义。

在以下示例中,默认配置被扩展以启用集群内部通信的 TLS 安全加密:

{
  "cacheConfiguration": [{
    "name": "__vertx.*",
    "cacheMode": "REPLICATED",
    "atomicityMode": "ATOMIC",
    "writeSynchronizationMode": "FULL_SYNC"
  }, {
    "name": "*",
    "cacheMode": "PARTITIONED",
    "backups": 1,
    "readFromBackup": false,
    "atomicityMode": "ATOMIC",
    "writeSynchronizationMode": "FULL_SYNC"
  }],
  "sslContextFactory": {
    "protocol": "TLSv1.2",
    "jksKeyCertOptions": {
      "path": "server.jks",
      "password": "changeme"
    },
    "jksTrustOptions": {
      "path": "server.jks",
      "password": "changeme"
    },
    "trustAll": false
  },
  "metricsLogFrequency": 0,
  "shutdownOnSegmentation": true
}

除了 JSON 格式外,你也可以选择使用 Ignite 原生的 XML 配置格式。在类路径下提供 ignite.xml 文件即可生效。

首先,添加 ignite-spring 依赖:

  • Maven(在 pom.xml 中):

<dependency>
  <groupId>org.apache.ignite</groupId>
  <artifactId>ignite-spring</artifactId>
  <version>${ignite.version}</version>
</dependency>
  • Gradle(在 build.gradle 文件中):

compile 'org.apache.ignite:ignite-spring:${ignite.version}'

然后添加类似如下的 ignite.xml 配置文件:

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/util
                           http://www.springframework.org/schema/util/spring-util.xsd">

  <bean class="org.apache.ignite.configuration.IgniteConfiguration">

    <property name="discoverySpi">
      <bean class="org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi">
        <property name="ipFinder">
          <bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.multicast.TcpDiscoveryMulticastIpFinder"/>
        </property>
      </bean>
    </property>

    <property name="cacheConfiguration">
      <list>
        <bean class="org.apache.ignite.configuration.CacheConfiguration">
          <property name="name" value="__vertx.*"/>
          <property name="cacheMode" value="REPLICATED"/>
          <property name="atomicityMode" value="ATOMIC"/>
          <property name="writeSynchronizationMode" value="FULL_SYNC"/>
        </bean>
        <bean class="org.apache.ignite.configuration.CacheConfiguration">
          <property name="name" value="*"/>
          <property name="cacheMode" value="PARTITIONED"/>
          <property name="backups" value="1"/>
          <property name="readFromBackup" value="false"/>
          <property name="atomicityMode" value="ATOMIC"/>
          <property name="affinity">
            <bean class="org.apache.ignite.cache.affinity.rendezvous.RendezvousAffinityFunction">
              <property name="partitions" value="128"/>
            </bean>
          </property>
          <property name="writeSynchronizationMode" value="FULL_SYNC"/>
        </bean>
      </list>
    </property>

    <property name="gridLogger">
      <bean class="io.vertx.spi.cluster.ignite.impl.VertxLogger"/>
    </property>

    <property name="metricsLogFrequency" value="0"/>
  </bean>
</beans>

JSON 格式是 XML 配置的精简版本,更多底层细节请参阅 Apache Ignite 官方文档。

以编程方式配置

你也可以完全通过代码构造配置:

IgniteConfiguration cfg = new IgniteConfiguration();
// 配置属性代码(此处省略)

ClusterManager clusterManager = new IgniteClusterManager(cfg);

VertxOptions options = new VertxOptions().setClusterManager(clusterManager);
Vertx.clusteredVertx(options, res -> {
  if (res.succeeded()) {
    Vertx vertx = res.result();
  } else {
    // 启动失败!
  }
});

节点发现与网络传输配置

默认配置使用 TcpDiscoveryMulticastIpFinder 进行节点发现,因此你的局域网必须开启组播(Multicast)功能。 在禁用组播的环境中,应使用 TcpDiscoveryVmIpFinder 配合预先配置好的静态 IP 列表。更多详情请参阅 Apache Ignite 官方文档中的 集群配置 (Cluster Configuration) 章节。

集群故障排查指南

如果默认的组播配置无法正常组网,请按以下常见原因排查:

1. 主机未开启组播路由

集群管理器默认依赖 TcpDiscoveryMulticastIpFinder,需要系统支持 IP 组播。在某些操作系统中,必须向系统路由表中手动添加组播路由规则,否则会走默认路由导致无法发现对端节点。

请注意:某些操作系统不会针对 IP 组播查询路由表,而仅针对单播查询。

macOS 示例:

# 为 224.0.0.1 - 231.255.255.254 添加组播路由:
sudo route add -net 224.0.0.0/5 127.0.0.1

# 为 232.0.0.1 - 239.255.255.254 添加组播路由:
sudo route add -net 232.0.0.0/5 192.168.1.3

2. 绑定了错误的网络网卡

如果机器上存在多个网络接口(例如安装了虚拟网卡或处于多网卡环境),Apache Ignite 可能会选错绑定的物理/虚拟网卡。

要指定 Ignite 使用特定网卡,可以在 IgniteConfiguration 中通过 localHost 属性显式指定该网卡的 IP 地址,例如:

{
  "localHost": "192.168.1.20"
}

在集群模式下运行 Vert.x 时,还必须确保 Vert.x Event Bus 同样绑定到正确的网络接口。在命令行中可以通过 cluster-host 参数显式指定:

vertx run myverticle.js -cluster -cluster-host your-ip-address

其中 your-ip-address 应与 Apache Ignite 配置中指定的 IP 地址保持一致。

若在代码中嵌入运行,可以通过 options.getEventBusOptions().setHost(ip) 进行设置。

3. VPN 软件网络干扰

VPN 软件通常会创建虚拟网络接口,而这些虚拟接口往往不支持组播。若运行了 VPN 且未在 Ignite 和 Vert.x 中显式指定正确的物理网卡,系统可能会错误选择 VPN 虚拟网卡导致组网失败。

解决方法同上一小节:显式配置 Ignite 与 Vert.x 绑定至真实的物理局域网网卡 IP。

4. 生产环境不支持组播时的替代方案

在公有云容器等生产环境中,组播通常被网络基础设施直接屏蔽。此时应切换为对应的静态或云端 IP 发现器,例如使用 TcpDiscoveryVmIpFinder 通过 TCP Socket 静态列表组网,或使用 TcpDiscoveryS3IpFinder 借助 AWS S3 对象存储发现节点。

更多关于 Ignite 支持的传输机制及其配置方法,请参阅 Ignite 集群官方文档。

5. 开启调试日志

在排查集群故障时,获取 Ignite 的详细运行时日志有助于判断节点组网是否成功。若使用默认的 JUL 日志,可以在类路径中添加 vertx-default-jul-logging.properties 文件并配置:

org.apache.ignite.level=INFO

同时开启控制台或文件输出处理器:

java.util.logging.ConsoleHandler.level=INFO
java.util.logging.FileHandler.level=INFO

6. JDK 17 及更高版本的模块反射参数

在 JDK 17+ 运行时环境下,需要为 JVM 追加以下开放模块反射权限参数:

--add-opens=java.base/java.nio=ALL-UNNAMED
--add-opens=java.base/java.util=ALL-UNNAMED
--add-opens=java.base/java.lang.invoke=ALL-UNNAMED
--add-opens=java.base/java.lang=ALL-UNNAMED