【发布时间】:2013-08-14 07:33:43
【问题描述】:
我编写了一个在单独线程中工作的网络记录器。这个想法是允许应用程序推送任何数量的数据,并且记录器应该单独处理它而不减慢主线程。伪代码如下:
void LogCoroutine::runLogic()
{
mBackgroundWorker = std::thread(&LogCoroutine::logic, this);
mBackgroundWorker.detach();
}
void LogCoroutine::logic()
{
while (true)
{
_serverLogic();
_senderLogic();
std::this_thread::sleep_for(std::chrono::milliseconds(10)); // 10ms
}
}
void LogCoroutine::_senderLogic()
{
std::lock_guard<std::mutex> lock(mMutex);
while (!mMessages.empty() && !mClients.empty())
{
std::string nextMessage = mMessages.front();
mMessages.pop_front();
_sendMessage(nextMessage);
}
}
_serverLogic 检查新连接(对等点)的套接字,_senderLogic 处理队列中的消息并将其发送给所有连接的对等点。
最后一个功能:推送消息:
void LogCoroutine::pushMessage(const std::string& message)
{
std::lock_guard<std::mutex> lock(mMutex);
mMessages.push_back(message);
}
当包裹不经常发送时,一切都很好。应用程序启动时有一个循环记录大量信息。并且应用程序挂起 5-10 秒,没有记录它不会变慢。
那么,这个架构的瓶颈在哪里?也许在里面推送带有互斥锁的每条消息是个坏主意?
【问题讨论】:
-
当我在 while(true) 循环中看到 sleep_for 时,我忍不住尖叫……为什么不用 std::condition_variable 来代替?如果我是你,我会创建一个线程安全的队列类,而不是在 logger 类中使用互斥锁
-
为什么不准备一个经过测试的消息队列,即ØMQ。有一次,我创建了an example,它只显示了原理,因为您的代码正在尝试。但是还有更多需要注意的地方:您的硬盘驱动器 io 是否因为它也在等待它而阻塞了应用程序的其余部分,或者您可能想从多个客户端通过网络登录等等。我建议查看 ØMQ .您甚至可以使用它在进程内进行通信。所有消息传递都是异步完成的。如果您登录速度过快,请注意排队人数过多
-
@Kek,即参见g2log,它基于无锁队列:)。把它和消息队列结合起来大概就是作者想要达到的目的
-
@DmitryLedentsov:在记录的情况下,您可能应该在队列上定义最大大小并决定是否在溢出的情况下丢弃传入的日志(比覆盖现有日志简单得多,因为这些通常是域发件人)。
-
@MatthieuM.:也许,是的,无论如何。如果有人认真对待它,那么负载平衡网络架构可能会有所帮助。在 0mq 中有一些dropping or offloading messages的配置选项
标签: c++ multithreading