这是我的网络场景:服务器(使用 boost asio 实现)正在接收请求,处理它们,然后传递到多个主机(使用也使用 asio 实现的 http 客户端),等待答案,处理答案,然后回复原始请求。
问题是主机被授予时间限制,服务器在等待答案时必须尊重它(即如果限制是100毫秒,那么服务器无法在100毫秒过去之前关闭连接)。
由于我的服务器正在使用工作线程池(每个线程都在运行
boost::asio::io_service::run()
),如果主机速度慢阻塞等待答案很快就会成为瓶颈(即所有工作人员都忙于等待,无法处理更多请求)。
这是服务器处理程序代码(大部分被跳过)
void connection::handle(asio::yield_context yield)
{
// read request
asio::async_read_until(socket_, request_buf, "\r\n", yield);
// read headers
asio::async_read_until(socket_, request_buf, "\r\n\r\n", yield);
// handle request
// THIS IS BLOCKING CALL
request_handler_->handle_request(request_, reply_);
// write reply
asio::async_write(socket_, reply_.to_buffers(), yield[ec]);
}
这就是handle_request 的作用
http::client::client c(host, port);
// this is asynchronous call returning immediately
std::future<http::reply> res = c.send(request);
// BOTTLENECK PROBLEM HERE
// this is blocking wait for answer
auto reply = res->get();
首先,我可以以异步方式重写
handle_request()
,如下所示:https://stackoverflow.com/a/26728121(这不会解决问题,但可能进一步有用)。我还可以将回调传递给 client::send()
以避免明确得到响应。
我想以某种方式“放弃”阻塞等待,直到收到所有响应,以便工作人员在此期间可以自由地服务其他传入请求。
我尝试了
boost::coroutine
和boost::fiber
,但是没有成功,确实这两个只是传递执行上下文,但我没有地方传递上下文,我只需要“等待”。
boost::asio::deadline_timer
在线程池上进行等待,直到时间限制。
boost::asio::deadline_timer timer(my_context);
timer.expires_from_now(boost::posix_time::milliseconds(100));
timer.async_wait(yield);