Multithreading boost asio处理程序中的长时间运行/阻塞操作 现状

Multithreading boost asio处理程序中的长时间运行/阻塞操作 现状,multithreading,client-server,boost-asio,Multithreading,Client Server,Boost Asio,我使用boost.asio实现了一个TCP服务器,它当前使用一个io\u服务对象,我在该对象上从单个线程调用run方法 到目前为止,服务器能够立即响应客户机的请求,因为它在内存中拥有所有必要的信息(不需要在接收处理程序中执行长时间运行的操作) 问题 现在需求发生了变化,我需要从数据库(使用ODBC)中获取一些信息,这基本上是一个长期运行的阻塞操作,以便为客户机创建响应 我看到了几种方法,但我不知道哪一种是最好的(可能还有更多的方法): 第一种方法 我可以在处理程序中保留长时间运行的操作,只需从多

我使用boost.asio实现了一个TCP服务器,它当前使用一个
io\u服务
对象,我在该对象上从单个线程调用
run
方法

到目前为止,服务器能够立即响应客户机的请求,因为它在内存中拥有所有必要的信息(不需要在接收处理程序中执行长时间运行的操作)

问题 现在需求发生了变化,我需要从数据库(使用ODBC)中获取一些信息,这基本上是一个长期运行的阻塞操作,以便为客户机创建响应

我看到了几种方法,但我不知道哪一种是最好的(可能还有更多的方法):

第一种方法 我可以在处理程序中保留长时间运行的操作,只需从多个线程调用
io\u service.run()
。我想我会使用尽可能多的线程,因为我有CPU内核可用

虽然这种方法很容易实现,但由于线程数量有限(由于数据库访问更像是一种I/O绑定操作,而不是一种计算绑定操作,因此大部分时间都处于空闲状态),我认为这种方法不会获得最佳性能

第二种方法 其中第6节说:

对长时间运行的任务使用线程

作为单线程设计的变体,此设计仍然使用单个io_service::run()线程来实现协议逻辑。长时间运行或阻塞任务被传递给后台线程,一旦完成,结果将被发回io_service::run()线程

这听起来很有希望,但我不知道如何实现。有人能为这种方法提供一些代码片段/示例吗

第三种方法 Boris Schäling在《如何使用定制服务扩展boost.asio》中解释了这一点


这看起来需要做很多工作。与其他方法相比,这种方法有什么好处吗?

这些方法并不明确地相互排斥。我经常看到第一个和第二个的组合:

  • 一个或多个线程正在一个
    io\u服务中处理网络I/O
  • 长时间运行或阻塞任务被发布到不同的
    io\u服务中
    。此
    io_服务
    用作线程池,不会干扰处理网络I/O的线程。或者,每次需要长时间运行或阻塞任务时,都可以生成分离的线程;但是,线程创建/销毁的开销可能会产生明显的影响
这提供了一个线程池实现。此外,下面是一个基本示例,它试图强调两个
io\u服务之间的交互

#包括
#包括
#包括
#包括
#包括
#包括
///@brief后台服务将用作线程池,其中
///长期阻塞操作可能会在不影响性能的情况下发生
///网络事件循环。
boost::asio::io_服务后台_服务;
///@brief主io_服务将处理网络操作。
boost::asio::io_服务io_服务;
boost::可选工作;
///@short-ODBC阻塞操作。
///
///@用于查询的简短数据。
///@完成操作后要调用的简短处理程序。
模板
无效查询\u odbc(无符号整数数据,
处理器(处理器)
{

std::cout我们的服务器中有相同的长时间运行的任务(带有存储的传统协议)。因此我们的服务器正在运行200个线程以避免阻塞服务(是的,200个线程正在运行
io_service::run
)。这不是太好的事情,但目前运行良好

我们遇到的唯一问题是
asio::strand
,它使用了所谓的“实现”,在当前调用hadler时会被锁定。通过增加此strains butckets和通过
io\u service::post
不使用strand wrap的情况下“解除连接”任务解决了这一问题


有些任务可能会运行几秒钟甚至几分钟,目前这项任务确实可以正常运行。

感谢您给出了这一伟大的答案。我希望我能对其进行更多的投票:) in main service, need to query odbc in main service, doing work. in background service, start querying odbc in main service, doing work. in main service, doing work. in main service, doing work. in main service, doing work. in background service, posting odbc result to main service in main service, got 42 from odbc.