首页 文章

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

提问于
浏览
3

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

我的要求是:

  • 在收到整个初始请求之前,无法开始处理请求 . (基本上,我有一个固定大小的请求标头,其中包括整个请求的大小) .

  • 处理请求可能会导致向请求客户端发送多条响应消息 . IE,通常情况下,请求可以在一个响应中处理,但有时,为了响应长时间运行的数据库事务,我需要ping回客户端,让他们知道我还在工作并且没有超时连接 .

为了实现这一点,我一直密切关注来自boost v1.44的HTTP服务器示例#2 . 一般来说,这个例子适用于简单的案例 . 我注意到的是,当我扩展到同时处理多个请求时,我所做的更改以某种方式导致所有请求被单个线程串行处理 . 显然,我做错了什么 .

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

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

3 回答

  • 2

    一些诊断:您可以在以下代码中使用之前打印 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 .

  • 0

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

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

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

  • 0

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

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

相关问题