系统设计/架构最佳方法

时间:2009-12-30 02:02:35

标签: .net web-services architecture windows-services soa

我有一个系统,它有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服务而导致性能损失?

关于最佳解决方案的任何建议?

干杯

2 个答案:

答案 0 :(得分:2)

  1. 您应该批量提取物品,这样就不会因请求而阻塞网络。抓取ID列表,然后循环它们并每次拉出完整项目是N个额外的数据库调用。

    • 如果您认为您将从抽象中受益,您可以使用Web服务来处理调用数据库。否则你只会造成不必要的复杂性
  2. 完成每个项目后更新数据库。成品可以在准备好后立即进一步使用,而不必等待5000批次完成。

    • 这假设您将保存每个项目的数据

    • 无论如何都需要进行N次呼叫(保存每个项目),因此等待每次批次结束后再进行更新都不会获得太多收益。

    • 如果崩溃,您将丢失所有未保存的数据。

    • 如果您不需要存储黑盒中的每件商品结果,那么您就有充分的理由考虑将所有商品批量更新。


  3. 我为银行写过这样的一堆应用。我通常的方法如下 - 它简单,容错,高效。 (假设您需要处理项目集并为每个项目保存数据)

    1. 除了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
      
    2. Windows服务在计时器上运行,比如每X分钟一次,并提取limit(Y)个项目进行处理。这标记了pulledForProcessing表中带有时间戳的ItemsProcessStatus标志。

      • 您想要拉出拉出日期为空的项目[以及那些已经拉出但未完成但超过Z分钟的项目(我通常选择15到30分钟)]

      • 小心拉动它们的程序。你需要使用锁

      • 您可以进一步优化:在第一次迭代中,抓取Y项,其中Y可以很好地猜测您可以在该时间跨度内处理多少。在下一次迭代中,您计算​​它正​​在处理的速率(作为滑动平均值)并调整要拉动的项目数。这样它就会不断调整自己以满负荷运转。

    3. Windows服务通过将它们发送到黑匣子逐个处理这些(好吧,通常它是多线程的,一次多个)。

      • 我把它们放在线程安全的队列中<> (不要与msmq混淆)。工作线程循环,从队列中拉出,处理黑盒子中的项目,然后更新数据库。

      • 你可以在这里使用任何典型的多线程技术(等待/脉冲,读取器/写入器锁定苗条,等待句柄),或者如果队列为空,只需让工作线程休眠几秒钟

    4. 在每个项目完成后,调用该项目的更新proc,这也会更新ItemsProcessStatus表(表示它已完成处理)

    5. 当您的服务停止时,请完成处理正在处理的所有项目并在数据库中更新它们。

      • 对于尚未发送到黑匣子的所有项目,您可以通过将pulledForProcessing设置为空来在流程表中取消标记。
    6. 如果您的服务崩溃,您不会“丢失”大量数据。未标记的项目将在超过特定年龄(流程表)时再次被提取

    7. 这适用于在服务器阵列上安装的多个Windows服务实例(尽管您希望将ComputerName添加到进程表以识别正在运行每个服务的计算机)。这是有效的,因为每个服务只是抓住要处理的“下一组项目” - 不需要任何类型的路由或流程相互通信。

答案 1 :(得分:1)

MSMQ是微软的排队方式。我同意应该使用排队方法 - 这在处理大量事务的大多数系统中完成。例如,在我曾经工作的银行,我们使用MQ作为我们的中间件解决方案。

优点是过程的下一步可以在第一步之后立即开始处理,而无需等待处理所有5000个条目。如果数字增加到500,000,000怎么办?然后第一个项目的等待时间将大大增加。使用排队方法,它根本不会改变。

还有其他优势 - 可扩展性,稳健性,保证交付等等 - 但您可以稍后了解这些问题。

此外,良好实现的队列在使用它的进程中产生非常少的等待开销,因为它们几乎总是支持访问队列的多个线程。 (会有开销,但等待时间不会太大)。