我有一个与数据库交互的C#服务应用程序。它最近从.NET 2.0迁移到.NET 4.0,因此我们可以使用大量新工具。
我正在寻找指向编程方法或工具/库的指针来处理定义任务,配置他们依赖的任务,排队,优先排序,取消等等。
有各种类型的服务:
这些服务通常相互依赖并按需触发,即报告任务,可能会在其中包含代码,例如
if (IsSomeDependentCalculationRequired())
PerformDependentCalculation(); // which may trigger further calculations
GenerateRequestedReport();
此外,任何数据修改都可能会在某些计算或报告服务上设置Required
标记,(所以报告在完成生成之前可能已经过时了。任务的长度从几秒到几分钟不等,并在交易中执行。
到现在为止,这已经很好了,但它的扩展效果不佳。有一些基本的设计问题,我希望重写这部分代码。例如,如果两个用户在相似时间请求相同的报告,则依赖任务将被执行两次。此外,目前无法取消正在进行的任务。维护依赖任务等很难。
我不是在寻找有关如何实施修复的建议。相反,如果我从头开始使用.NET 4,那么我正在寻找指向我将用于此类要求的工具/库的指针。这会是Windows Workflow的好候选人吗?这是Futures的用途吗?我应该看看还有其他图书馆,还是我应该阅读的书籍或博客文章?
修改:Rx Reactive Extensions怎么办?
答案 0 :(得分:4)
我不认为您的要求适合任何内置的东西。您的要求太具体了。
我建议您围绕SQL数据库构建任务排队基础结构。您的任务运行时间很长(秒),因此您无需在任务计划程序中获得特别高的吞吐量。这意味着您不会遇到性能障碍。从编程的角度来看,它实际上是一个非常易于管理的任务。
您可能应该构建一个Windows服务或其他一些持续轮询数据库以获取新任务或请求的进程。然后,此服务可以对请求的任务强制执行任意规则。例如,它可以检测到报告任务已在运行,而不是安排新的计算。
我的主要观点是,您需要使用C#代码对其进行编码。您无法使现有工具满足您的需求。你需要编程语言的图灵完整性才能自己完成。
编辑:您可能应该将任务请求与任务执行分开。这允许多方请求刷新一些报告,同时仅运行一个实际计算。完成此单个计算后,所有任务请求都标记为已完成。取消请求时,不需要取消执行。只有当 last 请求被取消时,任务执行才会被取消。
编辑2:我不认为工作流程是解决方案。工作流程通常彼此分开运行。但你不希望如此。您希望拥有跨多个任务/工作流程的规则。您将使用基于工作流的模型来对抗系统。
编辑3:关于TPL(任务并行库)的几句话。你提到过它(“期货”)。如果您想要了解任务如何协同工作的灵感,如何创建依赖关系以及如何组合任务,请查看任务并行库(特别是Task和TaskFactory类)。你会发现一些漂亮的设计模式,因为它设计得非常好。以下是对一系列任务进行建模的方法:调用Task.ContinueWith,它将连续函数注册为新任务。以下是依赖关系建模的方法:TaskFactory.WhenAll(Task [])启动一个只在所有输入任务完成时才运行的任务。
但是:TPL本身可能不适合您,因为它的任务无法保存到磁盘。重新启动服务器或部署新代码时,将取消所有现有任务并中止该过程。这可能是不可接受的。请使用TPL作为灵感。从中学习什么是“任务/未来”以及它们如何组成。然后实现自己的任务形式。
这有帮助吗?
答案 1 :(得分:4)
我会尝试使用状态机包stateless来建模工作流程。使用程序包将提供一致的方法来跨各种服务推进工作流的状态。您的每个服务都将保留一个内部状态机实现,并公开推进它的方法。无状态将基于工作流状态触发操作,并强制您明确设置它可以处于的各种状态 - 这对维护特别有用,它可能会帮助您更好地理解域。 / p>
答案 2 :(得分:3)
如果要以可扩展的方式正确解决这一基本问题,您应该将其视为SOA架构风格。 您的服务将接收命令并生成您可以处理的事件,以便对系统中发生的事实做出反应。
而且,是的,有它的工具。例如,NServiceBus是构建SOA系统的绝佳工具。
答案 3 :(得分:1)
您可以执行SQL数据代理以定时间隔运行SQL查询。您必须自己编写应用程序。写得像一个长时间运行的程序,检查时间和做某事。我认为没有明确的工具来做你想做的事情。做C#应用程序,WCF服务。数据自动化可以在sql本身完成。
答案 4 :(得分:1)
如果我理解你,你想要缓存生成的报告而不再重复工作。正如其他评论者指出的那样,可以通过多个生产者/消费者队列和一些缓存来优雅地解决这个问题。 首先,您将报告请求排入队列。根据报告生成参数,如果先前生成的报告已经可用,则可以先检查缓存,然后只返回此报告。如果由于数据库中的更改而导致报告过时,则需要注意缓存是否以可靠的方式失效。
现在,如果尚未生成报告,则需要安排报告生成。报告调度程序需要检查是否已生成相同的报告。如果是,则注册事件以在完成时通知您,并在完成后返回报告。确保您不通过缓存层访问数据,因为它可能会产生竞争(报告生成,数据被更改,完成的报告将立即被缓存丢弃,留下注意到您返回)。
或者,如果您确实希望阻止返回过时的报告,您可以让缓存层成为您的主数据提供者,这将生成尽可能多的报告,直到生成一个报告并且过时。但要注意,如果数据库中有不断的更改,如果报告生成时间比更改数据库的平均时间长,则可能会不断生成无效报告,从而进入无限循环。
正如你所看到的,你有很多选择而没有真正谈论.NET,TPL,SQL服务器。首先,您需要设定目标系统的快速/可扩展性和可靠性,然后您需要为上述特定问题域选择适当的架构设计。我不能为你做,因为我没有你的完整领域知道什么是可接受的,什么不是。
棘手的部分是不同队列之间的切换部分,具有适当的可靠性和正确性保证。根据您的特定报告生成需求,您可以将此逻辑放入云中或使用单个线程,将所有工作放入正确的队列中,并同时或逐个处理它们。
TPL和SQL服务器可以确保帮助,但它们只是工具。如果由于对这一方面的经验不足而错误地使用,则可能会发现不同的方法(例如仅在内存队列中使用和文件系统中的持久报告)更适合您的问题。
根据我目前的理解,我不会使用SQL服务器将其误用为缓存,但如果你想要一个数据库,我会使用像RavenDB或RaportDB那样看起来稳定且重量轻得多的东西到一个完整的SQL服务器。
但如果您已经运行了SQL服务器,请继续使用它。
答案 5 :(得分:0)
我不确定我是否理解正确,但你可能想看看JAMS Scheduler:http://www.jamsscheduler.com/。它是非自由的,但是一个非常好的系统,用于安排依赖任务和报告。我在以前的公司成功使用过它。它是用.NET编写的,并且有一个.NET API,所以你可以编写自己的应用程序与JAMS通信。他们也有很好的支持,并且渴望实现新功能。