调用控制器操作时 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 中生成视图的情况下调用动作 [关闭]

Grails 不会将变量传递给嵌套模板

ajax请求在spring security中被拒绝,Grails

如何从 gsp 调用 Grails 服务?