Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ARTEMIS-4545 Allow node ID to be configured #4951

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,16 @@ public interface Configuration {
*/
Configuration setName(String name);

/**
* Returns the ID of the node.
*/
String getNodeID();

/**
* Sets the ID of the node. If not set, a UUID generated on first startup will be used instead.
*/
Configuration setNodeID(String nodeID);

/**
* We use Bean-utils to pass in System.properties that start with {@link #setSystemPropertyPrefix(String)}.
* The default should be 'brokerconfig.' (Including the ".").
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,8 @@ public class ConfigurationImpl implements Configuration, Serializable {

private String name = "localhost";

private String nodeID = null;

private boolean persistenceEnabled = ActiveMQDefaultConfiguration.isDefaultPersistenceEnabled();

private int maxRedeliveryRecords = ActiveMQDefaultConfiguration.getDefaultMaxRedeliveryRecords();
Expand Down Expand Up @@ -2559,6 +2561,17 @@ public ConfigurationImpl setName(String name) {
return this;
}

@Override
public String getNodeID() {
return nodeID;
}

@Override
public ConfigurationImpl setNodeID(String nodeID) {
this.nodeID = nodeID;
return this;
}

@Override
public ConfigurationImpl setResolveProtocols(boolean resolveProtocols) {
this.resolveProtocols = resolveProtocols;
Expand Down Expand Up @@ -2707,6 +2720,7 @@ public int hashCode() {
result = prime * result + (int) (messageExpiryScanPeriod ^ (messageExpiryScanPeriod >>> 32));
result = prime * result + messageExpiryThreadPriority;
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((nodeID == null) ? 0 : nodeID.hashCode());
result = prime * result + ((outgoingInterceptorClassNames == null) ? 0 : outgoingInterceptorClassNames.hashCode());
result = prime * result + ((pagingDirectory == null) ? 0 : pagingDirectory.hashCode());
result = prime * result + (persistDeliveryCountBeforeDelivery ? 1231 : 1237);
Expand Down Expand Up @@ -2910,6 +2924,11 @@ public boolean equals(Object obj) {
return false;
} else if (!name.equals(other.name))
return false;
if (nodeID == null) {
if (other.nodeID != null)
return false;
} else if (!nodeID.equals(other.nodeID))
return false;
if (outgoingInterceptorClassNames == null) {
if (other.outgoingInterceptorClassNames != null)
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,8 @@ public void parseMainConfig(final Element e, final Configuration config) throws

config.setName(getString(e, "name", config.getName(), NO_CHECK));

config.setNodeID(getString(e, "node-id", config.getNodeID(), NO_CHECK));

config.setSystemPropertyPrefix(getString(e, "system-property-prefix", config.getSystemPropertyPrefix(), NOT_NULL_OR_EMPTY));

NodeList haPolicyNodes = e.getElementsByTagName("ha-policy");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,15 @@ public SimpleString getNodeId() {
}
}

/**
* Returns the converted form of a given nodeID
*
* @param nodeID
*/
public String getConvertedNodeId(String nodeID) {
return new UUID(UUID.TYPE_TIME_BASED, UUID.stringToBytes(nodeID)).toString();
}

public long readNodeActivationSequence() throws NodeManagerException {
// TODO make it abstract
throw new UnsupportedOperationException("TODO");
Expand Down Expand Up @@ -117,16 +126,14 @@ public UUID getUUID() {
}

/**
* Sets the nodeID.
* <p>
* Only used by replicating backups.
* Sets the nodeID
*
* @param nodeID
*/
public void setNodeID(String nodeID) {
synchronized (nodeIDGuard) {
this.nodeID = new SimpleString(nodeID);
this.uuid = new UUID(UUID.TYPE_TIME_BASED, UUID.stringToBytes(nodeID));
this.nodeID = new SimpleString(uuid.toString());
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -617,9 +617,35 @@ protected NodeManager createNodeManager(final File directory, boolean replicatin
} else {
manager = new FileLockNodeManager(directory, replicatingBackup, configuration.getJournalLockAcquisitionTimeout(), scheduledPool);
}

if (!replicatingBackup && configuration.getNodeID() != null) {
manager.setNodeID(toCompatibleNodeID(configuration.getNodeID()));
}

return manager;
}

private String toCompatibleNodeID(String nodeID) {
if (nodeID == null) {
return null;
}

final int len = nodeID.length();

if (!(len > 0)) {
return null;
}

if (len >= 16) {
nodeID = nodeID.substring(0, 16);
} else if (len % 2 != 0) {
// must be even for conversion to uuid, extend to next even
nodeID = nodeID + "+";
}

return nodeID.replace('-', '.');
}

@Override
public OperationContext newOperationContext() {
return getStorageManager().newContext(getExecutorFactory().getExecutor());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,9 @@ protected final synchronized void createNodeId() throws IOException {
channel.write(id, 3);
channel.force(true);
} else if (read != 16) {
setUUID(UUIDGenerator.getInstance().generateUUID());
if (getUUID() == null) {
setUUID(UUIDGenerator.getInstance().generateUUID());
}
id.put(getUUID().asBytes(), 0, 16);
id.position(0);
channel.write(id, 3);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ public ReplicationBackupActivation(final ActiveMQServerImpl activeMQServer,
// patch expectedNodeID
final String coordinationId = policy.getPrimaryPolicy().getCoordinationId();
if (coordinationId != null) {
expectedNodeID = coordinationId;
expectedNodeID = activeMQServer.getNodeManager().getConvertedNodeId(coordinationId);
} else {
final SimpleString serverNodeID = activeMQServer.getNodeID();
if (serverNodeID == null || serverNodeID.isEmpty()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,15 @@
</xsd:annotation>
</xsd:element>

<xsd:element name="node-id" type="xsd:string" maxOccurs="1" minOccurs="0">
<xsd:annotation>
<xsd:documentation>
Node ID. If set, it will be used as an identifier when running in a cluster.
Has to be unique within the cluster
</xsd:documentation>
</xsd:annotation>
</xsd:element>

<xsd:element name="system-property-prefix" type="xsd:string" maxOccurs="1" minOccurs="0">
<xsd:annotation>
<xsd:documentation>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
xsi:schemaLocation="urn:activemq ../../../../activemq-server/src/main/resources/schema/artemis-server.xsd">
<core xmlns="urn:activemq:core">
<name>SomeNameForUseOnTheApplicationServer</name>
<node-id>AUniqueIDForThisBroker</node-id>
<resolve-protocols>false</resolve-protocols>
<persistence-enabled>false</persistence-enabled>
<scheduled-thread-pool-max-size>12345</scheduled-thread-pool-max-size>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
xsi:schemaLocation="urn:activemq ../../../../activemq-server/src/main/resources/schema/artemis-server.xsd">
<core xmlns="urn:activemq:core">
<name>SomeNameForUseOnTheApplicationServer</name>
<node-id>AUniqueIDForThisBroker</node-id>
<resolve-protocols>false</resolve-protocols>
<persistence-enabled>false</persistence-enabled>
<scheduled-thread-pool-max-size>12345</scheduled-thread-pool-max-size>
Expand Down
1 change: 1 addition & 0 deletions docs/user-manual/_book.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ include::metrics.adoc[leveloffset=1]

//== Broker-to-Broker Connectivity

include::node-id.adoc[leveloffset=1]
include::core-bridges.adoc[leveloffset=1]
include::clusters.adoc[leveloffset=1]
include::federation.adoc[leveloffset=1]
Expand Down
40 changes: 40 additions & 0 deletions docs/user-manual/node-id.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
= Node ID
:idprefix:
:idseparator: -

When connecting multiple Artemis brokers together they can cooperate to solve a common task
like xref:clusters.adoc[clustering] or xref:ha.adoc[high availability] for example.

Implementation of coordination and control over which broker does what will vary between the different "Broker-to-broker Connectivity"
variants, but one important aspect is the use of a unique identifier called `node-id`.

By default, the brokers `node-id` will get generated the first time it starts up. The value is then
persisted into the `journal`, on a file called `server.lock`

This id _must_ be unique among all brokers to ensure proper functionality.


== Manually setting the brokers ID

In certain cases, being able to manually set a `node-id` rather than generating one can be preferable. Brokers running in
an environment where their storage is ephemeral would be one such case. This is because any time a broker is restarted, moved
or upgraded it could end up with a new disk and therefore also a new journal. Starting this broker up, while being configured
identiaclly, would still give it a new `node-id`. In some configurations, this means the broker won't be able to resume
whatever role it orinially had because the other broker it was connected to prior will look for the original `node-id`.

To handle these scenarios `node-id` can be set in the `broker.xml` configuration file.
[,xml]
----
<node-id>myUniqueID</node-id>
----

The selected nodeID will get converted internally into a 16-byte UUID. Therefore it might not be recognizeable to
someone looking for it in logs or the console.

The `node-id` has to be set before first starting the broker as this value will get persisted in the brokers `journal`.
Once persisted, this is the value that the broker will use regardless of configuration.

[WARNING]
====
If you choose to set `node-id` manually, it's uniqueness among other brokers are _UTMOST_ important.
====
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,7 @@ protected ConfigurationImpl createBasicConfig() throws Exception {

protected ConfigurationImpl createBasicConfig(final int serverID) {
ConfigurationImpl configuration = new ConfigurationImpl().setSecurityEnabled(false).setJournalMinFiles(2).setJournalFileSize(100 * 1024).setJournalType(getDefaultJournalType()).setJournalDirectory(getJournalDir(serverID, false)).setBindingsDirectory(getBindingsDir(serverID, false)).setPagingDirectory(getPageDir(serverID, false)).setLargeMessagesDirectory(getLargeMessagesDir(serverID, false)).setJournalCompactMinFiles(0).setJournalCompactPercentage(0).setClusterPassword(CLUSTER_PASSWORD).setJournalDatasync(false);
configuration.setNodeID("node-" + serverID);

// When it comes to the testsuite, we don't need any batching, I will leave some minimal batching to exercise the codebase
configuration.setJournalBufferTimeout_AIO(100).setJournalBufferTimeout_NIO(100);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,7 @@ protected Configuration createPrimaryConfiguration() throws Exception {
conf.addClusterConfiguration(ccconf);

conf.setSecurityEnabled(false).setJMXManagementEnabled(false).setJournalType(JournalType.MAPPED).setJournalFileSize(1024 * 512).setConnectionTTLOverride(60_000L);
conf.setNodeID("localhost::primary");

return conf;
}
Expand Down Expand Up @@ -300,6 +301,7 @@ protected Configuration createBackupConfiguration() throws Exception {
conf.addClusterConfiguration(ccconf);

conf.setSecurityEnabled(false).setJMXManagementEnabled(false).setJournalType(JournalType.MAPPED).setJournalFileSize(1024 * 512).setConnectionTTLOverride(60_000L);
conf.setNodeID("localhost::backup");

return conf;
}
Expand Down
Loading