记录一下ktor client的一个坑:java.net.BindException: Address already in use: no further information

记录一下用ktor client的时候遇到的一个坑。这是我的代码

@Scheduled(fixedRate = 10L)
//这里httpClient是ktor client,另一个client是OPC UA milo的client
    private fun collectingCoordData() = runBlocking {
        val time = measureTimeMillis {
                val absoluteValues = async(Dispatchers.IO) {
                    httpClient.get<Coordinate>(baseUrl + "coors/absolute").run {
                        sequenceOf(x, y, z).map { DataValue(Variant(it)) }.toList()
                    }
                }

                val machineValues = async(Dispatchers.IO) {
                    httpClient.get<Coordinate>(baseUrl + "coors/machine").run {
                        sequenceOf(x, y, z).map { DataValue(Variant(it)) }.toList()
                    }
                }
                val relativeValues = async(Dispatchers.IO) {
                    httpClient.get<Coordinate>(baseUrl + "coors/relative").run {
                        sequenceOf(x, y, z).map { DataValue(Variant(it)) }.toList()
                    }
                }

                launch {
                    client.writeValues(absoluteNodes, absoluteValues.await())
                            .whenCompleteAsync { t, u ->
                                u?.printStackTrace()
                                        ?: t.filter { it.isBad }.forEach { logger.warn("$it is wrong") }
                            }
                }
                launch {
                    client.writeValues(machineNodes, machineValues.await()).join()
                }
                launch {
                    client.writeValues(relativeNodes, relativeValues.await())
                            .whenCompleteAsync { t, u ->
                                u?.printStackTrace()
                                        ?: t.filter { it.isBad }.forEach { logger.warn("$it is wrong") }
                            }
                }

        }
        logger.info("Coord Time is $time")
    }

我是把整个请求放在一个计划任务中执行,最开始还好好的,打印的日志也很诱人

020-05-20 14:48:32.257  INFO 2128 --- [   scheduling-1] com.dennis.http.task.CncValueCollect     : Other Value Time is 0
2020-05-20 14:48:32.266  INFO 2128 --- [   scheduling-1] com.dennis.http.task.CncValueCollect     : Coord Time is 0
2020-05-20 14:48:32.275  INFO 2128 --- [   scheduling-1] c.dennis.http.task.CncStatusRefreshing   : Time is 0
2020-05-20 14:48:32.284  INFO 2128 --- [   scheduling-1] com.dennis.http.task.CncValueCollect     : Other Value Time is 0
2020-05-20 14:48:32.292  INFO 2128 --- [   scheduling-1] com.dennis.http.task.CncValueCollect     : Coord Time is 0
2020-05-20 14:48:32.302  INFO 2128 --- [   scheduling-1] com.dennis.http.task.CncValueCollect     : Other Value Time is 0
2020-05-20 14:48:32.310  INFO 2128 --- [   scheduling-1] com.dennis.http.task.CncValueCollect     : Coord Time is 0
2020-05-20 14:48:32.318  INFO 2128 --- [   scheduling-1] com.dennis.http.task.CncValueCollect     : Other Value Time is 0
2020-05-20 14:48:32.331  INFO 2128 --- [   scheduling-1] com.dennis.http.task.CncValueCollect     : Coord Time is 0
2020-05-20 14:48:32.341  INFO 2128 --- [   scheduling-1] c.dennis.http.task.CncStatusRefreshing   : Time is 0

基本上没什么延迟。(毕竟都是异步发送了)

但是过不了多久就出现了这种情况:

java.net.BindException: Address already in use: no further information
    at sun.nio.ch.SocketChannelImpl.checkConnect(Native Method) ~[na:1.8.0_131]
    at sun.nio.ch.SocketChannelImpl.finishConnect(SocketChannelImpl.java:717) ~[na:1.8.0_131]
    at io.ktor.network.sockets.SocketImpl.connect$ktor_network(SocketImpl.kt:36) ~[ktor-network-1.3.1.jar:1.3.1]
    at io.ktor.network.sockets.SocketImpl$connect$1.invokeSuspend(SocketImpl.kt) ~[ktor-network-1.3.1.jar:1.3.1]
    at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33) ~[kotlin-stdlib-1.3.72.jar:1.3.72-release-468 (1.3.72)]
    at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:56) ~[kotlinx-coroutines-core-1.3.5.jar:na]
    at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571) ~[kotlinx-coroutines-core-1.3.5.jar:na]
    at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:738) ~[kotlinx-coroutines-core-1.3.5.jar:na]
    at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678) ~[kotlinx-coroutines-core-1.3.5.jar:na]
    at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665) ~[kotlinx-coroutines-core-1.3.5.jar:na]
    Suppressed: java.net.BindException: Address already in use: no further information
        ... 10 common frames omitted
    Suppressed: java.net.BindException: Address already in use: no further information
        ... 10 common frames omitted

原因是:Windows给TCP/IP分配的端口有限。windows提供给TCP/IP链接的端口为 1024-5000,并且要四分钟来循环回收它们,就导致我们在短时间内跑大量的请求时将端口占满了,导致如上报错。

具体可以参考这篇博文:https://blog.csdn.net/MenofGod/article/details/84589751

按照这篇博文的修改过后,又可以愉快的玩耍了~放开端口用吧,反正只是调试

猜你喜欢

转载自blog.csdn.net/qq_41989109/article/details/106236250