我有一个系统,它有3个通用部分来帮助我描述。
1) DATABASE - 要存储所有表,这个相同的数据库将存储其他服务的数据,包括Web应用程序,Silverlight等...(需要灵活,如果在远程服务器,可以通过Web服务公开,如果在本地,可以本地连接或通过TCP连接到Windows服务)
2) BLACK BOX - 通过从数据库中注入所需项目列表,一次处理一个项目,如管道,其中u放入一组条件,单个值item,并返回该单个已处理项的结果。
3) WINDOWS SERVICE - 从数据库中检索数据,注入黑匣子,以预定义的间隔将黑盒子的结果保存到数据库中。该服务可能位于与数据库不同的服务器上。如果发生错误,将记录错误并继续。
平均而言,Windows服务必须处理大约5000个项目,黑盒子大约需要1.5秒来处理5000个项目。
我的问题是:
a)Windows服务是否应从数据库中获取要处理的项目的批处理列表,或者是否应该获取ID列表,并在循环中从数据库获取每个单独的项目,然后再传递给黑盒子?请注意,其他应用程序也在使用相同的数据库。暂时,我猜测数据库应该是某种Web服务调用。
b)处理后是否应立即保存单个项目?或者它应该在保存之前等待批处理完成处理?由于当系统在过程中间突然失败时,处理后保存每个单独的项目是好的,至少保存了已处理的项目,但是由于5000次调用Web服务而导致性能损失?
关于最佳解决方案的任何建议?
干杯
答案 0 :(得分:2)
您应该批量提取物品,这样就不会因请求而阻塞网络。抓取ID列表,然后循环它们并每次拉出完整项目是N个额外的数据库调用。
完成每个项目后更新数据库。成品可以在准备好后立即进一步使用,而不必等待5000批次完成。
这假设您将保存每个项目的数据
无论如何都需要进行N次呼叫(保存每个项目),因此等待每次批次结束后再进行更新都不会获得太多收益。
如果崩溃,您将丢失所有未保存的数据。
如果您不需要存储黑盒中的每件商品结果,那么您就有充分的理由考虑将所有商品批量更新。
我为银行写过这样的一堆应用。我通常的方法如下 - 它简单,容错,高效。 (假设您需要处理项目集并为每个项目保存数据)
除了items表之外,数据库还有一个表格,表示处理项目的状态。对于一些额外的工作,这将使调试和审核过程变得轻而易举:
table ItemsProcessStatus -- feel free to improve upon the name
int orderID (auto increment)
int itemID (fk to items)
datetime pulledForProcessing null
datetime finishedProcessing null
..etc
Windows服务在计时器上运行,比如每X分钟一次,并提取limit(Y)
个项目进行处理。这标记了pulledForProcessing
表中带有时间戳的ItemsProcessStatus
标志。
您想要拉出拉出日期为空的项目[以及那些已经拉出但未完成但超过Z
分钟的项目(我通常选择15到30分钟)]
小心拉动它们的程序。你需要使用锁
您可以进一步优化:在第一次迭代中,抓取Y
项,其中Y
可以很好地猜测您可以在该时间跨度内处理多少。在下一次迭代中,您计算它正在处理的速率(作为滑动平均值)并调整要拉动的项目数。这样它就会不断调整自己以满负荷运转。
Windows服务通过将它们发送到黑匣子逐个处理这些(好吧,通常它是多线程的,一次多个)。
我把它们放在线程安全的队列中<> (不要与msmq混淆)。工作线程循环,从队列中拉出,处理黑盒子中的项目,然后更新数据库。
你可以在这里使用任何典型的多线程技术(等待/脉冲,读取器/写入器锁定苗条,等待句柄),或者如果队列为空,只需让工作线程休眠几秒钟
在每个项目完成后,调用该项目的更新proc,这也会更新ItemsProcessStatus表(表示它已完成处理)
当您的服务停止时,请完成处理正在处理的所有项目并在数据库中更新它们。
pulledForProcessing
设置为空来在流程表中取消标记。
这适用于在服务器阵列上安装的多个Windows服务实例(尽管您希望将ComputerName
添加到进程表以识别正在运行每个服务的计算机)。这是有效的,因为每个服务只是抓住要处理的“下一组项目” - 不需要任何类型的路由或流程相互通信。
答案 1 :(得分:1)
MSMQ是微软的排队方式。我同意应该使用排队方法 - 这在处理大量事务的大多数系统中完成。例如,在我曾经工作的银行,我们使用MQ作为我们的中间件解决方案。
优点是过程的下一步可以在第一步之后立即开始处理,而无需等待处理所有5000个条目。如果数字增加到500,000,000怎么办?然后第一个项目的等待时间将大大增加。使用排队方法,它根本不会改变。
还有其他优势 - 可扩展性,稳健性,保证交付等等 - 但您可以稍后了解这些问题。
此外,良好实现的队列在使用它的进程中产生非常少的等待开销,因为它们几乎总是支持访问队列的多个线程。 (会有开销,但等待时间不会太大)。