2013-02-04 237 views
7

我在寻找一些关于如何扩展当前在我公司运行的Windows服务的输入。我们使用的是.NET 4.0(能够而且将会在未来的某个时候升级到4.5),并运行此Windows Server 2012的扩展Windows服务

。关于服务
服务的工作就是查询在新行一个日志表(我们正在处理Oracle数据库),处理信息,在其他5个表中创建和/或更新一堆行(让我们称它们为跟踪表),更新日志表并重复。

日志记录表中有大量的XML(每行最多可以有20 MB),需要选择并保存在其他5个跟踪表中。新行一直以每小时500,000行的最大速率添加。
跟踪表的流量要高得多,每小时从最小的90,000个新行到最大表中可能的数百万行不等。更不用说那些表上也有更新操作。

关于数据被处理
我觉得这有点是寻找基于这些对象的分组方式和处理的解决方案非常重要。数据结构是这样的:

public class Report 
{ 
    public long Id { get; set; } 
    public DateTime CreateTime { get; set; } 
    public Guid MessageId { get; set; } 
    public string XmlData { get; set; } 
} 

public class Message 
{ 
    public Guid Id { get; set; } 
} 
  • 报告是我需要选择记录数据和流程
  • 对于每一个消息平均有五份报告。在一些情况下,这可以在1到数百之间变化。
  • 消息有一堆其他集合和其他关系,但它们与问题无关。

今天,我们仅仅管理着一个16核服务器上的负载Windows服务(我不记得完整规格,但它肯定地说这台机器是兽)。我一直致力于找到一种扩展方法,并添加更多机器来处理所有这些数据,而不会干扰其他实例。

当前每条消息都获取它自己的主题并处理相关报告。我们通过MessageId分组处理报告,以便在处理数据时将数据库查询的数量降至最低。

限制

  • 在这个阶段允许我重新写这个使用任何架构我认为合适的从零开始的服务。
  • 如果一个实例崩溃,其他实例需要能够拾取崩溃的一个离开的位置。没有数据可以丢失。
  • 该处理过程需要尽可能接近实时地插入到数据库中的报告。

我正在寻找关于如何建立这样一个项目的任何输入或建议。我假设这些服务需要是无状态的,或者是否有办法以某种方式同步所有实例的缓存?我应该如何协调所有实例并确保它们不处理相同的数据?我如何平均分配负载?当然,如何处理实例崩溃并且不能完成它的工作?

编辑
去掉无关的信息

+0

这听起来像一个ETL过程。您是否考虑过查看SQL Server Integration Services(SSIS)之类的东西,并编写可定期运行以定期执行此过程的软件包? –

+0

不幸的是,我们使用Oracle和更高层的人不想听到有关SQL Server的信息。 – Artless

+0

