单击按钮时心跳停止/阻塞
Heartbeat is stopped / blocked while button click
情况的简短描述:单击 Vaadin 按钮时,Vaadin 心跳评估被会话锁定阻止。当按钮操作的执行时间超过 3 个心跳间隔时,连接就会丢失。
小问题:有没有办法让心跳继续,即使按钮点击执行需要超过 3 个心跳间隔?
更详细的情况描述:
在 Vaadin 8.8.6 应用程序中,我遇到了这种情况(相关代码似乎没有更改到 14.6.9 甚至更高版本):
- 应用程序中的 handling/execution 按钮点击通常在几秒钟内完成。
- 在极少数情况下,有些操作(文件导入/转换/导出)需要 17 分钟才能执行(是的,对于一个按钮来说这很长,不,我无法预测,是的,没关系让用户等待那 17 分钟)
- 在按钮 returns 之后,应用程序显示它失去了与服务器的连接。 (“服务器连接丢失,正在尝试重新连接...”)
服务器关闭会话的原因是 com.vaadin.server.communication.HeartbeatHandler
大约 15 分钟(=3x5 分钟 = 3x 心跳间隔)没有收到心跳消息。
并且服务器有 15 分钟没有收到心跳消息,因为在 com.vaadin.server.SynchronizedRequestHandler.handleRequest(VaadinSession, VaadinRequest, VaadinResponse)
会话中有一个锁(对于心跳请求和执行的按钮,它是具有相同 ID 的同一个对象请求)。
解决方法 A:将心跳间隔设置为 10 分钟,使按钮的执行范围为 3x10 = 30 分钟。
解决方法 B:修改 HeartbeatHandler class 并通过覆盖 handleRequest 方法禁用会话锁定(并且对 UnsupportedBrowserHandler
、SessionRequestHandler
和 VaadinService.findOrCreateVaadinSession
(这是我对改变感到不舒服的那个)):
@Override
public boolean handleRequest(VaadinSession session, VaadinRequest request,
VaadinResponse response) throws IOException {
if (!canHandleRequest(request)) {
return false;
}
// ## This is part of the relevant change
// session.lock();
try {
return synchronizedHandleRequest(session, request, response);
} finally {
// ## This is part of the relevant change
// session.unlock();
}
}
解决方法 C:异步执行每个按钮。这似乎很费力,因为该应用程序中有很多按钮。
问题:Vaadin 中是否有更标准化的方法来保持 Heartbeat 继续运行(并保持会话活动),即使很少有按钮执行时间超过默认值的 3 倍心跳间隔(=3x 5 分钟)?
正如安德烈所说,解决方法 C 是正确的做法。我什至不会称之为解决方法,而是您只需要做的事情。还要注意,解决方法 B 是绝对错误的,并且会破坏事物。解决方法 A,是的,心跳是可调的,但不是为此目的。这通常是相反的需求,即缩短服务器丢弃放弃UI的更积极,从而减少为它们保留的资源。
情况的简短描述:单击 Vaadin 按钮时,Vaadin 心跳评估被会话锁定阻止。当按钮操作的执行时间超过 3 个心跳间隔时,连接就会丢失。
小问题:有没有办法让心跳继续,即使按钮点击执行需要超过 3 个心跳间隔?
更详细的情况描述: 在 Vaadin 8.8.6 应用程序中,我遇到了这种情况(相关代码似乎没有更改到 14.6.9 甚至更高版本):
- 应用程序中的 handling/execution 按钮点击通常在几秒钟内完成。
- 在极少数情况下,有些操作(文件导入/转换/导出)需要 17 分钟才能执行(是的,对于一个按钮来说这很长,不,我无法预测,是的,没关系让用户等待那 17 分钟)
- 在按钮 returns 之后,应用程序显示它失去了与服务器的连接。 (“服务器连接丢失,正在尝试重新连接...”)
服务器关闭会话的原因是 com.vaadin.server.communication.HeartbeatHandler
大约 15 分钟(=3x5 分钟 = 3x 心跳间隔)没有收到心跳消息。
并且服务器有 15 分钟没有收到心跳消息,因为在 com.vaadin.server.SynchronizedRequestHandler.handleRequest(VaadinSession, VaadinRequest, VaadinResponse)
会话中有一个锁(对于心跳请求和执行的按钮,它是具有相同 ID 的同一个对象请求)。
解决方法 A:将心跳间隔设置为 10 分钟,使按钮的执行范围为 3x10 = 30 分钟。
解决方法 B:修改 HeartbeatHandler class 并通过覆盖 handleRequest 方法禁用会话锁定(并且对 UnsupportedBrowserHandler
、SessionRequestHandler
和 VaadinService.findOrCreateVaadinSession
(这是我对改变感到不舒服的那个)):
@Override
public boolean handleRequest(VaadinSession session, VaadinRequest request,
VaadinResponse response) throws IOException {
if (!canHandleRequest(request)) {
return false;
}
// ## This is part of the relevant change
// session.lock();
try {
return synchronizedHandleRequest(session, request, response);
} finally {
// ## This is part of the relevant change
// session.unlock();
}
}
解决方法 C:异步执行每个按钮。这似乎很费力,因为该应用程序中有很多按钮。
问题:Vaadin 中是否有更标准化的方法来保持 Heartbeat 继续运行(并保持会话活动),即使很少有按钮执行时间超过默认值的 3 倍心跳间隔(=3x 5 分钟)?
正如安德烈所说,解决方法 C 是正确的做法。我什至不会称之为解决方法,而是您只需要做的事情。还要注意,解决方法 B 是绝对错误的,并且会破坏事物。解决方法 A,是的,心跳是可调的,但不是为此目的。这通常是相反的需求,即缩短服务器丢弃放弃UI的更积极,从而减少为它们保留的资源。