Hazelcast offers great distributed structures as well as a great computing grid solution for java applications (or not ;)). However, it default startup is quite slow and uses multicast. Even if you can make the port random and the cluster specific to your test to kind of isolate the concurrent runs, it still adds latency in your dev flow. Let see how to reduce it.

The trick to reduce hazelcast startup time is to use an "embedded discovery strategy". In other words, we will drop the join feature for tests using a single instance.

The first step is to implement a mock of DiscoveryStrategyFactory and DiscoveryStrategy. It can be as simple as this class:

public class LocalDiscoveryStrategy implements DiscoveryStrategyFactory, DiscoveryStrategy {
    @Override
    public Class<? extends DiscoveryStrategy> getDiscoveryStrategyType() {
        return LocalDiscoveryStrategy.class;
    }

    @Override
    public DiscoveryStrategy newDiscoveryStrategy(final DiscoveryNode discoveryNode, final ILogger logger,
                                                  final Map<String, Comparable> properties) {
        return this;
    }

    @Override
    public Collection<PropertyDefinition> getConfigurationProperties() {
        return emptyList();
    }

    @Override
    public void start() {
        // no-op
    }

    @Override
    public Iterable<DiscoveryNode> discoverNodes() {
        return emptyList();
    }

    @Override
    public void destroy() {
        // no-op
    }

    @Override
    public PartitionGroupStrategy getPartitionGroupStrategy() {
        return null;
    }

    @Override
    public Map<String, String> discoverLocalMetadata() {
        return emptyMap();
    }
}

Then, we must register it to let hazelcast find it so we add its fully qualified name in META-INF/services/com.hazelcast.spi.discovery.DiscoveryStrategyFactory.

Finally we create a hazelcast.xml disabling multicasting and using this discovery stategy with no wait before join:

<?xml version="1.0" encoding="UTF-8"?>
<hazelcast xmlns="http://www.hazelcast.com/schema/config"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="
            http://www.hazelcast.com/schema/config
            http://www.hazelcast.com/schema/config/hazelcast-config-4.1.xsd">
  <cluster-name>test</cluster-name>
  <instance-name>test-1</instance-name>
  <properties> <!-- 1 -->
    <property name="hazelcast.discovery.enabled">true</property>
    <property name="hazelcast.wait.seconds.before.join">0</property>
  </properties>
  <network>
    <port>0</port> <!-- 2 -->
    <join>
      <auto-detection/> <!-- 3 -->
      <multicast enabled="false" /> <!-- 4 -->
      <discovery-strategies> <!-- 5 -->
        <discovery-strategy enabled="true"
                            class="com.rmannibucau.github.hazelcast.test.LocalDiscoveryStrategy" />
      </discovery-strategies>
    </join>
  </network>
  <cp-subsystem> <!-- 6 -->
    <cp-member-count>3</cp-member-count>
  </cp-subsystem>
</hazelcast>
  1. We enable, through properties, custom discovery of members and disable the waiting time before join call (see hazelcast joiner).
  2. We use a random port since for test it is ok to use any available port (setting 0 means random on java socket).
  3. We must enable auto detection to use our discovery strategy.
  4. We disable multicast otherwise hazelcast will use it.
  5. We define our custom strategy.
  6. Not required for this blog post but defining 3 for cp-subsystem member count enables to get rid of some warnings during startup.

With that the hazelcast startup is reduced significantly (-2s on my machine) and makes testing and retesting way simpler, in particular during development iterations where you run tests quite often to check your changes.

Another alternative - but hazelcast considers it is an "error" (it logs a warning) - is to disable port auto-increment and disable autodetection, this will be even faster than previous option -  but believe me it is about us so not sure you see the difference in practise.

Here is the hazelcast.xml for that last option:

<?xml version="1.0" encoding="UTF-8"?>
<hazelcast xmlns="http://www.hazelcast.com/schema/config"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="
            http://www.hazelcast.com/schema/config
            http://www.hazelcast.com/schema/config/hazelcast-config-4.1.xsd">
  <cluster-name>test</cluster-name>
  <instance-name>test-1</instance-name>
  <network> <!-- all happens there -->
    <port auto-increment="false">0</port>
    <join>
      <auto-detection enabled="false"/>
    </join>
  </network>
  <cp-subsystem>
    <cp-member-count>3</cp-member-count>
  </cp-subsystem>
</hazelcast>

The choice between both options mainly depends if you accept the warnings in the logs or not and if you want to code or not a custom discovery strategy.

Last point: all this post blog was done with hazelcast 4.1 (hope it is simpler/integrated in future versions ;)).

From the same author:

In the same category: