Skip to main content
编辑本页

InfinispanClusterManager 是基于 Infinispan 实现。

This implementation is packaged inside:

  • Maven (在 pom.xml 文件中):

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

compile 'io.vertx:vertx-infinispan:3.6.2'

Vert.x 集群管理器包含以下几个功能:

  • 发现并管理集群中的节点

  • 管理集群端的主题订阅清单(这样就可以轻松得知集群中的那些节点订阅了那些 EventBus 地址)

  • 分布式 Map 支持

  • 分布式锁

  • 分布式计数器

Vert.x 集群器并不处理节点之间的通信,在 Vert.x 中节点中的通信是直接由 TCP 链接处理的。

使用 Infinispan cluster manager

Vert.x 能够从 classpath 路径的 jar 自动检测并使用出 ClusterManager 的实现。不过需要确保在 classpath 没有其他的 ClusterManager 实现。

If you want clustering with this cluster manager in your Vert.x Maven or Gradle project then just add a dependency to the artifact: io.vertx:vertx-infinispan:3.6.2 in your project.

If the jar is on your classpath as above then Vert.x will automatically detect this and use it as the cluster manager. Please make sure you don’t have any other cluster managers on your classpath or Vert.x might choose the wrong one.

You can also specify the cluster manager programmatically if you are embedding Vert.x by specifying it on the options when you are creating your Vert.x instance, for example:

ClusterManager mgr = new InfinispanClusterManager();

VertxOptions options = new VertxOptions().setClusterManager(mgr);

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

配置 Infinispan cluster manager

The default cluster manager configuration can be modified with infinispan.xml and/or jgroups.xml files. The former configures the data grid, the latter group management and member discovery.

如果要覆盖其中任意一个配置文件,可以在 classpath 中添加对应的文件。 如果想在 fat jar 中内嵌相应的配置文件 ,此文件必须在 fat jar 的根目录中。 如果此文件是一个外部文件,则必须将其添加至 classpath 中。举个例子:

#  infinispan.xml 和/或 jgroups.xml 在当前路径中
java -jar my-app.jar -cp . -cluster

# infinispan.xml 和/或 jgroups.xml 在 conf 目录中
java -jar my-app.jar -cp conf -cluster

还有一种方式来覆盖默认的配置文件,那就是利用系统配置 vertx.infinispan.config 和/或 vertx.jgroups.config 来实现:

# 指定一个外部文件为自定义配置文件
java -Dvertx.infinispan.config=./config/my-infinispan.xml -jar ... -cluster

# 从 classpath 中加载一个文件为自定义配置文件
java -Dvertx.infinispan.config=my/package/config/my-infinispan.xml -jar ... -cluster

The cluster manager will search for the file in classpath first, and fallback to the filesystem.

The system properties, when present, override any infinispan.xml or jgroups.xml on the classpath.

The xml files are Infinispan and JGroups configuration files and are described in detail in the documentation on the Infinispan and JGroups web-sites.

Important
if a jgroups.xml file is on the classpath or if you set the vertx.jgroups.config system property, it will override any JGroups stack-file path defined in the Infinispan configuration file.

The default JGroups configuration uses multicast for discovery and TCP for group management. Make sure multicast is enabled on your network for this to work.

For full documentation on how to configure the transport differently or use a different transport please consult the Infinispan / JGroups documentations.

使用已有 Infinispan Cache Manager

开发者可以通过 DefaultCacheManager 来复用已经存在的 cache manager

ClusterManager mgr = new InfinispanClusterManager(cacheManager);

VertxOptions options = new VertxOptions().setClusterManager(mgr);

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

在这种情况下,Vert.x 并不是 cache manager 的所有者,因此不能在关闭 Vert.x 时,停止 Infinispan 。

需要注意的是,需要通过如下配置来自定义 Infinispan 实例:

<cache-container default-cache="distributed-cache">
 <distributed-cache name="distributed-cache"/>
 <distributed-cache name="__vertx.subs"/>
 <replicated-cache name="__vertx.haInfo"/>
 <distributed-cache-configuration name="__vertx.distributed.cache.configuration"/>
</cache-container>

Configuring for Kubernetes

On Kubernetes, JGroups should be configured to use the KUBE_PING protocol.

First, add the org.infinispan:infinispan-cloud:${infinispan.version} and org.jgroups.kubernetes:jgroups-kubernetes:${jgroups.kubernetes.version} dependencies to your project. With Maven it looks like:

<dependency>
 <groupId>org.infinispan</groupId>
 <artifactId>infinispan-cloud</artifactId>
 <version>${infinispan.version}</version>
</dependency>
<dependency>
 <groupId>org.jgroups.kubernetes</groupId>
 <artifactId>jgroups-kubernetes</artifactId>
 <version>${jgroups.kubernetes.version}</version>
</dependency>
<dependency>

Then, set the vertx.jgroups.config system property to default-configs/default-jgroups-kubernetes.xml.

-Dvertx.jgroups.config=default-configs/default-jgroups-kubernetes.xml

This JGroups stack file is located in the infinispan-cloud JAR and preconfigured for Kubernetes.

Also, set the project namespace as the scope for discovery.

ENV KUBERNETES_NAMESPACE my-project

Optionnaly, to create separate clusters in the same namespace, add a labels selector:

ENV KUBERNETES_LABELS my-label=my-value

Then, force usage of IPv4 in the JVM with a system property.

