Java守护进程设计实践

时间:2010-01-05 17:25:56

标签: java request daemon

我正在用Java编写一个守护进程,该守护进程接收来自多个提供商的请求,其中提供商将返回服务对象守护进程作为线程运行。

应用程序架构:

  • 主要课程
  • 提供商
  • 服务
  • 图书馆/模特
  • 列表项

主要课程 基本上加载配置文件,初始化所需的库等。一旦守护进程初始化,它将遍历所有提供程序并初始化它们。之后,守护进入无限循环,不断地通过均匀分布的每个提供商,并尝试获取新的服务

提供商 提供者基本上是第三方服务的适配器。这可以是电子邮件,传真,作业队列,数据库等。初始化提供程序时,它连接到第三方服务。每当应用程序从提供程序中提取新的服务对象时,它都会检查第三方服务,如果找到新请求,则会对其进行解析,然后返回新的服务对象申请。

服务 服务基本上是一项专门的工作。当提供程序获取新请求时,它会返回与请求相关的特定服务类型。当应用程序运行新的服务线程时,它将处理请求然后关闭。

这是一个例子,虽然它可能不会像这样使用。创建一个新的提供程序,用于侦听HTTP端口。一个新的HTTP请求进来,要求处理一个字符串(反转它)并将其存储在数据库中。一个新的请求进入,提供程序将服务返回给应用程序,应用程序启动一个新的服务,其中反转字符串并更新数据库。更新后,应用程序会看到作业已完成,并且可以从另一个提供商中获取新作业。

问题: 是否有像MVC这样的设计模式可以处理这样的架构?我意识到MVC是一个非常糟糕的术语,因为它包含多个模式。我想我要问的是,我的方法还可以吗?采用MVC背后的概念并将其移至此应用程序是否是一个好主意?提供者是控制者,服务是与模型相关的行为?虽然此类应用程序中从未有任何观点。

修改

  • 守护程序以异步方式处理请求者的请求。请求者永远不会收到直接回复。
  • 应用程序是分布式的,因此您可以根据需要在任意数量的服务器上运行此守护程序。每当提供程序检索新请求时,它都会锁定请求,以便其他守护程序不会复制请求。 Jeff Storey提到了可能对此有用的JMS。我还考虑过集成Memcache以处理提供程序处理锁定的问题。

由于

5 个答案:

答案 0 :(得分:3)

根据您需要扩展的规模,您可能需要考虑像JMS这样的消息传递服务。您的生产者和消费者(即提供者和响应者)可以发布和收听适当的JMS主题。

答案 1 :(得分:2)

Web服务器(而不仅仅是HTTP类型)使用请求/响应模式。套接字侦听器等待传入连接,使用请求工厂创建Request对象,然后将其传递给返回响应对象的处理程序(或者工厂也创建响应对象,处理程序只修改它)。

在HTTP世界中,处理程序由URL和URL参数标识,或POST数据变为请求数据。响应(通常是一些HTML页面)从响应对象编码并发送回浏览器。

答案 2 :(得分:2)

你所描述的内容听起来很像enterprise integration patterns解决的问题。

支持这些模式的轻量级Java库是Apache CamelSpring Integration之类的东西,或者您可以使用像ServiceMix或Mule这样的完整企业服务总线。

以下是您的条款的粗略翻译:

主类 - 在完整的ESB中,这将是ESB本身,即应用程序服务器。您可以自己编写,也可以使用现有的ESB或OSGI等通用应用程序服务器。

提供商 - 渠道适应器。

服务 - 这些将是各种组件。有些可能是EIP组件,如Message Transformers,Service Activators或其他Channel Adapters。

答案 3 :(得分:1)

根据我对您所描述的要求的理解,我确实有一些建议。

免责声明:我并不真正了解您的扩展要求或资源限制,如果您正在运行守护程序,这些可能很重要。与往常一样,即将采取的一些建议。

我最初的反应是,可能没有单一的设计模式可以解决您的整个问题,但是有一些设计模式可能会帮助您完成它的小节。

1)听起来您的Main类将轮询提供者。您可能想要做更多消息驱动的事情。如果/何时需要扩大规模,请查看Observer pattern和相关的publish/subscribe pattern

2)您可能想要考虑为您的提供商预先分配thread pools。它可能不是绝对必要的,但它可能对您的特定情况有意义。

3)根据您的描述,您可能会进入architecture astronaut领域(即在您需要之前概括所有内容)。除非您要分发API或让很多人在使用/重新使用此代码,否则我会提醒您不要采取这种行为:这是一个很大的时间问题,如此高的目标是令人沮丧的实现初始目标的一小部分。

有些建议可能不会直接适用于您的问题,但我希望它有所帮助。

答案 4 :(得分:1)

非Java特定(我指的是一种通用方法,而不是在使用Java时不适用的方法)是使用Aaron Digulla所述的简单请求/响应方法。这是一个非常常见的场景,但很容易过度工程(实际上,它非常简单易懂,特别是在使用适当的支持库时)。

如果用于添加/删除数据库的web服务的应用程序超过200-300行代码,那么它可能过度设计(即使有合理的错误处理和动态配置)。

如果您的数据库支持锁定和强制执行唯一性(以及事务,如果您需要这种功能),我建议您不要通过编写锁定恶魔来使事情过于复杂 - 只需让数据库处理它并处理例外。

如果你真的需要做锁定(例如,因为你正在写一些外部服务,比如一些硬件)那么你可以使用典型的UNIX方法来锁定资源并编写一个在本地运行的单实例守护进程您的所有Web服务都可以与之通信的套接字 - 取决于它是否指示资源繁忙,它们可以拒绝请求或将它们排队(例如在排队系统的内存中,SQL DB中的表等),并使用守护程序进程排队请求(也与锁定服务对话)。

为了让事情变得非常简单,你总是可以始终从Web服务向队列系统推送请求,我建议除非你需要区分“此行动现在正在执行”和在您提交请求的客户的回复中,“此操作已排队”。

对于界面本身,我个人赞成的东西是广泛认可的开放标准,易于实现和高度可解释,如Document / Literal SOAP服务,优先于RPC / encoded(不赞成和恶意)或JMS(这是专有的,虽然在实践中得到了不同程度的广泛支持)。

如果您正在编写一个专门的内部服务而且您只是一个Java商店,那么JMS非常适合,但如果它不是内部应用程序,那么最好是很好地玩,而不是假设其他人都想要只使用JMS客户端与你的服务交谈(我传播Doc / Lit SOAP,因为它可以通过任何东西进行解析,甚至可以处理基本的XML并且是WS-I认可的。)