Java守护进程设计实践
我正在用 Java 编写一个守护进程,它接受来自多个提供者的请求,其中提供者将返回一个服务对象供守护进程运行作为线程。
应用程序架构:
- 主类
- 提供商
- 服务
- 库/模型
- 列表项
主类 基本上加载配置文件,初始化所需的库等。守护进程初始化后,它会循环遍历所有提供程序并初始化它们。之后,守护进程进入无限循环,不断地遍历均匀分布的每个提供者,并尝试获取新的服务。
提供商 提供者基本上是第三方服务的适配器。这可以是电子邮件、传真、作业队列、数据库等。当提供商初始化时,它会连接到第 3 方服务。每当应用程序从提供者获取新的 service 对象时,它都会检查第 3 方服务,如果发现新请求,则会对其进行解析,然后返回一个新的 service 对象到应用程序。
服务 服务基本上是一项专门的工作。当提供者收到新请求时,它会返回与该请求相关的特定服务类型。当应用程序运行新的服务线程时,它将处理请求然后关闭。
这是一个示例,尽管它可能永远不会像这样使用。创建一个新的提供程序来侦听 HTTP 端口。一个新的 HTTP 请求要求处理一个字符串(反转它)并将其反转存储在数据库中。收到新请求时,提供程序将服务返回给应用程序,应用程序启动一个新的服务,其中反转字符串并更新数据库。更新后,应用程序会看到作业已完成,并且能够从另一个提供商获取新作业。
问题: 是否有像 MVC 这样的设计模式可以处理这样的架构?我意识到 MVC 是一个非常不好使用的术语,因为它包含多种模式。我想我要问的是,我要采用的方法好吗?采用 MVC 背后的概念并将其转移到此应用程序是一个好主意吗?提供者是控制器,服务是与模型相关的操作?尽管此类应用程序中从来没有任何视图。
编辑:
- 守护进程异步处理请求者的请求。请求者永远不会收到直接响应。
- 该应用程序是分布式的,因此您可以在任意多的服务器上运行该守护程序。每当提供者检索新请求时,它都会锁定该请求,以便其他守护程序不会重复该请求。 Jeff Storey 提到 JMS 对此可能很有用。我还考虑过集成 Memcache 来处理提供商处理锁定的方式。
谢谢
I'm writing a daemon in Java that takes in requests from multiple providers in which the provider would return a service object for the daemon to run as a thread.
Application architecture:
- Main class
- Providers
- Services
- Libraries / Models
- List item
Main class
Basically loads the configuration file, initializes libraries required, etc. Once the daemon is initialized, it loops through all the providers and initializes them. After that, the daemon goes into an endless loop constantly going through each provider evenly distributed and tries to fetch a new service.
Providers
A provider is basically an adapter to a 3rd party service. This could be e-mail, fax, a job queue, database, etc. When a provider is initialized it connects to the 3rd party service. Whenever the application fetches a new service object from the provider, it checks the 3rd party service, if it finds a new request, it parses it and then returns a new service object to the application.
Services
A service is basically a specialized job. When a provider gets a new request, it returns a specific service type related to the request. When the application runs a new service thread, it will handle the request and then close.
Here is an example, although it probably won't ever be used like this. A new provider is created that listens on an HTTP port. A new HTTP request comes in asking to process a string (reverse it) and store it in the database reversed. A new request comes in, the provider returns the service to the application, the application launches a new service in which is reverses the string and updates the database. When it's updated, the application sees that the job is done and is able to fetch a new one from another provider.
Question:
Are there any design patterns like MVC that would handle an architecture like this? I realize that MVC is a very bad term to use, as it contains multiple patterns. I guess what I'm asking is, the approach I'm going for okay? Would it be a good idea to take the concepts behind MVC and move it to this application? Providers being controllers, services being actions tied to models? Although there is never any views in this type of application.
Edit:
- The daemon handles requests asynchronously to the requester. The requester never receives a direct response.
- The application is distributed, so you can run this daemon on as many servers as you want. Whenever a provider retrieves a new request it locks the request so the other daemons do not duplicate the request. Jeff Storey mentioned JMS which could be useful for this. I've also thought about integrating Memcache to handle locking on top of how the providers handle it.
Thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您所描述的内容听起来很像企业集成模式解决的问题。
支持这些模式的轻量级 Java 库例如 Apache Camel 或 Spring Integration 或者您可以使用完整的企业服务总线,例如 ServiceMix 或 Mule。
以下是您的术语的粗略翻译:
主类 - 在完整的 ESB 中,这将是 ESB 本身,即应用程序服务器。您可以自己编写,也可以使用现有的 ESB 或通用应用程序服务器(例如 OSGI)。
提供商 - 渠道适配器。
服务 - 这些将是各种组件。有些可能是 EIP 组件,例如消息转换器以及服务激活器或其他通道适配器。
What you're describing sounds a lot like the the kind of thing that enterprise integration patterns solve.
Lightweight Java libraries that support these patterns are things like Apache Camel or Spring Integration or you could use a full Enterprise Service Bus like ServiceMix or Mule.
Here's a rough translation of your terms:
Main Class - In a full ESB this would be the ESB itself, i.e. the application server. You could write this yourself or you could use an existing ESB or general purpose application server like OSGI.
Providers - Channel Adapters.
Services - These will be various components. Some may be EIP components like Message Transformers as well as Service Activators or other Channel Adapters.
根据您需要扩展的规模,您可能需要考虑 JMS 等消息传递服务。您的生产者和消费者(即提供者和响应者)可以发布并侦听适当的 JMS 主题。
Depending on how large you need to scale, you might want to consider a messaging service like JMS. Your producers and consumers (i.e. providers and responders) could publish to and listen to the appropriate JMS topics.
Web 服务器(不仅是 HTTP 类型)使用请求/响应模式。套接字侦听器等待传入连接,使用请求工厂创建请求对象,然后将其传递给返回响应对象的处理程序(或者工厂也创建响应对象,处理程序只是修改它)。
在 HTTP 世界中,处理程序由 URL 标识,URL 参数或 POST 数据成为请求数据。响应(通常是一些 HTML 页面)从响应对象进行编码并发送回浏览器。
Web servers (and not only the HTTP kind) use the Request/Response pattern. A socket listener waits for incoming connections, uses a request factory to create a Request object and then passes this to a handler which returns a response object (or the factory also creates a response object and the handler just modifies it).
In the HTTP world, the handler is identified by the URL and the URL paramaters or the POST data becomes Request data. The response (usually some HTML page) is encoded from the response object and sent back to the browser.
根据我对您所描述的要求的理解,我确实有一些建议。
免责声明:我真的不知道您的扩展要求或资源限制,如果您正在运行守护程序,这些可能很重要。一如既往,对即将出现的建议持保留态度。
我最初的反应是,可能没有单一的设计模式可以解决您的整个问题,但有一些设计模式可能会帮助您解决其中的一部分。
1)听起来您的主类将轮询提供者。您可能想做一些更多消息驱动的事情。查看观察者模式和相关的发布/订阅模式 如果/当您需要扩大规模时。
2) 您可能需要考虑为您的提供商预先分配线程池。这可能不是绝对必要的,但对于您的特定情况可能有意义。
3) 根据您的描述,您可能正在进入架构宇航员领域(即概括一切都在你需要之前)。除非您要分发 API 或有很多人处理/重复使用此代码,否则我会警告您不要出现这种行为:这是一个很大的时间消耗,而且目标如此之高却令人沮丧。实现最初目标的一小部分。
其中一些建议可能并不直接适用于您的问题,但我希望它能有所帮助。
Based on my understanding of the requirements you described, I do have a couple of suggestions.
Disclaimer: I don't really know about your scaling requirements or your resource constraints, and if you're running a daemon these may be important. As always, take the forthcoming suggestions with a grain of salt.
My initial reaction is that there's probably no single design pattern that will solve your entire problem, but there are some design patterns that might help you with subsections of it.
1) It sounds like your Main class is going to be polling the providers. You may want to do something more message driven. Have a look at the Observer pattern and the related publish/subscribe pattern if/when you need to scale up.
2) You may want to think about pre-allocated thread pools for your providers. It may not be strictly necessary, but it might make sense for your particular situation.
3) Based on your description, you may be heading into architecture astronaut territory (i.e. generalizing everything before you need to). Unless you're going to be distributing an API or have a lot of people working on/re-using this code, I'd caution against this type of behavior: it's a big time sink and it's frustrating to aim so high and then only implement a tiny fraction of the initial ambition.
Some of this advice may not apply directly to your problem, but I hope it helps.
一种非 Java 特定的方法(我指的是一种通用方法,而不是在使用 Java 时不适用的方法)是使用 Aaron Digulla 指出的简单请求/响应方法。这是一个非常常见的场景,但很容易过度设计(实际上,它编写起来非常简单 - 特别是在使用适当的支持库时)。
如果您的用于从数据库添加/删除整体的 Web 服务应用程序超过 200-300 行代码,那么它可能是过度设计的(即使具有合理的错误处理和动态配置)。
如果您的数据库支持锁定和强制唯一性(以及事务,如果您需要此类功能),我建议您不要通过编写锁定恶魔来使事情变得过于复杂 - 只需让数据库处理它并处理异常即可。
如果您确实需要进行锁定(例如,因为您正在写入某些外部服务,例如硬件),那么您可以使用典型的 UNIX 方法来锁定资源并编写一个在本地套接字上运行的单实例守护程序,该守护程序所有您的 Web 服务可以与之对话 - 取决于它是否指示资源繁忙,它们可以拒绝请求或使用处理排队请求的守护进程对请求进行排队(例如,在排队系统的内存中、SQL DB 中的表等中) (它也与锁定服务对话)。
为了让事情变得非常简单,您总是可以始终从网络服务将请求推送到排队系统,我建议除非您需要区分“此操作正在执行”和“此操作”已排队”在您对提交请求的客户端的响应中。
对于接口本身,我个人更喜欢那些被广泛认可为开放标准、易于实现且高度可解释的东西,例如文档/文字 SOAP 服务,而不是 RPC/编码(不推荐使用且邪恶)或 JMS(这是专有的,尽管在实践中得到不同程度的广泛支持)。
如果您正在编写专门的内部服务并且您专门是一家 Java 商店,那么 JMS 非常合适,但如果它不是内部应用程序,那么最好好好发挥作用,不要假设其他人都希望使用 JMS 客户端只是为了与您的服务(我宣传 Doc/Lit SOAP,因为它可以被任何东西解析,甚至不能处理基本的 XML,并且是 WS-I 认可的)。
A non-Java specific (by which I mean a generic approach, not one that doesn't apply when using Java) is to use a simple Request/Response approach as noted by Aaron Digulla. This is a very common scenario but easy to over-engineer (as really, it's quite straightforward and simple to write - especially when using appropriate supporting libraries).
If your app for web service to add/remove entires from a database is more than a 200-300 lines of code then it's probably over-engineered (even with reasonable error handling and dynamic configuration).
If your database supports locking and enforcing uniqueness (and transactions, if you require that sort of functionality), I'd advise you don't overcomplicate things by writing a locking demon - just let the database take care of it and handle the exceptions.
If you really do need to do locking (e.g. because you are writing to some external service like a bit of hardware) then you can use a typical UNIX approach to locking resources and write a single-instanced daemon that runs on a local socket which all your web services can talk to - depending on if it indicates a resources is busy they could either reject requests or queue them (e.g. in memory in a queueing system, a table in an SQL DB, etc.) with a a daemon which process queued requests (which also talks to the locking service).
To keep things really simple you can always just always push requests to the queueing system from the web service, I would recommend that unless you need to distinguish between "this action is now being performed" and "this action is queued" in your responses to the client submitting the request.
For the interface itself, personally I favour something that is and widely endorsed as an open standard, easy to implement and highly interpretable, like Document/Literal SOAP service, in preference to something like RPC/encoded (deprecated & evil) or JMS (which is proprietary, though in practice supported widely to varying degrees).
If you are writing an exclusively internal service and you an exclusively a Java shop then JMS is highly suitable but if it's not an internal application it's best to play nicely and not assume everyone else will want to have to use a JMS client just to talk to your service (I evangelise Doc/Lit SOAP because it can be parsed by anything than can handle even basic XML and is WS-I endorsed).