-Djava.net.preferIPv4Stack=true

Eventually, the setup needs a service account.

oc policy add-role-to-user view system:serviceaccount:$(oc project -q):default -n $(oc project -q)

Further configuration details are available on the Kubernetes discovery protocol for JGroups repository.

Rolling updates

During rolling udpates, the Infinispan team recommends to replace pods one by one.

To do so, we must configure Kubernetes to:

  • never start more than one new pod at once

  • forbid more than one unavailable pod during the process

spec:
 strategy:
   type: Rolling
   rollingParams:
     updatePeriodSeconds: 10
     intervalSeconds: 20
     timeoutSeconds: 600
     maxUnavailable: 1 (1)
     maxSurge: 1 (2)
  1. the maximum number of pods that can be unavailable during the update process

  2. the maximum number of pods that can be created over the desired number of pods

Also, pod readiness probe must take cluster health into account. Indeed, when a node joins or leaves the cluster, Infinispan rebalances the data across members, and it is better to avoid concurrent state transfers. When the state transfer completes, the cluster health goes back to HEALTHY.

The readiness probe can be implemented with Vert.x Health Checks:

Handler<Future<Status>> procedure = ClusterHealthCheck.createProcedure(vertx, true);
HealthChecks checks = HealthChecks.create(vertx).register("cluster-health", procedure);

After creation, it can be exposed over HTTP with a Vert.x Web router handler:

Router router = Router.router(vertx);
router.get("/readiness").handler(HealthCheckHandler.createWithHealthChecks(checks));

适配 Docker Compose

确认 JVM 在启动时 设置了下面两项配置:

-Djava.net.preferIPv4Stack=true -Djgroups.tcp.address=NON_LOOPBACK

通过上述两项系统配置,JGroups 才能正确的挑选出 Docker 创建的虚拟网络接口。

故障排除

If the default multicast discovery configuration is not working here are some common causes:

组播未正常开启

MacOS 默认禁用组播。Google一下启用组播。

使用错误的网络接口

如果机器上有多个网络接口(也有可能是在运行 VPN 的情况下),那么 JGroups 很有可能是使用了错误的网络接口。

为了确保 JGroups 使用正确的网络接口,在配置文件中将 bind_addr 设置为指定IP地址。 例如:

<TCP bind_addr="192.168.1.20"
    ...
    />
<MPING bind_addr="192.168.1.20"
    ...
    />

另外,如果需要修改打包好的 jgoups.xml 文件,可以通过设置 jgroups.tcp.address 系统变量来达到目的

-Djgroups.tcp.address=192.168.1.20

当运行集群模式时,需要确保 Vert.x 使用正确的网络接口。 当通过命令行模式时,可以设置 cluster-host 参数:

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

其中 your-ip-address 必须与 JGroup 中的配置保持一致。

当通过编程模式使用 Vert.x 时,可以调用方法 setClusterHost 来设置参数

使用VPN

VPN软件通常通过创建不支持多播虚拟网络接口来进行工作。如果有一个 VPN 运行,如果 JGroups与 Vert.x 不正确配置的话,VPN接口将被选择,而不是正确的接口。

所以,如果你运行在 VPN 环境中,参考上述章节,设置正确的网络接口。

组播被禁用

在某些情况下,因为特殊的运行环境,可能无法使用组播。在这种情况下,应该配置其他网络传输协议,例如在 TCP 上使用 TCPPING ,在亚马逊云上使用 S3_PING

有关 JGroups 更多传输方式,以及如何配置它们,请咨询 JGroups文档

IPv6 错误

如果在 IPv6 地址配置有难点,请通过 java.net.preferIPv4Stack 配置强制使用 IPv4:

-Djava.net.preferIPv4Stack=true

Infinispan 日志配置

在排除故障时,开启 Infinispan 和 JGroups 日志,将会给予很大的帮助。在 classpath 中添加 vertx-default-jul-logging.properties 文件(默认的JUL记录时),这是一个标准 java.util.loging(JUL) 配置文件。具体配置如下:

org.infinispan.level=INFO
org.jgroups.level=INFO

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

Infinispan logging

Infinispan 依赖与 JBoss Logging 。JBoss Logging 是一个与多种日志框架的桥接器。

JBoss Logging 能够自动检测使用 classpath 中 JARS 中的日志框架实现。

如果在 classpath 有多种日志框架,可以通过设置系统变量 org.jboss.logging.provider 来指定具体的实现,例子:

-Dorg.jboss.logging.provider=log4j2

更多配置信息请参考 JBoss Logging guide

JGroups 日志配置

JGroups 默认采用 JDK Logging 实现。同时也支持 log4j 与 log4j2 ,如果相应的 jar 包 在 classpath 中。

如果想查阅更详细的信息,或实现自己的日志后端,请参考 JGroups 日志文档

SharedData extensions

AsyncMap content streams

The InfinispanAsyncMap API allows to retrieve keys, values and entries as streams. This can be useful if you need to go through the content of a large map for bulk processing.

InfinispanAsyncMap<K, V> infinispanAsyncMap = InfinispanAsyncMap.unwrap(asyncMap);
ReadStream<K> keyStream = infinispanAsyncMap.keyStream();
ReadStream<V> valueStream = infinispanAsyncMap.valueStream();
ReadStream<Map.Entry<K, V>> entryReadStream = infinispanAsyncMap.entryStream();