mirror of
https://github.com/corda/corda.git
synced 2025-06-13 04:38:19 +00:00
Ent 1394 ha artemis (#1428)
* ENT-1394: artemis locators for HA bases on configuration * ENT-1394: bridge artemis connection service with HA impl * ENT-1394: added own round robin logic for artemis client connections * ENT-1394: added support for external clustered artemis to internal RPC client * ENT-1394: added failover listener to internal rpc client, some cleanup * ENT-1394: remove unused import * ENT-1394: refactored after rebasing * ENT-1394: refactored after rebasing, addressed PR comments * ENT-1394: got rid of HA connection service in favor of a simple check inside current one * ENT-1394: ha locator gets its own thread to handle failover that happens behind the scenes * ENT-1394: move ha artemis flag in the outboundConfig * ENT-1394: haArtemis flag has default value in constructor * ENT-1394: address PR comment, handle status change during failover * ENT-1394: reverted usage of ha locator * ENT-1394: ensure that on failover the p2pclient sends a fresh snapshot to the bridge
This commit is contained in:
@ -4,6 +4,8 @@ import net.corda.core.serialization.internal.nodeSerializationEnv
|
||||
import net.corda.core.utilities.NetworkHostAndPort
|
||||
import net.corda.core.utilities.loggerFor
|
||||
import net.corda.nodeapi.internal.ArtemisMessagingComponent.Companion.NODE_P2P_USER
|
||||
import net.corda.nodeapi.internal.ArtemisTcpTransport.Companion.p2pConnectorTcpTransport
|
||||
import net.corda.nodeapi.internal.ArtemisTcpTransport.Companion.p2pConnectorTcpTransportFromList
|
||||
import net.corda.nodeapi.internal.config.ExternalBrokerConnectionConfiguration
|
||||
import net.corda.nodeapi.internal.config.MutualSslConfiguration
|
||||
import org.apache.activemq.artemis.api.core.client.ActiveMQClient
|
||||
@ -22,7 +24,8 @@ class ArtemisMessagingClient(private val config: MutualSslConfiguration,
|
||||
private val autoCommitSends: Boolean = true,
|
||||
private val autoCommitAcks: Boolean = true,
|
||||
private val confirmationWindowSize: Int = -1,
|
||||
private val externalBrokerConnectionConfig: ExternalBrokerConnectionConfiguration? = null
|
||||
private val externalBrokerConnectionConfig: ExternalBrokerConnectionConfiguration? = null,
|
||||
private val backupServerAddressPool: List<NetworkHostAndPort> = emptyList()
|
||||
) : ArtemisSessionProvider {
|
||||
companion object {
|
||||
private val log = loggerFor<ArtemisMessagingClient>()
|
||||
@ -35,10 +38,15 @@ class ArtemisMessagingClient(private val config: MutualSslConfiguration,
|
||||
|
||||
override fun start(): Started = synchronized(this) {
|
||||
check(started == null) { "start can't be called twice" }
|
||||
val tcpTransport = p2pConnectorTcpTransport(serverAddress, config)
|
||||
val backupTransports = p2pConnectorTcpTransportFromList(backupServerAddressPool, config)
|
||||
|
||||
log.info("Connecting to message broker: $serverAddress")
|
||||
// TODO Add broker CN to config for host verification in case the embedded broker isn't used
|
||||
val tcpTransport = ArtemisTcpTransport.p2pConnectorTcpTransport(serverAddress, config)
|
||||
val locator = ActiveMQClient.createServerLocatorWithoutHA(tcpTransport).apply {
|
||||
if (backupTransports.isNotEmpty()) {
|
||||
log.info("Back-up message broker addresses: $backupServerAddressPool")
|
||||
}
|
||||
// If back-up artemis addresses are configured, the locator will be created using HA mode.
|
||||
val locator = ActiveMQClient.createServerLocator(backupTransports.isNotEmpty(), *(listOf(tcpTransport) + backupTransports).toTypedArray()).apply {
|
||||
// Never time out on our loopback Artemis connections. If we switch back to using the InVM transport this
|
||||
// would be the default and the two lines below can be deleted.
|
||||
connectionTTL = 60000
|
||||
@ -47,6 +55,7 @@ class ArtemisMessagingClient(private val config: MutualSslConfiguration,
|
||||
isUseGlobalPools = nodeSerializationEnv != null
|
||||
confirmationWindowSize = this@ArtemisMessagingClient.confirmationWindowSize
|
||||
externalBrokerConnectionConfig?.let {
|
||||
connectionLoadBalancingPolicyClassName = RoundRobinConnectionPolicy::class.java.canonicalName
|
||||
reconnectAttempts = externalBrokerConnectionConfig.reconnectAttempts
|
||||
retryInterval = externalBrokerConnectionConfig.retryInterval.toMillis()
|
||||
retryIntervalMultiplier = externalBrokerConnectionConfig.retryIntervalMultiplier
|
||||
|
@ -130,6 +130,10 @@ class ArtemisTcpTransport {
|
||||
return TransportConfiguration(connectorFactoryClassName, options)
|
||||
}
|
||||
|
||||
fun p2pConnectorTcpTransportFromList(hostAndPortList: List<NetworkHostAndPort>, config: MutualSslConfiguration?, enableSSL: Boolean = true): List<TransportConfiguration> = hostAndPortList.map {
|
||||
p2pConnectorTcpTransport(it, config, enableSSL)
|
||||
}
|
||||
|
||||
fun rpcAcceptorTcpTransport(hostAndPort: NetworkHostAndPort, config: BrokerRpcSslOptions?, enableSSL: Boolean = true): TransportConfiguration {
|
||||
val options = defaultArtemisOptions(hostAndPort).toMutableMap()
|
||||
|
||||
@ -160,6 +164,7 @@ class ArtemisTcpTransport {
|
||||
return TransportConfiguration(connectorFactoryClassName, defaultArtemisOptions(hostAndPort) + defaultSSLOptions + config.toTransportOptions())
|
||||
}
|
||||
|
||||
|
||||
fun rpcInternalAcceptorTcpTransport(hostAndPort: NetworkHostAndPort, config: SslConfiguration): TransportConfiguration {
|
||||
return TransportConfiguration(acceptorFactoryClassName, defaultArtemisOptions(hostAndPort) + defaultSSLOptions + config.toTransportOptions())
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
package net.corda.nodeapi.internal
|
||||
|
||||
import org.apache.activemq.artemis.api.core.client.loadbalance.ConnectionLoadBalancingPolicy
|
||||
import java.nio.file.FileSystems
|
||||
import java.nio.file.Path
|
||||
|
||||
@ -16,3 +17,18 @@ fun Path.requireOnDefaultFileSystem() {
|
||||
fun requireMessageSize(messageSize: Int, limit: Int) {
|
||||
require(messageSize <= limit) { "Message exceeds maxMessageSize network parameter, maxMessageSize: [$limit], message size: [$messageSize]" }
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of an Artemis load balancing policy. It does round-robin always starting from the first position, whereas
|
||||
* the current [RoundRobinConnectionLoadBalancingPolicy] in Artemis picks the starting position randomly. This can lead to
|
||||
* attempting to connect to an inactive broker on the first attempt, which can cause start-up delays depending on what connection
|
||||
* settings are used.
|
||||
*/
|
||||
class RoundRobinConnectionPolicy : ConnectionLoadBalancingPolicy {
|
||||
private var pos = 0
|
||||
|
||||
override fun select(max: Int): Int {
|
||||
pos = if (pos >= max) 0 else pos
|
||||
return pos++
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,6 @@ import net.corda.core.identity.CordaX500Name
|
||||
import net.corda.core.internal.div
|
||||
import net.corda.core.utilities.NetworkHostAndPort
|
||||
import org.assertj.core.api.Assertions.*
|
||||
import org.hibernate.exception.DataException
|
||||
import org.junit.Test
|
||||
import java.net.URL
|
||||
import java.nio.file.Path
|
||||
|
Reference in New Issue
Block a user