关于在 Grails 中进行异步处理的简单方法的建议
假设我有一个像这样的简单控制器:
class FooController {
def index = {
someVeryLongCompution() //e.g crawl a set of web pages
render "Long computation was launched."
}
}
当调用索引操作时,我希望该方法立即返回给用户,同时异步运行长计算。
我知道最可靠的方法是在架构中使用消息代理,但我想知道是否有更简单的方法。
我尝试了 Executor 插件,但是它会阻止 http 请求返回,直到长计算完成为止。
我尝试了 Quartz 插件,但这似乎对于周期性任务很有用(除非有办法只运行一次作业?)
你们是如何在 Grails 中处理此类请求的?
Let's say I have a simple controller like this:
class FooController {
def index = {
someVeryLongCompution() //e.g crawl a set of web pages
render "Long computation was launched."
}
}
When the index action is invoked, I want the method to return immediately to the user while running the long computation asynchronously.
I understand the most robust way to do this would be to use a message broker in the architecture, but I was wondering if there is a simpler way to do it.
I tried the Executor plugin but that blocks the http request from returning until the long computation is done.
I tried the Quartz plugin, but that seems to be good for periodic tasks (unless there is a way to run a job just once?)
How are you guys handling such requests in Grails?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
您想在同一个 Grails 服务器上还是不同的服务器上处理veryLongComputation()?
如果是同一台服务器,则不需要 JMS,另一种选择是创建一个新线程并异步处理计算。
Where do you want to process veryLongComputation(), on the same Grails server, or a different server?
If the same server, you don't need JMS, another option is to just create a new thread and process the computation asynchronously.
如果您在 Grails Quartz 中使用简单触发器并将重复计数设置为 0,则作业将仅运行一次。但是,它与用户请求分开运行,因此您需要找到某种方式在完成后与用户进行通信。
If you use a simple trigger in Grails Quartz and set the repeatCount to 0, the job will only run once. It runs separate from user requests, however, so you'd need to figure out some way to communicate to user when it completed.
我知道这是一个非常老的问题,只是想给出更新的答案。
从 grails 2.3 开始,框架支持使用 Servlet 3.0 异步请求处理的异步调用(当然,必须使用 servlet 3.0 容器,并且配置中的 servlet 版本应为 3.0,默认情况下)
它记录在此处:http://grails.org/doc/latest/guide/async.html
一般情况,有两种方法可以实现您的要求:
或 Servlet 异步方法:
小注释 - grails 方法使用 Promise,这是一个重大的(异步)飞跃。任何 Promise 都可以链接到进一步的 Promise,对成功和失败进行回调等。
I know this is a very old question, just wanted to give an updated answer.
Since grails 2.3, the framework supports async calls using Servlet 3.0 async request handling (of course, a servlet 3.0 container must be used and the servlet version should be 3.0 in the configuration, which it is per default)
It is documented here : http://grails.org/doc/latest/guide/async.html
In general, there are two ways achieving what you asked for:
or the Servlet Async way:
Small note - The grails method is using promises, which is a major (async) leap forward. Any Promise can be chained to further promised, have a callback on success and fail etc'
您是否尝试过 Grails Promisses API?它应该像这样简单
Have you tried Grails Promisses API? It should be as simple as
尝试 Spring 事件插件 - 它支持异步事件侦听器。
Try Spring events plugin - It supports asynchronous event listeners.
如果您想使用 Quartz 插件(就像我们一直做的那样),您可以这样做。它对我们来说效果很好:
DEFINE A JOB(没有定时触发器)
CALL.triggerNow() 以异步模式手动执行作业。
专业提示 #1
要从另一端获取命名参数...
专业提示 #2
执行方法总是在应用程序启动时被调用,但是命名参数参数为空。
文档: http://grails.org/version/Quartz%20plugin/24 #Dynamic%20Jobs%20Scheduling
If you'd like to use the Quartz plugin (as we always do), you can do it like this. It works well for us:
DEFINE A JOB (with no timed triggers)
CALL <job>.triggerNow() to manually execute the job in asynchronous mode.
Pro Tip #1
To get the named parameters out the other side...
Pro Tip #2
The execute method always gets called just as the application starts up, but the named parameters come through as null.
Documentation: http://grails.org/version/Quartz%20plugin/24#Dynamic%20Jobs%20Scheduling
解决此类问题的最佳解决方案是通过 JMS 插件 使用 JMS。
对于更简单的实现,不需要外部服务器/服务,您可以尝试 Spring Events 插件。
The best solution for this kind of problem is to use JMS, via the JMS plugin.
For a simpler implementation, that doesn't requires an externel server/service, you can try the Spring Events plugin.
Grails 2.2.1 解决方案 我有一个额外的要求,即报告完成后必须自动弹出一个窗口。所以我选择了上面的 servlet 方式。我用 json 格式的字符串替换了渲染视图,返回它看起来像这样。
另外,我的客户端不是 gsp 视图,而是 ExtJS 4.1.1(HTML5 产品)
Grails 2.2.1 Solution I had an additional requirement that said the report had to auto pop a window when it was complete. So I chose the servlet way from above with a twist. I replaced the render a view with a json formatted string return it looked like this.
Additionally my client side is not a gsp view, it is ExtJS 4.1.1 (a HTML5 product)