通过MSMQ解耦Web和数据库层是必要的还是过度设计?

8
我正在制作一个简单的asp.net网络控件,通过ajax表单提交将记录插入到MSQL数据库中。
由于可能有许多用户在短时间内访问包含此控件的页面,我担心每个请求都需要打开数据库连接、插入记录然后关闭连接的性能问题。
我的解决方案是让网络控件将消息放入MSMQ队列,并在服务器上定期读取队列并进行批量插入操作。
鉴于Web和数据库服务器运行在同一台机器上,这种设计听起来合理吗?是否必要?
根据我对数据库的阅读,使用MSMQ的大部分好处与弹性而非性能有关,所以我可能走错了路线。
非常感谢您的建议。
谢谢
Pete
2个回答

10
处理离线请求是处理高并发请求的常见模式。是否应该这样做,甚至能否这样做,取决于多个因素。主要因素是:你的调用者是否需要同步地看到其请求的响应?也就是说,调用者是否必须立即且绝对确定地知道数据库是否成功提交了他们的数据作为调用响应的一部分?如果是这样的话,那么将请求处理离线不是一个真正的选项。然而,如果可以接受调用者收到响应,表示他们的请求将在离线状态下处理(并发送任何必要的响应),那么使用队列肯定有益于整体架构。首先得益于前端可用性问题。如果你在短时间内处理数千个请求,并且每个请求由一个线程服务,然后该线程离开并插入数据到数据库中,很可能会遇到没有可用的分派线程来服务传入请求的问题。然而,通过减少 IIS 所做的后端工作量(相对于数据库调用来说,写入本地队列真的很便宜),你也减少了基于可用性的故障的可能性。
其次,通过使用队列,您将拥有一种限制后端流量的手段,因为您可以控制后端处理的吞吐量。
例如,您可以拥有一个单线程队列读取器进程,该进程将请求出队并将其处理到数据库中。如果您发现队列中有积压的消息,您可以通过托管更多实例来扩展队列读取器服务。
这意味着您可以减少数据库争用问题的可能性,因为您可以更好地控制任何时候对数据库进行访问的线程数量。
因此,通过使用队列,您会遭受更少的故障并具有较低的管理开销,这是良好编写应用程序的标志。特别是当您考虑在Web服务器上托管数据库时!
此外,您应该阅读一种称为CQRS的架构模式,其中的一个核心原则是离线执行数据库写入操作。

绝妙的答案Hugh,非常感谢。确认了我怀疑的事情,还有更多收获! - Pete Field
感谢您对这些选项的精彩比较和解释,加一分。非常感谢。 - Jens H

2
异步架构有许多优点(正如Hugh所指出的),但肯定会带来更大的成本和复杂性。这应该仔细权衡。从2个组件(Web应用程序和DB)开始,您现在必须开发、维护和监视4个组件(Web应用程序、DB、批处理服务和MSMQ)。您说Web服务器和DB服务器是同一台机器,这很奇怪,考虑到您的性能要求。明天您可能需要将Web应用程序、批处理服务和DB分别托管在3台不同的机器上。现在MSMQ也涉及到网络。还有一件事情可能会出错。
多线程批处理器也不容易,如果您必须按生成它们的顺序(至少对于给定实体)处理每个消息,则逻辑可能变得复杂。
如果可能,请测量两种解决方案并进行决策。

2
我明白您对监控开销的看法,确实有更多需要监控的事情。但是,我完全反对这种方法更加复杂的观点。高度耦合的解决方案在部署和维护上更加复杂。虽然有更多的运动部件,但松散耦合的解决方案更简单。每个部分都有明确的职责。并且,不需要多线程批处理服务,只需一个单线程队列监听器服务。同意扩展可能会影响交付顺序,但这是不可避免的。此外,MSMQ是Windows子系统的一部分,不需要“开发”。 - tom redfern

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接