我正在编写一个带有 boost beast 1.70 和 mysql 8 C 连接器的 c++ websocket 服务器。服务器将同时连接多个客户端。特殊性是每个客户端将连续向服务器执行 100 个 websocket 请求。对于我的服务器,每个请求都是“cpu light”,但服务器对每个请求执行“时间繁重”的 sql 请求。
我已经使用 websocket_server_coro.cpp 示例启动了我的服务器。服务器步骤是:
1)一个websocket读取
2)一个sql请求
3)一个websocket写
问题是对于给定的用户,服务器在第 2 步被“锁定”,直到这一步和第 3 步完成后才能读取。因此,这 100 个请求被依次解决。这对我的用例来说太慢了。
我已经读过 boost beast 不可能进行非阻塞读/写。但是,我现在要做的是在协程中执行 async_read 和 async_write 。
void ServerCoro::accept(websocket::stream<beast::tcp_stream> &ws) {
beast::error_code ec;
ws.set_option(websocket::stream_base::timeout::suggested(beast::role_type::server));
ws.set_option(websocket::stream_base::decorator([](websocket::response_type &res) {
res.set(http::field::server, std::string(BOOST_BEAST_VERSION_STRING) + " websocket-Server-coro");
}));
ws.async_accept(yield[ec]);
if (ec) return fail(ec, "accept");
while (!_bStop) {
beast::flat_buffer buffer;
ws.async_read(buffer, yield[ec]);
if (ec == websocket::error::closed) {
std::cout << "=> get closed" << std::endl;
return;
}
if (ec) return fail(ec, "read");
auto buffer_str = new std::string(boost::beast::buffers_to_string(buffer.cdata()));
net::post([&, buffer_str] {
// sql async request such as :
// while (status == (mysql_real_query_nonblocking(this->con, sqlRequest.c_str(), sqlRequest.size()))) {
// ioc.poll_one(ec);
// }
// more sql ...
ws.async_write(net::buffer(worker->getResponse()), yield[ec]); // this line is throwing void boost::coroutines::detail::pull_coroutine_impl<void>::pull(): Assertion `! is_running()' failed.
if (ec) return fail(ec, "write");
});
}
}
问题是带有 async_write 的行会抛出错误:
void boost::coroutines::detail::pull_coroutine_impl::pull(): 断言`!is_running()' 失败。
如果将此行替换为sync_write,它可以工作,但对于给定用户,服务器保持顺序。我试图在单线程服务器上执行此代码。我还尝试对 async_read 和 async_write 使用相同的链。仍然有断言错误。
这样的服务器对于 websocket 的 boost beast 是不可能的吗?谢谢你。