在给定线程上使用同步I / O提升asio多线程tcp服务器

时间:2010-11-30 03:47:41

标签: c++ boost-asio

基本上,我想要实现的是实现一个通用的多线程TCP服务器,它可以处理2个不同服务器使用的任意请求,但需求略有不同。

我的要求是:

  1. 在收到整个初始请求之前,无法开始处理请求。 (基本上,我有一个固定大小的请求标头,其中包括整个请求的大小)。
  2. 处理请求可能会导致向请求客户端发送多条响应消息。 IE,通常情况下,请求可以在一个响应中处理,但有时,为了响应长时间运行的数据库事务,我需要ping回客户端,让他们知道我还在工作并且没有超时连接
  3. 为实现这一目标,我一直密切关注来自boost v1.44的HTTP服务器示例#2。一般来说,这个例子适用于简单的案例。我注意到的是,当我扩展到同时处理多个请求时,我所做的更改以某种方式导致所有请求被单个线程串行处理。显然,我做错了。

    由于雇主的限制,我无法发布我正在使用的所有实际代码,但足以说明,我保持异步调用以接受新连接,但已用同步替换了异步读/写调用。如果您认为需要查看特定部分,我可以看到我能做什么。

    基本上,我正在寻找的是如何将boost :: asio用于多线程TCP服务器的指针,其中单个连接由具有同步I / O的单个线程处理。再次,请记住,我的抽象是基于http服务器示例#2(每个CPU一个io_service),但我可以灵活交替

3 个答案:

答案 0 :(得分:2)

Boost.Asio documentation建议每个应用程序使用一个io_service,并从线程池中调用io_service::run

对我来说,为什么你不能使用异步readwritedeadline_timer对象结合来定期ping客户端也不明显。这种设计几乎肯定会比使用同步readswrites的每个连接线程更好地扩展。

答案 1 :(得分:0)

某些诊断:您可以在使用以下代码之前打印io_service_pool_.get_io_service()的值吗?

// from server.cpp
void server::handle_accept(const boost::system::error_code& e)
{
  if (!e)
  {
    new_connection_->start();
    new_connection_.reset(new connection(
          io_service_pool_.get_io_service(), request_handler_));
    acceptor_.async_accept(new_connection_->socket(),
        boost::bind(&server::handle_accept, this,
          boost::asio::placeholders::error));
  }
}

在将其传递给new_connection_.reset()之前,您需要将其存储在临时中;也就是说,不要为此测试调用get_io_service()两次。

我们首先要确保您获得新的io_service

答案 2 :(得分:0)

如果您正在进行大量的同步I / O,则并发性仅限于您拥有的线程数。我建议你现在拥有一个io_service用于你所有的异步I / O(即:所有的通信,定时器),然后决定如何处理同步I / O.

对于同步I / O,您需要确定峰值并发性。因为它是同步的并且它是I / O,所以您将需要更多的CPU线程,并且决定将基于您想要的I / O并发量。使用单独的io_service,然后使用io_service :: dispatch()将工作分配到执行同步工作负载的线程中。

这样做可以避免阻塞I / O调用停止处理其他异步事件的问题。