Multithreading 如何避免淹没消息队列?

Multithreading 如何避免淹没消息队列?,multithreading,language-agnostic,concurrency,synchronization,Multithreading,Language Agnostic,Concurrency,Synchronization,我正在开发一个应用程序,它分为瘦客户机和服务器两部分,通过TCP进行通信。我们经常让服务器向客户机发出异步调用(通知),以报告状态更改。这避免了服务器在等待客户机确认时浪费太多时间。更重要的是,它避免了死锁 这种死锁可能发生如下情况。假设服务器将同步发送状态更改通知(请注意,这是一个构造的示例)。当客户端处理通知时,客户端需要同步地向服务器请求信息。但是,服务器无法响应,因为他正在等待问题的答案 现在,通过异步发送通知可以避免此死锁,但这会带来另一个问题。当异步调用的速度超过其处理速度时,调用队

我正在开发一个应用程序,它分为瘦客户机和服务器两部分,通过TCP进行通信。我们经常让服务器向客户机发出异步调用(通知),以报告状态更改。这避免了服务器在等待客户机确认时浪费太多时间。更重要的是,它避免了死锁

这种死锁可能发生如下情况。假设服务器将同步发送状态更改通知(请注意,这是一个构造的示例)。当客户端处理通知时,客户端需要同步地向服务器请求信息。但是,服务器无法响应,因为他正在等待问题的答案

现在,通过异步发送通知可以避免此死锁,但这会带来另一个问题。当异步调用的速度超过其处理速度时,调用队列将不断增长。如果这种情况维持足够长的时间,呼叫队列将完全满(充满消息)。我的问题是:当这种情况发生时,我们能做些什么

我的问题可以概括如下。我真的必须在发送通知而不阻塞(可能导致消息队列溢出)和发送通知而阻塞(可能导致死锁)之间做出选择吗?是否有一些技巧可以避免消息队列被淹没

注意:要重复,服务器在发送通知时不会暂停。它们是异步发送的


注意:在我的示例中,我使用了两个通信进程,但两个通信线程也存在同样的问题。

如果服务器正在向客户端发送信息性消息(您自己说是异步的),则不必等待客户端的回复。如果它们不是信息性的,换句话说,它们需要一个答案,我会说服务器永远不应该向客户端发送这样的消息,它们的存在表明设计很差。

取决于这些消息的重要性,或者,虽然听起来您的架构可能不正确。

我宁愿在服务器端修复逻辑。消息队列不应暂停等待答复。而是有一个状态机,它在等待客户机的回答时也可以接收这些信息查询


当然,您仍然可以处理消息队列,但是使用TCP,您可以非常轻松地处理它。

如果您经常遇到拥塞问题,除了正常地失败并通知客户端无法发布新消息之外,您几乎无法做其他事;然后,由客户机来维护待发布消息的积压

引入优先级队列并使用消息过期/过滤可以释放队列中的空间,但这实际上只是推迟了问题。如果可能,您也可以聚合消息或忽略重复消息,但问题似乎不是队列本身。(更不用说更复杂的队列逻辑可能会占用宝贵的资源,而这些资源在实际处理消息时会得到更好的利用。)

根据服务器端的操作,您可以为长时间计算引入结果哈希,将某些类型的消息卸载到专用设备,检查服务器是否等待I/O操作的时间过长,以及各种其他技术。如果可能,至少尝试找出哪些消息导致拥塞


哦,还有业务解决方案:将估计的开发时间成本与更好的硬件成本进行比较,得出结论,您应该只购买一台功能更强大的服务器(或一台额外的服务器)

我认为,最好的方法是为客户机添加另一个状态。这是我从SMPP协议规范中借用的

向客户端添加一个拥塞状态,在此状态下,客户端总是检查队列长度,假设这是可能的,因此一旦达到某个阈值,例如1000条未处理的消息,客户端向服务器发送一条消息,指示其拥塞,服务器将被要求停止所有消息传递,直到收到一条通知,指示客户端不再拥塞

或者,在服务器端,如果有一定数量的待定回复,服务器可以简单地停止发送消息,直到客户端回复一定数量的回复


这些阈值可以动态计算或固定,具体取决于……

它是什么队列-一些自定义实现的队列或Windows消息队列?如果有人试图对您的服务器执行此操作,则称为DDOS(定向拒绝服务)攻击。您是对的,但我正在寻找一种避免消息队列泛滥的方法。到底是哪个消息队列?Windows实现的线程消息队列?@Dimitri如果删除等待的服务器消息,应该不会出现泛滥。@sharptooth不,我们在IPC库中实现了自己的消息队列。然而,我说的是消息队列,不管它们是如何实现的,这是一个不同的问题。如果您的服务器比您的客户机慢,那么除了丢弃消息之外,没有其他解决方案。我们的体系结构主要工作如下:服务器异步发送状态更改,瘦客户机使用该更改来保持用户界面最新。但是,对于某些通知,客户端需要从服务器获取其他信息。你认为这是一种错误的做法吗?你是对的,我的部分问题可以通过过滤队列中的消息来解决。但是,这种过滤会降低性能。此外,它并不能为所有情况提供解决方案。感觉您仍然必须希望队列不会泛滥。不,在我的主要示例中,服务器在发送通知时不会暂停(我知道,可能是我把我的问题弄得太混乱了)。泛滥问题也存在于TCP级别:如果向TCP queu添加数据包