我只想着它的SSIS部分,而不是数据库引擎:)替代方案将类似Pentaho数据集成(http://www.pentaho.com/explore/pentaho-data-integration/)或Talend etl分析( http://www.talend.com/solutions/etl-analytics) –

回答

0

我通过编码这一切的可扩展性和冗余的东西我自己解决了这个。我会解释我做了什么以及我是如何做到的,任何人都需要这样做。

我在每个实例中创建了几个进程以跟踪其他实例并知道特定实例可以处理哪些记录。在启动时,实例将在名为Instances的表中注册到数据库中(如果尚未)。此表有以下几列:

Id     Number 
MachineName  Varchar2 
LastActive   Timestamp 
IsMaster   Number(1) 

注册,并在此表中创建一行,如果该实例的MachineName没有被发现后,实例开始查验该表中的每一秒在一个单独的线程,更新其LastActive列。然后它会从该表中选择所有行,并确保Master Instance(稍后更多)仍然存在 - 意味着它的LastActive时间在过去的10秒钟内。如果主实例停止响应,它将采取控制并将其自己设置为主。在下一次迭代中,它将确保只有一个主设备(如果另一个实例同时承担了控制权),并且如果不是,它将产生最低的Id实例。

什么是主实例?
该服务的工作是扫描日志表并处理该数据,以便人们可以轻松地对其进行过滤和读取。我没有在我的问题中说明这一点,但这可能与此有关。我们有一堆ESB服务器根据请求将多条记录写入日志记录表,而我的服务的工作就是实时追踪它们。由于他们正在异步写入日志,因此我可能会在日志中的started processing request A条目之前获得finished processing request A。所以,我有一些代码对这些记录进行排序,并确保我的服务以正确的顺序处理数据。因为我需要扩展此服务,所以只有一个实例可以执行此逻辑以避免大量不必要的数据库查询和可能的疯狂错误。
这是Master Instance进来的地方。只有它执行此排序逻辑并将日志记录ID临时保存在名为ReportAssignment的另一个表中。这张表的工作是跟踪哪些记录被处理以及由谁来处理。一旦处理完成,记录被删除。该表如下所示:

RecordId  Number 
InstanceId  Number Nullable 

主实例对日志条目进行排序并在此处插入其ID。我的所有服务实例都以1秒的间隔检查此表,以查找任何人未处理或正在由非活动实例处理的新记录,以及[record's Id] % [number of isnstances] == [index of current instance in a sorted array of all the active instances](在Pinging过程中获取)。查询看起来有点像这样:

SELECT * FROM ReportAssignment 
WHERE (InstanceId IS NULL OR InstanceId NOT IN (1, 2, 3)) // 1,2,3 are the active instances 
AND RecordId % 3 == 0 // 0 is the index of the current instance in the list of active instances 

为什么我需要这样做?

  • 另外两个实例将查询RecordId % 3 == 1RecordId % 3 == 2
  • RecordId % [instanceCount] == [indexOfCurrentInstance]确保记录在所有实例之间均匀分布。
  • InstanceId NOT IN (1,2,3)允许实例接管正在由崩溃的实例正在处理的记录,并且在添加新实例时不处理已激活实例的记录。

一旦一个实例查询这些记录,它将执行一个更新命令,将InstanceId设置为它自己的值,然后在日志记录表中查询这些Id的记录。处理完成后,将从ReportAssignment删除记录。

总的来说,我对此非常满意。它可以很好地扩展,确保在实例出现故障时不会丢失任何数据,并且对现有代码几乎没有任何更改。

6

为您的工作项目,Windows工作流可能是重构你的服务你最快的方式。

Windows Workflow Foundation @ MSDN

你会得到了WF的最有用的东西是持久性的工作流程,在设计合理的工作流程可以从坚持点继续,如果有什么从过去的点,它是发生在工作流程保存。

Workflow Persistence @ MSDN

这包括对工作流中的能力从另一个过程应在处理任何其他进程崩溃工作流中回收。如果您使用共享工作流存储,则恢复过程不需要在同一台计算机上。请注意,所有可恢复的工作流程都需要使用工作流存储。

对于工作分配,您有几个选项。

  1. 服务生成消息经由WorkflowService类使用WCF端点经由工作流调用基于主机的负载平衡结合。请注意,您可能希望在此处使用设计模式编辑器来构建输入方法,而不是手动设置Receive和相应的SendReply处理程序(这些处理程序映射到WCF方法)。您可能会为每条消息调用该服务,并且可能还会为每个报告调用该服务。请注意,CanCreateInstance属性在这里很重要。与之相关的每个调用都将创建一个独立运行的运行实例。

    WorkflowService Class (System.ServiceModel.Activities) @ MSDN
    Receive Class (System.ServiceModel.Activities) @ MSDN
    Receive.CanCreateInstance Property (System.ServiceModel.Activities) @ MSDN
    SendReply Class (System.ServiceModel.Activities) @ MSDN

  2. 使用具有队列支持服务总线。至少,您需要可能接受来自任意数量客户端的输入的内容,并且其输出可能会被唯一标识并处理一次。有一些想到的是NServiceBus,MSMQ,RabbitMQ和ZeroMQ。在这里提到的项目中,NServiceBus是独一无二的.NET开箱即用的。在云环境中,您的选项还包括特定于平台的产品,如Azure Service Bus和Amazon SQS。

    NServiceBus
    MSMQ @ MSDN
    RabbitMQ
    ZeroMQ
    Azure Service Bus @ MSDN
    Amazon SQS @ Amazon AWS

    注意,服务总线仅仅是一个生产商将启动的消息,并可以在任何存在的消费者之间的胶水从队列中读取的机器数量。同样,您可以使用这种间接方式生成报告。您的消费者将创建工作流实例,然后使用工作流持久性。

  3. Windows AppFabric可用于托管工作流程,允许您使用许多适用于IIS负载平衡的技术来分配工作。我个人没有任何经验,除了它具有良好的开箱即用监控支持以外,我没有太多可以说的。

    How to: Host a Workflow Service with Windows App Fabric @ MSDN
+0

谢谢!我将不得不做一些阅读和测试,并看看我的公司愿意做什么。 – Artless

+1

考虑到您对问题的报告解决方案评论的评论,我应该提醒您,WF附带的持久性存储依赖于MS SQL Server,而MS SQL Server可能是贵公司的一个破产商。如果您可以将MSDE作为持久性存储库运行以避免必须设置MSSQL实例,则可能值得一看。 – meklarian