我正在开发一个分为瘦客户端和服务器部分的应用程序,通过TCP进行通信。我们经常让服务器向客户端发出异步调用(通知)来报告状态变化。这避免了服务器在等待客户端确认时损失太多时间。更重要的是,它避免死锁。
此类死锁可能发生如下。假设服务器将同步发送状态更改通知(请注意,这是一个有点构造的示例)。当客户端处理通知时,客户端需要同步询问服务器以获取信息。但是,服务器无法响应,因为他正在等待他的问题的答案。
现在,通过异步发送通知可以避免这种死锁,但这会带来另一个问题。当异步调用比处理它们更快时,调用队列会不断增长。如果这种情况保持足够长的时间,则呼叫队列将完全填满(充满消息)。我的问题是:当发生这种情况时可以做些什么?
我的问题可以汇总如下。我是否真的必须选择在没有阻止的情况下发送通知而冒着泛滥消息队列的风险,或者在发送通知时阻止发送死锁< / b>吗?是否有一些技巧可以避免泛滥消息队列?
注意:要重复,服务器在发送通知时不会停止。它们是异步发送的。
注意:在我的示例中,我使用了两个通信进程,但两个通信线程存在同样的问题。
答案 0 :(得分:3)
如果服务器正在向客户端发送信息性消息(您自己说是异步的),则不必等待客户端的回复。如果它们不是信息性的,换句话说它们需要答案,我会说服务器永远不应该向客户端发送这样的消息,并且它们的存在表明设计很差。
答案 1 :(得分:3)
如果你有持续的拥塞问题,除了优雅地失败之外你几乎没有其他事情可以做,除了通知客户没有新的消息可以发布;然后由客户端来维护要发布的积压消息。
引入优先级队列并使用消息过期/过滤可以让您释放队列中的空间,但这实际上只是推迟了问题。如果可能,您还可以聚合消息或忽略重复的消息,但问题似乎不是队列本身。 (更不用说更复杂的队列逻辑可能占用宝贵的资源,这些资源可以更好地用于实际处理消息。)
根据服务器端的作用,您可以为长计算引入结果散列,将某些类型的消息卸载到专用设备,检查服务器是否等待I / O操作的时间过长,以及无数其他技术。如果可能,配置文件,至少尝试找出哪些消息导致拥塞。
哦,业务解决方案:将估计开发时间的成本与更好的硬件成本进行比较,并得出结论:您应该购买功能更强大的服务器(或额外的服务器)。
答案 2 :(得分:2)
根据这些消息的重要性,您可能希望查看Message Expiration或Message Filter,但听起来您的架构可能不正确。
答案 3 :(得分:1)
我宁愿修复服务器端的逻辑。消息队列不应该停止等待答案。而是有一个状态机,它也可以在等待来自客户端的答案时接收这些信息查询。
当然你仍然可以充斥你的消息队列,但是使用TCP你可以很容易地处理它。
答案 4 :(得分:1)
我认为,最好的办法是为您的客户添加另一种状态。我借用了SMPP协议规范。
向客户端添加拥塞状态,它总是检查队列长度,假设这是可能的,因此一旦达到某个阈值,比如1000条未处理的消息,客户端就会向服务器发送一条消息,表明它已拥塞并且在收到通知表明客户端不再拥塞之前,服务器将被要求停止所有消息传递。
或者,在服务器端,如果有一定数量的待处理回复,服务器可以直接停止发送消息,直到客户端回复一定数量的回复。
这些阈值可以动态计算或修复,具体取决于......