ENT-10016: Give all node threads descriptive names

This commit is contained in:
Shams Asari 2023-06-09 11:17:26 +01:00
parent 746e16bca0
commit 5b3180bf7b
21 changed files with 203 additions and 107 deletions

View File

@ -1,5 +1,6 @@
package net.corda.client.rpc package net.corda.client.rpc
import io.netty.util.concurrent.DefaultThreadFactory
import net.corda.client.rpc.internal.RPCClient import net.corda.client.rpc.internal.RPCClient
import net.corda.client.rpc.internal.ReconnectingCordaRPCOps import net.corda.client.rpc.internal.ReconnectingCordaRPCOps
import net.corda.client.rpc.internal.SerializationEnvironmentHelper import net.corda.client.rpc.internal.SerializationEnvironmentHelper
@ -52,7 +53,7 @@ class CordaRPCConnection private constructor(
sslConfiguration: ClientRpcSslOptions? = null, sslConfiguration: ClientRpcSslOptions? = null,
classLoader: ClassLoader? = null classLoader: ClassLoader? = null
): CordaRPCConnection { ): CordaRPCConnection {
val observersPool: ExecutorService = Executors.newCachedThreadPool() val observersPool: ExecutorService = Executors.newCachedThreadPool(DefaultThreadFactory("RPCObserver"))
return CordaRPCConnection(null, observersPool, ReconnectingCordaRPCOps( return CordaRPCConnection(null, observersPool, ReconnectingCordaRPCOps(
addresses, addresses,
username, username,

View File

@ -1,5 +1,6 @@
package net.corda.client.rpc.internal package net.corda.client.rpc.internal
import io.netty.util.concurrent.DefaultThreadFactory
import net.corda.client.rpc.ConnectionFailureException import net.corda.client.rpc.ConnectionFailureException
import net.corda.client.rpc.CordaRPCClient import net.corda.client.rpc.CordaRPCClient
import net.corda.client.rpc.CordaRPCClientConfiguration import net.corda.client.rpc.CordaRPCClientConfiguration
@ -99,7 +100,8 @@ class ReconnectingCordaRPCOps private constructor(
ErrorInterceptingHandler(reconnectingRPCConnection)) as CordaRPCOps ErrorInterceptingHandler(reconnectingRPCConnection)) as CordaRPCOps
} }
} }
private val retryFlowsPool = Executors.newScheduledThreadPool(1) private val retryFlowsPool = Executors.newScheduledThreadPool(1, DefaultThreadFactory("FlowRetry"))
/** /**
* This function runs a flow and retries until it completes successfully. * This function runs a flow and retries until it completes successfully.
* *

View File

@ -42,8 +42,8 @@ class ArtemisMessagingClient(private val config: MutualSslConfiguration,
override fun start(): Started = synchronized(this) { override fun start(): Started = synchronized(this) {
check(started == null) { "start can't be called twice" } check(started == null) { "start can't be called twice" }
val tcpTransport = p2pConnectorTcpTransport(serverAddress, config, threadPoolName = threadPoolName, trace = trace) val tcpTransport = p2pConnectorTcpTransport(serverAddress, config, threadPoolName = threadPoolName, trace = trace)
val backupTransports = backupServerAddressPool.map { val backupTransports = backupServerAddressPool.mapIndexed { index, address ->
p2pConnectorTcpTransport(it, config, threadPoolName = threadPoolName, trace = trace) p2pConnectorTcpTransport(address, config, threadPoolName = "$threadPoolName-backup${index+1}", trace = trace)
} }
log.info("Connecting to message broker: $serverAddress") log.info("Connecting to message broker: $serverAddress")

View File

@ -122,6 +122,7 @@ class ArtemisTcpTransport {
fun rpcAcceptorTcpTransport(hostAndPort: NetworkHostAndPort, fun rpcAcceptorTcpTransport(hostAndPort: NetworkHostAndPort,
config: BrokerRpcSslOptions?, config: BrokerRpcSslOptions?,
enableSSL: Boolean = true, enableSSL: Boolean = true,
threadPoolName: String = "RPCServer",
trace: Boolean = false, trace: Boolean = false,
remotingThreads: Int? = null): TransportConfiguration { remotingThreads: Int? = null): TransportConfiguration {
val options = mutableMapOf<String, Any>() val options = mutableMapOf<String, Any>()
@ -129,7 +130,7 @@ class ArtemisTcpTransport {
config.keyStorePath.requireOnDefaultFileSystem() config.keyStorePath.requireOnDefaultFileSystem()
options.putAll(config.toTransportOptions()) options.putAll(config.toTransportOptions())
} }
return createAcceptorTransport(hostAndPort, RPC_PROTOCOLS, options, null, enableSSL, "RPCServer", trace, remotingThreads) return createAcceptorTransport(hostAndPort, RPC_PROTOCOLS, options, null, enableSSL, threadPoolName, trace, remotingThreads)
} }
fun rpcConnectorTcpTransport(hostAndPort: NetworkHostAndPort, fun rpcConnectorTcpTransport(hostAndPort: NetworkHostAndPort,
@ -147,14 +148,16 @@ class ArtemisTcpTransport {
fun rpcInternalClientTcpTransport(hostAndPort: NetworkHostAndPort, fun rpcInternalClientTcpTransport(hostAndPort: NetworkHostAndPort,
config: SslConfiguration, config: SslConfiguration,
threadPoolName: String = "Internal-RPCClient",
trace: Boolean = false): TransportConfiguration { trace: Boolean = false): TransportConfiguration {
val options = mutableMapOf<String, Any>() val options = mutableMapOf<String, Any>()
config.addToTransportOptions(options) config.addToTransportOptions(options)
return createConnectorTransport(hostAndPort, RPC_PROTOCOLS, options, true, "Internal-RPCClient", trace, null) return createConnectorTransport(hostAndPort, RPC_PROTOCOLS, options, true, threadPoolName, trace, null)
} }
fun rpcInternalAcceptorTcpTransport(hostAndPort: NetworkHostAndPort, fun rpcInternalAcceptorTcpTransport(hostAndPort: NetworkHostAndPort,
config: SslConfiguration, config: SslConfiguration,
threadPoolName: String = "Internal-RPCServer",
trace: Boolean = false, trace: Boolean = false,
remotingThreads: Int? = null): TransportConfiguration { remotingThreads: Int? = null): TransportConfiguration {
val options = mutableMapOf<String, Any>() val options = mutableMapOf<String, Any>()
@ -165,7 +168,7 @@ class ArtemisTcpTransport {
options, options,
trustManagerFactory(requireNotNull(config.trustStore).get()), trustManagerFactory(requireNotNull(config.trustStore).get()),
true, true,
"Internal-RPCServer", threadPoolName,
trace, trace,
remotingThreads remotingThreads
) )
@ -209,7 +212,7 @@ class ArtemisTcpTransport {
trace: Boolean, trace: Boolean,
remotingThreads: Int?): TransportConfiguration { remotingThreads: Int?): TransportConfiguration {
return createTransport( return createTransport(
NodeNettyConnectorFactory::class.java.name, CordaNettyConnectorFactory::class.java.name,
hostAndPort, hostAndPort,
protocols, protocols,
options, options,

View File

@ -1,8 +1,14 @@
@file:JvmName("ArtemisUtils") @file:JvmName("ArtemisUtils")
package net.corda.nodeapi.internal package net.corda.nodeapi.internal
import net.corda.core.internal.declaredField
import org.apache.activemq.artemis.utils.actors.ProcessorBase
import java.nio.file.FileSystems import java.nio.file.FileSystems
import java.nio.file.Path import java.nio.file.Path
import java.util.concurrent.Executor
import java.util.concurrent.ThreadFactory
import java.util.concurrent.ThreadPoolExecutor
import java.util.concurrent.atomic.AtomicInteger
/** /**
* Require that the [Path] is on a default file system, and therefore is one that Artemis is willing to use. * Require that the [Path] is on a default file system, and therefore is one that Artemis is willing to use.
@ -16,3 +22,29 @@ fun requireMessageSize(messageSize: Int, limit: Int) {
require(messageSize <= limit) { "Message exceeds maxMessageSize network parameter, maxMessageSize: [$limit], message size: [$messageSize]" } require(messageSize <= limit) { "Message exceeds maxMessageSize network parameter, maxMessageSize: [$limit], message size: [$messageSize]" }
} }
val Executor.rootExecutor: Executor get() {
var executor: Executor = this
while (executor is ProcessorBase<*>) {
executor = executor.declaredField<Executor>("delegate").value
}
return executor
}
fun Executor.setThreadPoolName(threadPoolName: String) {
(rootExecutor as? ThreadPoolExecutor)?.let { it.threadFactory = NamedThreadFactory(threadPoolName, it.threadFactory) }
}
private class NamedThreadFactory(poolName: String, private val delegate: ThreadFactory) : ThreadFactory {
companion object {
private val poolId = AtomicInteger(0)
}
private val prefix = "$poolName-${poolId.incrementAndGet()}-"
private val nextId = AtomicInteger(0)
override fun newThread(r: Runnable): Thread {
val thread = delegate.newThread(r)
thread.name = "$prefix${nextId.incrementAndGet()}"
return thread
}
}

View File

@ -14,15 +14,16 @@ import org.apache.activemq.artemis.utils.ConfigurationHelper
import java.util.concurrent.Executor import java.util.concurrent.Executor
import java.util.concurrent.ScheduledExecutorService import java.util.concurrent.ScheduledExecutorService
class NodeNettyConnectorFactory : ConnectorFactory { class CordaNettyConnectorFactory : ConnectorFactory {
override fun createConnector(configuration: MutableMap<String, Any>?, override fun createConnector(configuration: MutableMap<String, Any>?,
handler: BufferHandler?, handler: BufferHandler?,
listener: ClientConnectionLifeCycleListener?, listener: ClientConnectionLifeCycleListener?,
closeExecutor: Executor?, closeExecutor: Executor,
threadPool: Executor?, threadPool: Executor,
scheduledThreadPool: ScheduledExecutorService?, scheduledThreadPool: ScheduledExecutorService,
protocolManager: ClientProtocolManager?): Connector { protocolManager: ClientProtocolManager?): Connector {
val threadPoolName = ConfigurationHelper.getStringProperty(ArtemisTcpTransport.THREAD_POOL_NAME_NAME, "Connector", configuration) val threadPoolName = ConfigurationHelper.getStringProperty(ArtemisTcpTransport.THREAD_POOL_NAME_NAME, "Connector", configuration)
setThreadPoolName(threadPool, closeExecutor, scheduledThreadPool, threadPoolName)
val trace = ConfigurationHelper.getBooleanProperty(ArtemisTcpTransport.TRACE_NAME, false, configuration) val trace = ConfigurationHelper.getBooleanProperty(ArtemisTcpTransport.TRACE_NAME, false, configuration)
return NettyConnector( return NettyConnector(
configuration, configuration,
@ -31,7 +32,7 @@ class NodeNettyConnectorFactory : ConnectorFactory {
closeExecutor, closeExecutor,
threadPool, threadPool,
scheduledThreadPool, scheduledThreadPool,
MyClientProtocolManager(threadPoolName, trace) MyClientProtocolManager("$threadPoolName-netty", trace)
) )
} }
@ -39,6 +40,17 @@ class NodeNettyConnectorFactory : ConnectorFactory {
override fun getDefaults(): Map<String?, Any?> = NettyConnector.DEFAULT_CONFIG override fun getDefaults(): Map<String?, Any?> = NettyConnector.DEFAULT_CONFIG
private fun setThreadPoolName(threadPool: Executor, closeExecutor: Executor, scheduledThreadPool: ScheduledExecutorService, name: String) {
threadPool.setThreadPoolName("$name-artemis")
// Artemis will actually wrap the same backing Executor to create multiple "OrderedExecutors". In this scenerio both the threadPool
// and the closeExecutor are the same when it comes to the pool names. If however they are different then given them separate names.
if (threadPool.rootExecutor !== closeExecutor.rootExecutor) {
closeExecutor.setThreadPoolName("$name-artemis-closer")
}
// The scheduler is separate
scheduledThreadPool.setThreadPoolName("$name-artemis-scheduler")
}
private class MyClientProtocolManager(private val threadPoolName: String, private val trace: Boolean) : ActiveMQClientProtocolManager() { private class MyClientProtocolManager(private val threadPoolName: String, private val trace: Boolean) : ActiveMQClientProtocolManager() {
override fun addChannelHandlers(pipeline: ChannelPipeline) { override fun addChannelHandlers(pipeline: ChannelPipeline) {

View File

@ -22,6 +22,7 @@ import net.corda.nodeapi.internal.protonwrapper.netty.AMQPClient
import net.corda.nodeapi.internal.protonwrapper.netty.AMQPConfiguration import net.corda.nodeapi.internal.protonwrapper.netty.AMQPConfiguration
import net.corda.nodeapi.internal.protonwrapper.netty.ProxyConfig import net.corda.nodeapi.internal.protonwrapper.netty.ProxyConfig
import net.corda.nodeapi.internal.protonwrapper.netty.RevocationConfig import net.corda.nodeapi.internal.protonwrapper.netty.RevocationConfig
import net.corda.nodeapi.internal.protonwrapper.netty.sslDelegatedTaskExecutor
import org.apache.activemq.artemis.api.core.ActiveMQObjectClosedException import org.apache.activemq.artemis.api.core.ActiveMQObjectClosedException
import org.apache.activemq.artemis.api.core.SimpleString import org.apache.activemq.artemis.api.core.SimpleString
import org.apache.activemq.artemis.api.core.client.ActiveMQClient.DEFAULT_ACK_BATCH_SIZE import org.apache.activemq.artemis.api.core.client.ActiveMQClient.DEFAULT_ACK_BATCH_SIZE
@ -31,6 +32,7 @@ import org.apache.activemq.artemis.api.core.client.ClientSession
import org.slf4j.MDC import org.slf4j.MDC
import rx.Subscription import rx.Subscription
import java.time.Duration import java.time.Duration
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors import java.util.concurrent.Executors
import java.util.concurrent.ScheduledExecutorService import java.util.concurrent.ScheduledExecutorService
import java.util.concurrent.ScheduledFuture import java.util.concurrent.ScheduledFuture
@ -53,7 +55,7 @@ open class AMQPBridgeManager(keyStore: CertificateStore,
maxMessageSize: Int, maxMessageSize: Int,
revocationConfig: RevocationConfig, revocationConfig: RevocationConfig,
enableSNI: Boolean, enableSNI: Boolean,
private val artemisMessageClientFactory: () -> ArtemisSessionProvider, private val artemisMessageClientFactory: (String) -> ArtemisSessionProvider,
private val bridgeMetricsService: BridgeMetricsService? = null, private val bridgeMetricsService: BridgeMetricsService? = null,
trace: Boolean, trace: Boolean,
sslHandshakeTimeout: Duration?, sslHandshakeTimeout: Duration?,
@ -78,9 +80,11 @@ open class AMQPBridgeManager(keyStore: CertificateStore,
private val amqpConfig: AMQPConfiguration = AMQPConfigurationImpl(keyStore, trustStore, proxyConfig, maxMessageSize, revocationConfig,useOpenSSL, enableSNI, trace = trace, _sslHandshakeTimeout = sslHandshakeTimeout) private val amqpConfig: AMQPConfiguration = AMQPConfigurationImpl(keyStore, trustStore, proxyConfig, maxMessageSize, revocationConfig,useOpenSSL, enableSNI, trace = trace, _sslHandshakeTimeout = sslHandshakeTimeout)
private var sharedEventLoopGroup: EventLoopGroup? = null private var sharedEventLoopGroup: EventLoopGroup? = null
private var sslDelegatedTaskExecutor: ExecutorService? = null
private var artemis: ArtemisSessionProvider? = null private var artemis: ArtemisSessionProvider? = null
companion object { companion object {
private val log = contextLogger()
private const val CORDA_NUM_BRIDGE_THREADS_PROP_NAME = "net.corda.nodeapi.amqpbridgemanager.NumBridgeThreads" private const val CORDA_NUM_BRIDGE_THREADS_PROP_NAME = "net.corda.nodeapi.amqpbridgemanager.NumBridgeThreads"
@ -97,18 +101,11 @@ open class AMQPBridgeManager(keyStore: CertificateStore,
* however Artemis and the remote Corda instanced will deduplicate these messages. * however Artemis and the remote Corda instanced will deduplicate these messages.
*/ */
@Suppress("TooManyFunctions") @Suppress("TooManyFunctions")
private class AMQPBridge(val sourceX500Name: String, private inner class AMQPBridge(val sourceX500Name: String,
val queueName: String, val queueName: String,
val targets: List<NetworkHostAndPort>, val targets: List<NetworkHostAndPort>,
val allowedRemoteLegalNames: Set<CordaX500Name>, val allowedRemoteLegalNames: Set<CordaX500Name>,
private val amqpConfig: AMQPConfiguration, private val amqpConfig: AMQPConfiguration) {
sharedEventGroup: EventLoopGroup,
private val artemis: ArtemisSessionProvider,
private val bridgeMetricsService: BridgeMetricsService?,
private val bridgeConnectionTTLSeconds: Int) {
companion object {
private val log = contextLogger()
}
private fun withMDC(block: () -> Unit) { private fun withMDC(block: () -> Unit) {
val oldMDC = MDC.getCopyOfContextMap() ?: emptyMap<String, String>() val oldMDC = MDC.getCopyOfContextMap() ?: emptyMap<String, String>()
@ -134,13 +131,18 @@ open class AMQPBridgeManager(keyStore: CertificateStore,
private fun logWarnWithMDC(msg: String) = withMDC { log.warn(msg) } private fun logWarnWithMDC(msg: String) = withMDC { log.warn(msg) }
val amqpClient = AMQPClient(targets, allowedRemoteLegalNames, amqpConfig, sharedThreadPool = sharedEventGroup) val amqpClient = AMQPClient(
targets,
allowedRemoteLegalNames,
amqpConfig,
AMQPClient.NettyThreading.Shared(sharedEventLoopGroup!!, sslDelegatedTaskExecutor!!)
)
private var session: ClientSession? = null private var session: ClientSession? = null
private var consumer: ClientConsumer? = null private var consumer: ClientConsumer? = null
private var connectedSubscription: Subscription? = null private var connectedSubscription: Subscription? = null
@Volatile @Volatile
private var messagesReceived: Boolean = false private var messagesReceived: Boolean = false
private val eventLoop: EventLoop = sharedEventGroup.next() private val eventLoop: EventLoop = sharedEventLoopGroup!!.next()
private var artemisState: ArtemisState = ArtemisState.STOPPED private var artemisState: ArtemisState = ArtemisState.STOPPED
set(value) { set(value) {
logDebugWithMDC { "State change $field to $value" } logDebugWithMDC { "State change $field to $value" }
@ -152,32 +154,9 @@ open class AMQPBridgeManager(keyStore: CertificateStore,
private var scheduledExecutorService: ScheduledExecutorService private var scheduledExecutorService: ScheduledExecutorService
= Executors.newSingleThreadScheduledExecutor(ThreadFactoryBuilder().setNameFormat("bridge-connection-reset-%d").build()) = Executors.newSingleThreadScheduledExecutor(ThreadFactoryBuilder().setNameFormat("bridge-connection-reset-%d").build())
@Suppress("ClassNaming")
private sealed class ArtemisState {
object STARTING : ArtemisState()
data class STARTED(override val pending: ScheduledFuture<Unit>) : ArtemisState()
object CHECKING : ArtemisState()
object RESTARTED : ArtemisState()
object RECEIVING : ArtemisState()
object AMQP_STOPPED : ArtemisState()
object AMQP_STARTING : ArtemisState()
object AMQP_STARTED : ArtemisState()
object AMQP_RESTARTED : ArtemisState()
object STOPPING : ArtemisState()
object STOPPED : ArtemisState()
data class STOPPED_AMQP_START_SCHEDULED(override val pending: ScheduledFuture<Unit>) : ArtemisState()
open val pending: ScheduledFuture<Unit>? = null
override fun toString(): String = javaClass.simpleName
}
private fun artemis(inProgress: ArtemisState, block: (precedingState: ArtemisState) -> ArtemisState) { private fun artemis(inProgress: ArtemisState, block: (precedingState: ArtemisState) -> ArtemisState) {
val runnable = { val runnable = {
synchronized(artemis) { synchronized(artemis!!) {
try { try {
val precedingState = artemisState val precedingState = artemisState
artemisState.pending?.cancel(false) artemisState.pending?.cancel(false)
@ -253,7 +232,7 @@ open class AMQPBridgeManager(keyStore: CertificateStore,
} }
} }
artemis(ArtemisState.STARTING) { artemis(ArtemisState.STARTING) {
val startedArtemis = artemis.started val startedArtemis = artemis!!.started
if (startedArtemis == null) { if (startedArtemis == null) {
logInfoWithMDC("Bridge Connected but Artemis is disconnected") logInfoWithMDC("Bridge Connected but Artemis is disconnected")
ArtemisState.STOPPED ArtemisState.STOPPED
@ -457,6 +436,29 @@ open class AMQPBridgeManager(keyStore: CertificateStore,
} }
} }
@Suppress("ClassNaming")
private sealed class ArtemisState {
object STARTING : ArtemisState()
data class STARTED(override val pending: ScheduledFuture<Unit>) : ArtemisState()
object CHECKING : ArtemisState()
object RESTARTED : ArtemisState()
object RECEIVING : ArtemisState()
object AMQP_STOPPED : ArtemisState()
object AMQP_STARTING : ArtemisState()
object AMQP_STARTED : ArtemisState()
object AMQP_RESTARTED : ArtemisState()
object STOPPING : ArtemisState()
object STOPPED : ArtemisState()
data class STOPPED_AMQP_START_SCHEDULED(override val pending: ScheduledFuture<Unit>) : ArtemisState()
open val pending: ScheduledFuture<Unit>? = null
override fun toString(): String = javaClass.simpleName
}
override fun deployBridge(sourceX500Name: String, queueName: String, targets: List<NetworkHostAndPort>, legalNames: Set<CordaX500Name>) { override fun deployBridge(sourceX500Name: String, queueName: String, targets: List<NetworkHostAndPort>, legalNames: Set<CordaX500Name>) {
lock.withLock { lock.withLock {
val bridges = queueNamesToBridgesMap.getOrPut(queueName) { mutableListOf() } val bridges = queueNamesToBridgesMap.getOrPut(queueName) { mutableListOf() }
@ -467,8 +469,7 @@ open class AMQPBridgeManager(keyStore: CertificateStore,
} }
val newAMQPConfig = with(amqpConfig) { AMQPConfigurationImpl(keyStore, trustStore, proxyConfig, maxMessageSize, val newAMQPConfig = with(amqpConfig) { AMQPConfigurationImpl(keyStore, trustStore, proxyConfig, maxMessageSize,
revocationConfig, useOpenSsl, enableSNI, sourceX500Name, trace, sslHandshakeTimeout) } revocationConfig, useOpenSsl, enableSNI, sourceX500Name, trace, sslHandshakeTimeout) }
val newBridge = AMQPBridge(sourceX500Name, queueName, targets, legalNames, newAMQPConfig, sharedEventLoopGroup!!, artemis!!, val newBridge = AMQPBridge(sourceX500Name, queueName, targets, legalNames, newAMQPConfig)
bridgeMetricsService, bridgeConnectionTTLSeconds)
bridges += newBridge bridges += newBridge
bridgeMetricsService?.bridgeCreated(targets, legalNames) bridgeMetricsService?.bridgeCreated(targets, legalNames)
newBridge newBridge
@ -497,15 +498,16 @@ open class AMQPBridgeManager(keyStore: CertificateStore,
// queueNamesToBridgesMap returns a mutable list, .toList converts it to a immutable list so it won't be changed by the [destroyBridge] method. // queueNamesToBridgesMap returns a mutable list, .toList converts it to a immutable list so it won't be changed by the [destroyBridge] method.
val bridges = queueNamesToBridgesMap[queueName]?.toList() val bridges = queueNamesToBridgesMap[queueName]?.toList()
destroyBridge(queueName, bridges?.flatMap { it.targets } ?: emptyList()) destroyBridge(queueName, bridges?.flatMap { it.targets } ?: emptyList())
bridges?.map { bridges?.associate {
it.sourceX500Name to BridgeEntry(it.queueName, it.targets, it.allowedRemoteLegalNames.toList(), serviceAddress = false) it.sourceX500Name to BridgeEntry(it.queueName, it.targets, it.allowedRemoteLegalNames.toList(), serviceAddress = false)
}?.toMap() ?: emptyMap() } ?: emptyMap()
} }
} }
override fun start() { override fun start() {
sharedEventLoopGroup = NioEventLoopGroup(NUM_BRIDGE_THREADS, DefaultThreadFactory("AMQPBridge", Thread.MAX_PRIORITY)) sharedEventLoopGroup = NioEventLoopGroup(NUM_BRIDGE_THREADS, DefaultThreadFactory("NettyBridge", Thread.MAX_PRIORITY))
val artemis = artemisMessageClientFactory() sslDelegatedTaskExecutor = sslDelegatedTaskExecutor("NettyBridge")
val artemis = artemisMessageClientFactory("ArtemisBridge")
this.artemis = artemis this.artemis = artemis
artemis.start() artemis.start()
} }
@ -522,6 +524,8 @@ open class AMQPBridgeManager(keyStore: CertificateStore,
sharedEventLoopGroup = null sharedEventLoopGroup = null
queueNamesToBridgesMap.clear() queueNamesToBridgesMap.clear()
artemis?.stop() artemis?.stop()
sslDelegatedTaskExecutor?.shutdown()
sslDelegatedTaskExecutor = null
} }
} }
} }

View File

@ -34,7 +34,7 @@ class BridgeControlListener(private val keyStore: CertificateStore,
maxMessageSize: Int, maxMessageSize: Int,
revocationConfig: RevocationConfig, revocationConfig: RevocationConfig,
enableSNI: Boolean, enableSNI: Boolean,
private val artemisMessageClientFactory: () -> ArtemisSessionProvider, private val artemisMessageClientFactory: (String) -> ArtemisSessionProvider,
bridgeMetricsService: BridgeMetricsService? = null, bridgeMetricsService: BridgeMetricsService? = null,
trace: Boolean = false, trace: Boolean = false,
sslHandshakeTimeout: Duration? = null, sslHandshakeTimeout: Duration? = null,
@ -79,7 +79,7 @@ class BridgeControlListener(private val keyStore: CertificateStore,
bridgeNotifyQueue = "$BRIDGE_NOTIFY.$queueDisambiguityId" bridgeNotifyQueue = "$BRIDGE_NOTIFY.$queueDisambiguityId"
bridgeManager.start() bridgeManager.start()
val artemis = artemisMessageClientFactory() val artemis = artemisMessageClientFactory("BridgeControl")
this.artemis = artemis this.artemis = artemis
artemis.start() artemis.start()
val artemisClient = artemis.started!! val artemisClient = artemis.started!!

View File

@ -37,7 +37,7 @@ class LoopbackBridgeManager(keyStore: CertificateStore,
maxMessageSize: Int, maxMessageSize: Int,
revocationConfig: RevocationConfig, revocationConfig: RevocationConfig,
enableSNI: Boolean, enableSNI: Boolean,
private val artemisMessageClientFactory: () -> ArtemisSessionProvider, private val artemisMessageClientFactory: (String) -> ArtemisSessionProvider,
private val bridgeMetricsService: BridgeMetricsService? = null, private val bridgeMetricsService: BridgeMetricsService? = null,
private val isLocalInbox: (String) -> Boolean, private val isLocalInbox: (String) -> Boolean,
trace: Boolean, trace: Boolean,
@ -204,7 +204,7 @@ class LoopbackBridgeManager(keyStore: CertificateStore,
override fun start() { override fun start() {
super.start() super.start()
val artemis = artemisMessageClientFactory() val artemis = artemisMessageClientFactory("LoopbackBridge")
this.artemis = artemis this.artemis = artemis
artemis.start() artemis.start()
} }

View File

@ -32,7 +32,9 @@ import rx.Observable
import rx.subjects.PublishSubject import rx.subjects.PublishSubject
import java.lang.Long.min import java.lang.Long.min
import java.net.InetSocketAddress import java.net.InetSocketAddress
import java.util.concurrent.Executor
import java.util.concurrent.ExecutorService import java.util.concurrent.ExecutorService
import java.util.concurrent.ThreadPoolExecutor
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
import java.util.concurrent.locks.ReentrantLock import java.util.concurrent.locks.ReentrantLock
import kotlin.concurrent.withLock import kotlin.concurrent.withLock
@ -61,8 +63,7 @@ data class ProxyConfig(val version: ProxyVersion, val proxyAddress: NetworkHostA
class AMQPClient(private val targets: List<NetworkHostAndPort>, class AMQPClient(private val targets: List<NetworkHostAndPort>,
val allowedRemoteLegalNames: Set<CordaX500Name>, val allowedRemoteLegalNames: Set<CordaX500Name>,
private val configuration: AMQPConfiguration, private val configuration: AMQPConfiguration,
private val sharedThreadPool: EventLoopGroup? = null, private val nettyThreading: NettyThreading = NettyThreading.NonShared("AMQPClient"),
private val threadPoolName: String = "AMQPClient",
private val distPointCrlSource: CertDistPointCrlSource = CertDistPointCrlSource.SINGLETON) : AutoCloseable { private val distPointCrlSource: CertDistPointCrlSource = CertDistPointCrlSource.SINGLETON) : AutoCloseable {
companion object { companion object {
init { init {
@ -82,7 +83,6 @@ class AMQPClient(private val targets: List<NetworkHostAndPort>,
private val lock = ReentrantLock() private val lock = ReentrantLock()
@Volatile @Volatile
private var started: Boolean = false private var started: Boolean = false
private var workerGroup: EventLoopGroup? = null
@Volatile @Volatile
private var clientChannel: Channel? = null private var clientChannel: Channel? = null
// Offset into the list of targets, so that we can implement round-robin reconnect logic. // Offset into the list of targets, so that we can implement round-robin reconnect logic.
@ -94,7 +94,6 @@ class AMQPClient(private val targets: List<NetworkHostAndPort>,
private var amqpActive = false private var amqpActive = false
@Volatile @Volatile
private var amqpChannelHandler: ChannelHandler? = null private var amqpChannelHandler: ChannelHandler? = null
private var sslDelegatedTaskExecutor: ExecutorService? = null
val localAddressString: String val localAddressString: String
get() = clientChannel?.localAddress()?.toString() ?: "<unknownLocalAddress>" get() = clientChannel?.localAddress()?.toString() ?: "<unknownLocalAddress>"
@ -123,7 +122,7 @@ class AMQPClient(private val targets: List<NetworkHostAndPort>,
log.info("Failed to connect to $currentTarget", future.cause()) log.info("Failed to connect to $currentTarget", future.cause())
if (started) { if (started) {
workerGroup?.schedule({ nettyThreading.eventLoopGroup.schedule({
nextTarget() nextTarget()
restart() restart()
}, retryInterval, TimeUnit.MILLISECONDS) }, retryInterval, TimeUnit.MILLISECONDS)
@ -142,7 +141,7 @@ class AMQPClient(private val targets: List<NetworkHostAndPort>,
clientChannel = null clientChannel = null
if (started && !amqpActive) { if (started && !amqpActive) {
log.debug { "Scheduling restart of $currentTarget (AMQP inactive)" } log.debug { "Scheduling restart of $currentTarget (AMQP inactive)" }
workerGroup?.schedule({ nettyThreading.eventLoopGroup.schedule({
nextTarget() nextTarget()
restart() restart()
}, retryInterval, TimeUnit.MILLISECONDS) }, retryInterval, TimeUnit.MILLISECONDS)
@ -198,7 +197,6 @@ class AMQPClient(private val targets: List<NetworkHostAndPort>,
val wrappedKeyManagerFactory = CertHoldingKeyManagerFactoryWrapper(keyManagerFactory, parent.configuration) val wrappedKeyManagerFactory = CertHoldingKeyManagerFactoryWrapper(keyManagerFactory, parent.configuration)
val target = parent.currentTarget val target = parent.currentTarget
val delegatedTaskExecutor = checkNotNull(parent.sslDelegatedTaskExecutor)
val handler = if (parent.configuration.useOpenSsl) { val handler = if (parent.configuration.useOpenSsl) {
createClientOpenSslHandler( createClientOpenSslHandler(
target, target,
@ -206,7 +204,7 @@ class AMQPClient(private val targets: List<NetworkHostAndPort>,
wrappedKeyManagerFactory, wrappedKeyManagerFactory,
trustManagerFactory, trustManagerFactory,
ch.alloc(), ch.alloc(),
delegatedTaskExecutor parent.nettyThreading.sslDelegatedTaskExecutor
) )
} else { } else {
createClientSslHandler( createClientSslHandler(
@ -214,7 +212,7 @@ class AMQPClient(private val targets: List<NetworkHostAndPort>,
parent.allowedRemoteLegalNames, parent.allowedRemoteLegalNames,
wrappedKeyManagerFactory, wrappedKeyManagerFactory,
trustManagerFactory, trustManagerFactory,
delegatedTaskExecutor parent.nettyThreading.sslDelegatedTaskExecutor
) )
} }
handler.handshakeTimeoutMillis = conf.sslHandshakeTimeout.toMillis() handler.handshakeTimeoutMillis = conf.sslHandshakeTimeout.toMillis()
@ -256,7 +254,7 @@ class AMQPClient(private val targets: List<NetworkHostAndPort>,
if (started && amqpActive) { if (started && amqpActive) {
log.debug { "Scheduling restart of $currentTarget (AMQP active)" } log.debug { "Scheduling restart of $currentTarget (AMQP active)" }
workerGroup?.schedule({ nettyThreading.eventLoopGroup.schedule({
nextTarget() nextTarget()
restart() restart()
}, retryInterval, TimeUnit.MILLISECONDS) }, retryInterval, TimeUnit.MILLISECONDS)
@ -273,8 +271,7 @@ class AMQPClient(private val targets: List<NetworkHostAndPort>,
return return
} }
log.info("Connect to: $currentTarget") log.info("Connect to: $currentTarget")
sslDelegatedTaskExecutor = sslDelegatedTaskExecutor(threadPoolName) (nettyThreading as? NettyThreading.NonShared)?.start()
workerGroup = sharedThreadPool ?: NioEventLoopGroup(NUM_CLIENT_THREADS, DefaultThreadFactory(threadPoolName, Thread.MAX_PRIORITY))
started = true started = true
restart() restart()
} }
@ -286,7 +283,7 @@ class AMQPClient(private val targets: List<NetworkHostAndPort>,
} }
val bootstrap = Bootstrap() val bootstrap = Bootstrap()
// TODO Needs more configuration control when we profile. e.g. to use EPOLL on Linux // TODO Needs more configuration control when we profile. e.g. to use EPOLL on Linux
bootstrap.group(workerGroup).channel(NioSocketChannel::class.java).handler(ClientChannelInitializer(this)) bootstrap.group(nettyThreading.eventLoopGroup).channel(NioSocketChannel::class.java).handler(ClientChannelInitializer(this))
// Delegate DNS Resolution to the proxy side, if we are using proxy. // Delegate DNS Resolution to the proxy side, if we are using proxy.
if (configuration.proxyConfig != null) { if (configuration.proxyConfig != null) {
bootstrap.resolver(NoopAddressResolverGroup.INSTANCE) bootstrap.resolver(NoopAddressResolverGroup.INSTANCE)
@ -300,16 +297,12 @@ class AMQPClient(private val targets: List<NetworkHostAndPort>,
lock.withLock { lock.withLock {
log.info("Stopping connection to: $currentTarget, Local address: $localAddressString") log.info("Stopping connection to: $currentTarget, Local address: $localAddressString")
started = false started = false
if (sharedThreadPool == null) { if (nettyThreading is NettyThreading.NonShared) {
workerGroup?.shutdownGracefully() nettyThreading.stop()
workerGroup?.terminationFuture()?.sync()
} else { } else {
clientChannel?.close()?.sync() clientChannel?.close()?.sync()
} }
clientChannel = null clientChannel = null
workerGroup = null
sslDelegatedTaskExecutor?.shutdown()
sslDelegatedTaskExecutor = null
log.info("Stopped connection to $currentTarget") log.info("Stopped connection to $currentTarget")
} }
} }
@ -350,4 +343,36 @@ class AMQPClient(private val targets: List<NetworkHostAndPort>,
private val _onConnection = PublishSubject.create<ConnectionChange>().toSerialized() private val _onConnection = PublishSubject.create<ConnectionChange>().toSerialized()
val onConnection: Observable<ConnectionChange> val onConnection: Observable<ConnectionChange>
get() = _onConnection get() = _onConnection
sealed class NettyThreading {
abstract val eventLoopGroup: EventLoopGroup
abstract val sslDelegatedTaskExecutor: Executor
class Shared(override val eventLoopGroup: EventLoopGroup,
override val sslDelegatedTaskExecutor: ExecutorService = sslDelegatedTaskExecutor("AMQPClient")) : NettyThreading()
class NonShared(val threadPoolName: String) : NettyThreading() {
private var _eventLoopGroup: NioEventLoopGroup? = null
override val eventLoopGroup: EventLoopGroup get() = checkNotNull(_eventLoopGroup)
private var _sslDelegatedTaskExecutor: ThreadPoolExecutor? = null
override val sslDelegatedTaskExecutor: ExecutorService get() = checkNotNull(_sslDelegatedTaskExecutor)
fun start() {
check(_eventLoopGroup == null)
check(_sslDelegatedTaskExecutor == null)
_eventLoopGroup = NioEventLoopGroup(NUM_CLIENT_THREADS, DefaultThreadFactory(threadPoolName, Thread.MAX_PRIORITY))
_sslDelegatedTaskExecutor = sslDelegatedTaskExecutor(threadPoolName)
}
fun stop() {
eventLoopGroup.shutdownGracefully()
eventLoopGroup.terminationFuture().sync()
sslDelegatedTaskExecutor.shutdown()
_eventLoopGroup = null
_sslDelegatedTaskExecutor = null
}
}
}
} }

View File

@ -300,7 +300,7 @@ abstract class AbstractServerRevocationTest {
listOf(NetworkHostAndPort("localhost", targetPort)), listOf(NetworkHostAndPort("localhost", targetPort)),
setOf(CHARLIE_NAME), setOf(CHARLIE_NAME),
amqpConfig, amqpConfig,
threadPoolName = legalName.organisation, nettyThreading = AMQPClient.NettyThreading.NonShared(legalName.organisation),
distPointCrlSource = CertDistPointCrlSource(connectTimeout = crlConnectTimeout) distPointCrlSource = CertDistPointCrlSource(connectTimeout = crlConnectTimeout)
) )
amqpClients += amqpClient amqpClients += amqpClient

View File

@ -503,7 +503,7 @@ class ProtonWrapperTests {
listOf(NetworkHostAndPort("localhost", serverPort)), listOf(NetworkHostAndPort("localhost", serverPort)),
setOf(ALICE_NAME), setOf(ALICE_NAME),
amqpConfig, amqpConfig,
sharedThreadPool = sharedEventGroup) nettyThreading = AMQPClient.NettyThreading.Shared(sharedEventGroup))
} }
private fun createServer(port: Int, private fun createServer(port: Int,

View File

@ -5,6 +5,7 @@ import com.codahale.metrics.MetricRegistry
import com.google.common.collect.MutableClassToInstanceMap import com.google.common.collect.MutableClassToInstanceMap
import com.google.common.util.concurrent.MoreExecutors import com.google.common.util.concurrent.MoreExecutors
import com.zaxxer.hikari.pool.HikariPool import com.zaxxer.hikari.pool.HikariPool
import io.netty.util.concurrent.DefaultThreadFactory
import net.corda.common.logging.errorReporting.NodeDatabaseErrors import net.corda.common.logging.errorReporting.NodeDatabaseErrors
import net.corda.confidential.SwapIdentitiesFlow import net.corda.confidential.SwapIdentitiesFlow
import net.corda.core.CordaException import net.corda.core.CordaException
@ -334,7 +335,7 @@ abstract class AbstractNode<S>(val configuration: NodeConfiguration,
private val schedulerService = makeNodeSchedulerService() private val schedulerService = makeNodeSchedulerService()
private val cordappServices = MutableClassToInstanceMap.create<SerializeAsToken>() private val cordappServices = MutableClassToInstanceMap.create<SerializeAsToken>()
private val shutdownExecutor = Executors.newSingleThreadExecutor() private val shutdownExecutor = Executors.newSingleThreadExecutor(DefaultThreadFactory("Shutdown"))
protected abstract val transactionVerifierWorkerCount: Int protected abstract val transactionVerifierWorkerCount: Int
/** /**
@ -770,7 +771,7 @@ abstract class AbstractNode<S>(val configuration: NodeConfiguration,
} else { } else {
1.days 1.days
} }
val executor = Executors.newSingleThreadScheduledExecutor(NamedThreadFactory("Network Map Updater")) val executor = Executors.newSingleThreadScheduledExecutor(NamedThreadFactory("NetworkMapPublisher"))
executor.submit(object : Runnable { executor.submit(object : Runnable {
override fun run() { override fun run() {
val republishInterval = try { val republishInterval = try {

View File

@ -415,12 +415,13 @@ open class Node(configuration: NodeConfiguration,
} }
private fun makeBridgeControlListener(serverAddress: NetworkHostAndPort, networkParameters: NetworkParameters): BridgeControlListener { private fun makeBridgeControlListener(serverAddress: NetworkHostAndPort, networkParameters: NetworkParameters): BridgeControlListener {
val artemisMessagingClientFactory = { val artemisMessagingClientFactory = { threadPoolName: String ->
ArtemisMessagingClient( ArtemisMessagingClient(
configuration.p2pSslOptions, configuration.p2pSslOptions,
serverAddress, serverAddress,
networkParameters.maxMessageSize, networkParameters.maxMessageSize,
failoverCallback = { errorAndTerminate("ArtemisMessagingClient failed. Shutting down.", null) } failoverCallback = { errorAndTerminate("ArtemisMessagingClient failed. Shutting down.", null) },
threadPoolName = threadPoolName
) )
} }
return BridgeControlListener( return BridgeControlListener(
@ -431,7 +432,8 @@ open class Node(configuration: NodeConfiguration,
networkParameters.maxMessageSize, networkParameters.maxMessageSize,
configuration.crlCheckSoftFail.toRevocationConfig(), configuration.crlCheckSoftFail.toRevocationConfig(),
false, false,
artemisMessagingClientFactory) artemisMessagingClientFactory
)
} }
private fun startLocalRpcBroker(securityManager: RPCSecurityManager): BrokerAddresses? { private fun startLocalRpcBroker(securityManager: RPCSecurityManager): BrokerAddresses? {

View File

@ -2,6 +2,7 @@ package net.corda.node.services.events
import co.paralleluniverse.fibers.Suspendable import co.paralleluniverse.fibers.Suspendable
import com.google.common.util.concurrent.ListenableFuture import com.google.common.util.concurrent.ListenableFuture
import io.netty.util.concurrent.DefaultThreadFactory
import net.corda.core.concurrent.CordaFuture import net.corda.core.concurrent.CordaFuture
import net.corda.core.context.InvocationContext import net.corda.core.context.InvocationContext
import net.corda.core.context.InvocationOrigin import net.corda.core.context.InvocationOrigin
@ -148,7 +149,7 @@ class NodeSchedulerService(private val clock: CordaClock,
// from the database // from the database
private val startingStateRefs: MutableSet<ScheduledStateRef> = ConcurrentHashMap.newKeySet<ScheduledStateRef>() private val startingStateRefs: MutableSet<ScheduledStateRef> = ConcurrentHashMap.newKeySet<ScheduledStateRef>()
private val mutex = ThreadBox(InnerState()) private val mutex = ThreadBox(InnerState())
private val schedulerTimerExecutor = Executors.newSingleThreadExecutor() private val schedulerTimerExecutor = Executors.newSingleThreadExecutor(DefaultThreadFactory("SchedulerService"))
// if there's nothing to do, check every minute if something fell through the cracks. // if there's nothing to do, check every minute if something fell through the cracks.
// any new state should trigger a reschedule immediately if nothing is scheduled, so I would not expect // any new state should trigger a reschedule immediately if nothing is scheduled, so I would not expect

View File

@ -65,7 +65,7 @@ class ArtemisMessagingServer(private val config: NodeConfiguration,
private val messagingServerAddress: NetworkHostAndPort, private val messagingServerAddress: NetworkHostAndPort,
private val maxMessageSize: Int, private val maxMessageSize: Int,
private val journalBufferTimeout : Int? = null, private val journalBufferTimeout : Int? = null,
private val threadPoolName: String = "ArtemisServer", private val threadPoolName: String = "P2PServer",
private val trace: Boolean = false, private val trace: Boolean = false,
private val distPointCrlSource: CertDistPointCrlSource = CertDistPointCrlSource.SINGLETON, private val distPointCrlSource: CertDistPointCrlSource = CertDistPointCrlSource.SINGLETON,
private val remotingThreads: Int? = null) : ArtemisBroker, SingletonSerializeAsToken() { private val remotingThreads: Int? = null) : ArtemisBroker, SingletonSerializeAsToken() {

View File

@ -17,6 +17,7 @@ import net.corda.nodeapi.internal.config.CertificateStore
import net.corda.nodeapi.internal.protonwrapper.netty.createAndInitSslContext import net.corda.nodeapi.internal.protonwrapper.netty.createAndInitSslContext
import net.corda.nodeapi.internal.protonwrapper.netty.keyManagerFactory import net.corda.nodeapi.internal.protonwrapper.netty.keyManagerFactory
import net.corda.nodeapi.internal.protonwrapper.netty.sslDelegatedTaskExecutor import net.corda.nodeapi.internal.protonwrapper.netty.sslDelegatedTaskExecutor
import net.corda.nodeapi.internal.setThreadPoolName
import org.apache.activemq.artemis.api.config.ActiveMQDefaultConfiguration import org.apache.activemq.artemis.api.config.ActiveMQDefaultConfiguration
import org.apache.activemq.artemis.api.core.BaseInterceptor import org.apache.activemq.artemis.api.core.BaseInterceptor
import org.apache.activemq.artemis.core.remoting.impl.netty.NettyAcceptor import org.apache.activemq.artemis.core.remoting.impl.netty.NettyAcceptor
@ -54,10 +55,23 @@ class NodeNettyAcceptorFactory : AcceptorFactory {
handler: BufferHandler?, handler: BufferHandler?,
listener: ServerConnectionLifeCycleListener?, listener: ServerConnectionLifeCycleListener?,
threadPool: Executor, threadPool: Executor,
scheduledThreadPool: ScheduledExecutorService?, scheduledThreadPool: ScheduledExecutorService,
protocolMap: Map<String, ProtocolManager<BaseInterceptor<*>>>?): Acceptor { protocolMap: Map<String, ProtocolManager<BaseInterceptor<*>>>?): Acceptor {
val threadPoolName = ConfigurationHelper.getStringProperty(ArtemisTcpTransport.THREAD_POOL_NAME_NAME, "Acceptor", configuration)
threadPool.setThreadPoolName("$threadPoolName-artemis")
scheduledThreadPool.setThreadPoolName("$threadPoolName-artemis-scheduler")
val failureExecutor = OrderedExecutor(threadPool) val failureExecutor = OrderedExecutor(threadPool)
return NodeNettyAcceptor(name, clusterConnection, configuration, handler, listener, scheduledThreadPool, failureExecutor, protocolMap) return NodeNettyAcceptor(
name,
clusterConnection,
configuration,
handler,
listener,
scheduledThreadPool,
failureExecutor,
protocolMap,
"$threadPoolName-netty"
)
} }
@ -68,14 +82,14 @@ class NodeNettyAcceptorFactory : AcceptorFactory {
listener: ServerConnectionLifeCycleListener?, listener: ServerConnectionLifeCycleListener?,
scheduledThreadPool: ScheduledExecutorService?, scheduledThreadPool: ScheduledExecutorService?,
failureExecutor: Executor, failureExecutor: Executor,
protocolMap: Map<String, ProtocolManager<BaseInterceptor<*>>>?) : protocolMap: Map<String, ProtocolManager<BaseInterceptor<*>>>?,
private val threadPoolName: String) :
NettyAcceptor(name, clusterConnection, configuration, handler, listener, scheduledThreadPool, failureExecutor, protocolMap) NettyAcceptor(name, clusterConnection, configuration, handler, listener, scheduledThreadPool, failureExecutor, protocolMap)
{ {
companion object { companion object {
private val defaultThreadPoolNamePattern = Pattern.compile("""Thread-(\d+) \(activemq-netty-threads\)""") private val defaultThreadPoolNamePattern = Pattern.compile("""Thread-(\d+) \(activemq-netty-threads\)""")
} }
private val threadPoolName = ConfigurationHelper.getStringProperty(ArtemisTcpTransport.THREAD_POOL_NAME_NAME, "NodeNettyAcceptor", configuration)
private val sslDelegatedTaskExecutor = sslDelegatedTaskExecutor(threadPoolName) private val sslDelegatedTaskExecutor = sslDelegatedTaskExecutor(threadPoolName)
private val trace = ConfigurationHelper.getBooleanProperty(ArtemisTcpTransport.TRACE_NAME, false, configuration) private val trace = ConfigurationHelper.getBooleanProperty(ArtemisTcpTransport.TRACE_NAME, false, configuration)

View File

@ -74,7 +74,7 @@ class NetworkMapUpdater(private val networkMapCache: NetworkMapCacheInternal,
} }
private val parametersUpdatesTrack = PublishSubject.create<ParametersUpdateInfo>() private val parametersUpdatesTrack = PublishSubject.create<ParametersUpdateInfo>()
private val networkMapPoller = ScheduledThreadPoolExecutor(1, NamedThreadFactory("Network Map Updater Thread")).apply { private val networkMapPoller = ScheduledThreadPoolExecutor(1, NamedThreadFactory("NetworkMapUpdater")).apply {
executeExistingDelayedTasksAfterShutdownPolicy = false executeExistingDelayedTasksAfterShutdownPolicy = false
} }
private var newNetworkParameters: Pair<ParametersUpdate, SignedNetworkParameters>? = null private var newNetworkParameters: Pair<ParametersUpdate, SignedNetworkParameters>? = null
@ -261,9 +261,12 @@ class NetworkMapUpdater(private val networkMapCache: NetworkMapCacheInternal,
//as HTTP GET is mostly IO bound, use more threads than CPU's //as HTTP GET is mostly IO bound, use more threads than CPU's
//maximum threads to use = 24, as if we did not limit this on large machines it could result in 100's of concurrent requests //maximum threads to use = 24, as if we did not limit this on large machines it could result in 100's of concurrent requests
val threadsToUseForNetworkMapDownload = min(Runtime.getRuntime().availableProcessors() * 4, 24) val threadsToUseForNetworkMapDownload = min(Runtime.getRuntime().availableProcessors() * 4, 24)
val executorToUseForDownloadingNodeInfos = Executors.newFixedThreadPool(threadsToUseForNetworkMapDownload, NamedThreadFactory("NetworkMapUpdaterNodeInfoDownloadThread")) val executorToUseForDownloadingNodeInfos = Executors.newFixedThreadPool(
threadsToUseForNetworkMapDownload,
NamedThreadFactory("NetworkMapUpdaterNodeInfoDownload")
)
//DB insert is single threaded - use a single threaded executor for it. //DB insert is single threaded - use a single threaded executor for it.
val executorToUseForInsertionIntoDB = Executors.newSingleThreadExecutor(NamedThreadFactory("NetworkMapUpdateDBInsertThread")) val executorToUseForInsertionIntoDB = Executors.newSingleThreadExecutor(NamedThreadFactory("NetworkMapUpdateDBInsert"))
val hashesToFetch = (allHashesFromNetworkMap - allNodeHashes) val hashesToFetch = (allHashesFromNetworkMap - allNodeHashes)
val networkMapDownloadStartTime = System.currentTimeMillis() val networkMapDownloadStartTime = System.currentTimeMillis()
if (hashesToFetch.isNotEmpty()) { if (hashesToFetch.isNotEmpty()) {

View File

@ -22,8 +22,7 @@ class InternalRPCMessagingClient(val sslConfig: MutualSslConfiguration, val serv
private var rpcServer: RPCServer? = null private var rpcServer: RPCServer? = null
fun init(rpcOps: List<RPCOps>, securityManager: RPCSecurityManager, cacheFactory: NamedCacheFactory) = synchronized(this) { fun init(rpcOps: List<RPCOps>, securityManager: RPCSecurityManager, cacheFactory: NamedCacheFactory) = synchronized(this) {
val tcpTransport = ArtemisTcpTransport.rpcInternalClientTcpTransport(serverAddress, sslConfig, threadPoolName = "RPCClient")
val tcpTransport = ArtemisTcpTransport.rpcInternalClientTcpTransport(serverAddress, sslConfig)
locator = ActiveMQClient.createServerLocatorWithoutHA(tcpTransport).apply { locator = ActiveMQClient.createServerLocatorWithoutHA(tcpTransport).apply {
// Never time out on our loopback Artemis connections. If we switch back to using the InVM transport this // 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. // would be the default and the two lines below can be deleted.

View File

@ -30,10 +30,10 @@ internal class RpcBrokerConfiguration(baseDirectory: Path, maxMessageSize: Int,
setDirectories(baseDirectory) setDirectories(baseDirectory)
val acceptorConfigurationsSet = mutableSetOf( val acceptorConfigurationsSet = mutableSetOf(
rpcAcceptorTcpTransport(address, sslOptions, enableSSL = useSsl) rpcAcceptorTcpTransport(address, sslOptions, enableSSL = useSsl, threadPoolName = "RPCServer")
) )
adminAddress?.let { adminAddress?.let {
acceptorConfigurationsSet += rpcInternalAcceptorTcpTransport(it, nodeConfiguration) acceptorConfigurationsSet += rpcInternalAcceptorTcpTransport(it, nodeConfiguration, threadPoolName = "RPCServerAdmin")
} }
acceptorConfigurations = acceptorConfigurationsSet acceptorConfigurations = acceptorConfigurationsSet

View File

@ -1,5 +1,6 @@
package net.corda.node.services.statemachine package net.corda.node.services.statemachine
import io.netty.util.concurrent.DefaultThreadFactory
import net.corda.core.flows.FlowSession import net.corda.core.flows.FlowSession
import net.corda.core.internal.FlowIORequest import net.corda.core.internal.FlowIORequest
import net.corda.core.internal.FlowStateMachine import net.corda.core.internal.FlowStateMachine
@ -22,10 +23,6 @@ internal class FlowMonitor(
) : LifecycleSupport { ) : LifecycleSupport {
private companion object { private companion object {
private fun defaultScheduler(): ScheduledExecutorService {
return Executors.newSingleThreadScheduledExecutor()
}
private val logger = loggerFor<FlowMonitor>() private val logger = loggerFor<FlowMonitor>()
} }
@ -36,7 +33,7 @@ internal class FlowMonitor(
override fun start() { override fun start() {
synchronized(this) { synchronized(this) {
if (scheduler == null) { if (scheduler == null) {
scheduler = defaultScheduler() scheduler = Executors.newSingleThreadScheduledExecutor(DefaultThreadFactory("FlowMonitor"))
shutdownScheduler = true shutdownScheduler = true
} }
scheduler!!.scheduleAtFixedRate({ logFlowsWaitingForParty() }, 0, monitoringPeriod.toMillis(), TimeUnit.MILLISECONDS) scheduler!!.scheduleAtFixedRate({ logFlowsWaitingForParty() }, 0, monitoringPeriod.toMillis(), TimeUnit.MILLISECONDS)