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:
bpaunescu
2018-10-25 15:21:26 +01:00
committed by GitHub
parent 63f80d1fb5
commit c8b65c933f
9 changed files with 68 additions and 13 deletions

View File

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

View File

@ -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())
}

View File

@ -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++
}
}

View File

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