Vert.x 的 Apache Ignite 集群管理器

这是 Vert.x 的集群管理器实现,它使用 Apache Ignite

在 Vert.x 中,集群管理器用于多种功能,包括

  • 集群中 Vert.x 节点的发现和组成员管理

  • 维护集群范围的主题订阅者列表(以便我们知道哪些节点对哪些事件总线地址感兴趣)

  • 分布式 Map 支持

  • 分布式锁

  • 分布式计数器

集群管理器*不*处理事件总线节点间传输,这由 Vert.x 直接通过 TCP 连接完成。

Vert.x 集群管理器是一个可插拔组件,因此您可以选择您想要的,或最适合您环境的。因此,您可以用此实现替换默认的 Vert.x 集群管理器。

使用 Ignite 集群管理器

如果 jar 包在您的类路径中,Vert.x 将自动检测并将其用作集群管理器。请确保您的类路径中没有其他集群管理器,否则 Vert.x 可能会选择错误的。

或者,您可以配置以下系统属性来指示 Vert.x 使用此集群管理器:-Dvertx.clusterManagerFactory=io.vertx.spi.cluster.ignite.IgniteClusterManager

从命令行使用 Vert.x

vertx-ignite-5.0.1.jar 应位于 Vert.x 安装的 lib 目录中。

在 Maven 或 Gradle 项目中使用 Vert.x

添加对该工件的依赖。

  • Maven(在您的 pom.xml 中)

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

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

编程方式指定集群管理器

您也可以通过编程方式指定集群管理器。为此,只需在创建 Vert.x 实例时在选项中指定它,例如

ClusterManager clusterManager = new IgniteClusterManager();

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

配置集群管理器

注意:从 2.0 版本开始,Apache Ignite 引入了一种新的堆外内存架构。所有缓存默认都使用堆外内存。新的内存架构在 Ignite 虚拟内存 文章中进行了描述。

使用配置文件

集群管理器通过 jar 包中包含的 default-ignite.json 文件进行配置。

如果您想覆盖此配置,您可以在类路径中提供 ignite.json 文件,它将替代使用。该配置映射到 IgniteOptions,您可以在其中找到每个单独选项的更多详细信息。

在下面的示例中,默认配置被扩展以激活集群通信的 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();
// Configuration code (omitted)

ClusterManager clusterManager = new IgniteClusterManager(cfg);

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

发现和网络传输配置

默认配置使用 TcpDiscoveryMulticastIpFinder,因此您的网络必须启用多播。在多播被禁用时,应使用 TcpDiscoveryVmIpFinder 并预先配置 IP 地址列表。有关详细信息,请参阅 Apache Ignite 文档中的 集群配置 部分。

集群故障排除

如果默认的多播配置不起作用,以下是一些常见原因

机器上未启用多播。

默认情况下,集群管理器使用 TcpDiscoveryMulticastIpFinder,因此需要 IP 多播。在某些系统上,需要将多播路由添加到路由表,否则将使用默认路由。

请注意,某些系统不查询路由表进行 IP 多播路由,只查询单播路由

MacOS 示例

# Adds a multicast route for 224.0.0.1-231.255.255.254
sudo route add -net 224.0.0.0/5 127.0.0.1

# Adds a multicast route for 232.0.0.1-239.255.255.254
sudo route add -net 232.0.0.0/5 192.168.1.3

请在 Google 上搜索更多信息。

使用错误的网络接口

如果您的机器上有多个网络接口(如果您在机器上运行 VPN 软件也可能出现这种情况),那么 Apache Ignite 可能正在使用错误的接口。

要告诉 Ignite 使用特定接口,您可以使用 localHost 属性向 IgniteConfiguration 类型的 bean 提供该接口的 IP 地址。例如

{
  "localHost": "192.168.1.20"
}

当 Vert.x 在集群模式下运行时,您还应确保 Vert.x 知道正确的接口。在命令行中运行时,可以通过指定 cluster-host 选项来完成此操作

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

其中 your-ip-address 是您在 Apache Ignite 配置中指定的相同 IP 地址。

如果以编程方式使用 Vert.x,您可以使用 .setHost(java.lang.String) 来指定此项。

使用 VPN

这是上述情况的一种变体。VPN 软件通常通过创建虚拟网络接口来工作,而这些接口通常不支持多播。如果您正在运行 VPN,并且没有在 Ignite 配置和 Vert.x 中指定要使用的正确接口,那么可能会选择 VPN 接口而不是正确的接口。

因此,如果您正在运行 VPN,您可能需要按照上一节所述,配置 Ignite 和 Vert.x 都使用正确的接口。

当多播不可用时

在某些情况下,您可能无法使用多播,因为它在您的环境中可能不可用。在这种情况下,您应该使用相应的 IP 查找器配置另一种传输方式,例如使用 TcpDiscoveryVmIpFinder 来使用 TCP 套接字,或使用 TcpDiscoveryS3IpFinder 来使用 Amazon S3。

有关可用的 Ignite 传输及其配置方法的更多信息,请查阅 Ignite 集群 文档。

启用日志记录

在排查集群问题时,通常获取 Ignite 的日志输出以查看其是否正确形成集群是很有用的。您可以通过在类路径中添加一个名为 vertx-default-jul-logging.properties 的文件来完成此操作(使用默认的 JUL 日志记录时)。这是一个标准的 java.util.logging (JUL) 配置文件。在其中设置

org.apache.ignite.level=INFO

并且

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

JDK17 及更高版本

添加 VM 选项

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