调用控制器操作时 Grails 视图挂起
Posted
技术标签:
【中文标题】调用控制器操作时 Grails 视图挂起【英文标题】:Grails view hangs when calling a controller action 【发布时间】:2021-12-20 13:41:16 【问题描述】:我有一个视图,它有一个使用g:link
GSP 标记的链接,该链接具有在大量行上运行和更新的操作,因此需要一些时间。与此同时,浏览器处于不稳定状态,并在 30 秒后超时(这是 servlet 容器的超时)。
问题:
-
页面超时是一种糟糕的用户体验。
浏览器每次超时都会提交控制器动作。我已通过检查查询是否已在运行来处理此问题,因此这不再是问题。
问题:
如何触发控制器操作并将页面重新加载到同一视图?还是有更好的方法来处理这个问题,比如触发异步操作?
我尝试使用js重新加载页面,但似乎没有重新加载页面。我已经阅读了有关实现消息队列的信息,但是对于一个简单的问题似乎需要做很多工作。任何想法都会很好。提前谢谢你。
查看:
<li>
<a class=""
href="$g.createLink(controller: "hello", action: "dbAction")">Run Update on DB
</a>
</li>
控制器动作:
def dbAction()
some code...
myservice.dbAction();
redirect(action: 'index')progress"
我的服务 dbAction:
def dbAction()
Sql sql = getSql()
sql.executeUpdate('''
update mytable
set
mydata = calculate_data,
updated_by = 'dbAction',
updated_at = now()
where
id in (1,2,3)
【问题讨论】:
【参考方案1】:我有你的问题。查询需要很长时间才能运行,控制器无法响应浏览器。所以,浏览器超时了。
我尝试了 3 种不同的方法来解决这个问题。
简单的出路: 我正在使用Tomcat。因此,我将连接超时值设置得更长。 connectionTimeout 变量位于 server.xml 文件中。
懒惰的出路: 我不知道 Grails 是否有任何消息队列功能。所以,我推出了自己的。当我单击提交按钮运行一个很长的更新查询时,该操作将在数据库表中插入一种更新命令以及状态。然后我使用 Quartz 安排可能每 10 秒读取一次该表以检查状态。如果状态为 NEW,我将状态更改为“IN PROGRESS”。然后我让触发器在后台运行更新查询。完成后,我将状态更改为 FINISH。
因此,该操作只是在数据库中添加一行,然后回复显示类似... 您已发出请求的视图。系统将在稍后处理您的请求。
艰难的出路: 我检查了操作中的所有 SQL 和函数,以计算 SQL 和代码完成查询所需的时间。然后我重新排列/重写函数和过程。我对此还不够好。如果我能达到 O(n),那对我来说就足够了。
【讨论】:
感谢您的回答伙伴。由于其他原因,我现在将 tomcat 超时设置为 3 分钟。它不会超时,但从 UX 的角度来看,浏览器卡住并每分钟发送一个帖子。我确实使用石英来执行其他通宵运行的任务和数据修复,所以我可能会调查一下。我希望是否可以启动一个新线程并在该线程上运行控制器操作。 “懒惰的出路:我不知道 Grails 是否有任何消息队列功能。所以,我推出了自己的。” - @tom6502 确实如此。我们选择不推出自己的产品,因为可靠的解决方案已经很好地解决了围绕消息传递的复杂挑战。 Kafka 和 RabbitMQ 是我们明确支持和集成的消息传递系统之一。您可以通过guides.grails.org/grails-micronaut-kafka/guide/index.html 和guides.grails.org/grails-rabbitmq/guide/index.html 了解更多信息。 与消息队列系统分开,我们还有一个可能相关的内部事件机制。 guides.grails.org/grails-events/guide/index.html 嗨 @JeffScottBrown,感谢 cmets 提出这个问题。我已经在看 RabbitMQ,但我不知道 grails-events。我想建立一个包含所有石英作业状态的视图,是否有一种简单的方法可以做到这一点,或者您是否看过任何此类实现。如果你愿意,我可以问一个单独的问题。以上是关于调用控制器操作时 Grails 视图挂起的主要内容,如果未能解决你的问题,请参考以下文章
Groovy/grails 如何使用 jquery 从视图中调用控制器方法
如何在不在 grails 中生成视图的情况下调用动作 [关闭]