我想实现一个接受多个客户端的高吞吐量服务器。每个请求都应查询数据库,因此我需要某种异步行为。
我遵循了文档+ ROUTER
中的REQ
- 到 - Futures
模式,因此我结束了这个"架构":
trait ZmqProtocol extends Protocol {
private val pool = Executors.newCachedThreadPool()
private implicit val ec: ExecutionContextExecutor = ExecutionContext.fromExecutor(pool)
val context: ZMQ.Context = ZMQ.context(1)
val socket: ZMQ.Socket = context.socket(ZMQ.ROUTER)
socket.bind("tcp://*:5555")
override def receiveMessages(): String = {
while (true) {
val address = socket.recv(0)
val empty = socket.recv(0)
val request = socket.recv(0)
Future {
val message = new String(request)
getResponseFromDb(message)
} onComplete {
case Success(response) =>
// Send reply back to client
socket.send(address, ZMQ.SNDMORE)
socket.send("".getBytes, ZMQ.SNDMORE)
socket.send(response.getBytes(), 0)
case Failure(ex) => println(ex)
}
}
"DONE"
}
}
我理解这不会奏效,因为我在Future
共享套接字,所以我需要一个更好的模型。我知道ZeroMQ套接字很快并且在输入端创建几个工作线程就足够了,但是如果瓶颈在数据库端并且如果我需要在等待DB时做一些其他的工作,我假设我的所有线程很快就会出现耗尽。
如果我在每个ROUTER
中创建新套接字并绑定Future
,或者是否有更好的解决方案,是否会产生过多的开销?
另外,对于Scala开发人员:有没有办法强制在主线程上执行 onComplete
(我想它会解决问题)?谢谢!