Corda RPC连接池/缓存

时间:2018-09-10 17:51:25

标签: rpc corda

Corda是否具有连接池功能?如何处理多个RPC用户连接池...

感谢您是否可以重定向到任何RPC连接池/缓存的开源实现/指南...

1 个答案:

答案 0 :(得分:1)

以下是如何池化节点RPC连接的示例:

import net.corda.client.rpc.CordaRPCClient
import net.corda.client.rpc.CordaRPCConnection
import net.corda.core.utilities.NetworkHostAndPort
import net.corda.core.utilities.contextLogger
import net.corda.core.utilities.getOrThrow
import net.corda.node.services.Permissions
import net.corda.testing.driver.DriverParameters
import net.corda.testing.driver.NodeParameters
import net.corda.testing.driver.driver
import net.corda.testing.node.User
import org.junit.Test
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.LinkedBlockingQueue

data class UserParams(val username: String, val password: String)

class PooledRpcConnections(address: NetworkHostAndPort): AutoCloseable {
    val userToPool = ConcurrentHashMap<UserParams, LinkedBlockingQueue<CordaRPCConnection>>()
    val client = CordaRPCClient(address)

    fun <A> withConnection(userParams: UserParams, block: (CordaRPCConnection) -> A): A {
        val queue = userToPool.getOrPut(userParams) { LinkedBlockingQueue() }
        val connection = queue.poll() ?: client.start(userParams.username, userParams.password)
        return try {
            block(connection)
        } finally {
            queue.add(connection)
        }
    }

    override fun close() {
        for (queue in userToPool.values) {
            do {
                val connection = queue.poll()
                connection?.close()
            } while (connection != null)
        }
    }
}

class Test {
    companion object {
        val log = contextLogger()
    }

    @Test
    fun poolWorks() {
        val users = ('a' .. 'f').map { User(it.toString(), it.toString(), setOf(Permissions.all())) }
        val userParams = users.map { UserParams(it.username, it.password) }
        driver(DriverParameters(startNodesInProcess = true, notarySpecs = emptyList())) {
            log.info("Starting node for users ${users.map { it.username }}")
            val node = startNode(NodeParameters(rpcUsers = users)).getOrThrow()
            log.info("Starting pool")
            PooledRpcConnections(node.rpcAddress).use { pool ->
                val N = 1000
                log.info("Making $N requests using pooled connections")
                (1 .. N).toList().parallelStream().forEach { i ->
                    val user = userParams[i % users.size]
                    pool.withConnection(user) { connection ->
                        log.info("USER[${user.username}] CONNECTION[${connection.hashCode()}] NODE_TIME[${connection.proxy.currentNodeTime()}]")
                    }
                }
                log.info("Done! Number of connections used per user: ${pool.userToPool.map { it.key.username to it.value.size }}")
            }
        }
    }
}