我们有一个 Java 中的 Web 应用程序,它调用进度过程。Progress 4gl 版本是 10.x,在 AIX 上。
要求是实现以下功能:假设 Web 应用程序调用了一个进度过程。这使得 appserver 事务运行。在事务处理期间,如果用户关闭浏览器窗口,则需要识别 appserver 进程,并应使用其进程 ID 将其终止。进程的终止可以通过调用 shell 脚本来实现。如何识别即将关闭的 Web 应用程序会话的 appserver 进程 ID?
我们有一个 Java 中的 Web 应用程序,它调用进度过程。Progress 4gl 版本是 10.x,在 AIX 上。
要求是实现以下功能:假设 Web 应用程序调用了一个进度过程。这使得 appserver 事务运行。在事务处理期间,如果用户关闭浏览器窗口,则需要识别 appserver 进程,并应使用其进程 ID 将其终止。进程的终止可以通过调用 shell 脚本来实现。如何识别即将关闭的 Web 应用程序会话的 appserver 进程 ID?
你从汤姆和蒂姆那里得到了两个很好的答案。我认为你需要重新考虑你的架构。
但这并不能回答有关获取 PID 的问题。假设您运行某种与 Progress AppServer 的连接,该 AppServer 正在运行一个 .p 程序,并且在该程序中您可以执行以下操作:
FIND FIRST _MyConnection NO-LOCK.
/* You might not want to DISPLAY but rather do something else: */
DISPLAY _MyConnection._MyConn-Pid.
您也可以在操作系统中执行此操作。假设你已经运行了 proenv-script,所以你已经设置了你的环境,你可以这样做:
wtbman -name asXXX -query
(将 asXXX 替换为您的应用服务器的名称 - 默认为 asbroker1)。
输出是这样的:
OpenEdge Release 11.3.1 as of Fri Sep 13 19:00:23 EDT 2013
Connecting to Progress AdminServer using rmi://localhost:xxxx/Chimera (8280)
Searching for asXXX (8288)
Connecting to asXXX (8276)
Incorrect utility to use for asXXX (15827)
Broker Name : asXXX
Operating Mode : State-reset
Broker Status : ACTIVE
Broker Port : YYYY
Broker PID : ZZZZ
Active Servers : 2
Busy Servers : 0
Locked Servers : 0
Available Servers : 2
Active Clients (now, peak) : (0, 2)
Client Queue Depth (cur, max) : (0, 2)
Total Requests : 26322
Rq Wait (max, avg) : (18079 ms, 25 ms)
Rq Duration (max, avg) : (18079 ms, 25 ms)
PID State Port nRq nRcvd nSent Started Last Change
16319 AVAILABLE ZZZZZ 001447 001447 001447 Aug 8, 2014 11:50 Aug 14, 2014 13:20
16320 BUSY ZZZZZ 001385 001385 001385 Aug 8, 2014 11:50 Aug 14, 2014 13:10
查看pid列表。16319 可用且 16320 正忙并且已经持续了 10 分钟(如果现在时间是 13:20)。这告诉我们 PID 16320 很可能是挂起程序。
现在你可以这样做:
asbman -name asxxx -agentdetail 16320
这将为您提供更多信息,例如 PROPATH、堆栈跟踪和连接的数据库。在查找问题时非常有帮助。
如果 appserver 进程花费的时间足够长以至于这是一个问题,那么你做错了 - 通常对 appserver 的往返调用应该很短,以至于在此期间关闭浏览器并不重要。
其次,如果您正在无状态运行,则无法知道呼叫正在运行哪个 appserver 代理,因为最后一个呼叫可能已路由到多个代理中的任何一个,并且没有与呼叫者握手那是哪一个。
因此,做你正在寻找的唯一合理的方法是
所以真正的问题是你有长时间运行的任务,用户会因为不耐烦而放弃并重试(可能是由于缺乏对任务进度的反馈)?
您尚未提供有关“Java 中的 Web 应用程序”的任何详细信息,因此我真的不知道您在做什么,也不知道它与 Progress 应用程序服务器会话有何关系。
为了让 Web 应用程序终止远程运行的进程,它需要对该远程进程有某种引用。听起来您当前正在同步调用远程进程并等待响应。您需要做的第一件事是异步调用远程进程(Progress 确实支持异步应用服务器调用。这可能是一个起点。但这取决于“Java 中的 Web 应用程序”的含义。)
如果您可以以某种方式异步调用该进程,那么您应该在启动它时获取 PID(或其他可用于外部参照该进程的唯一标识符)。当您弹出确认警报框以正确输入“kill”命令时,可以使用它。
如果您无法弄清楚如何进行异步应用服务器调用,那么使用同步调用模拟此类事情的粗略方法是通过 db 表编组请求(和响应):
插入描述请求的记录,提供所有必要的参数和上下文以独立启动请求,然后将请求 ID 返回给调用者。
然后调用者循环——暂停一段时间并检查请求的状态。这应该是一个非常简单的调用,它只是从数据库中读取请求记录以提取其状态。
在远程,一个或多个批处理正在循环读取请求表以查找新记录。当他们找到一个时,他们会启动一个进程来执行请求。您可以在这里使用各种控件和负载平衡的东西,或者您可以保持简单和容易。
执行请求的进程会适当地更新状态记录,以便 Web 浏览器客户端可以看到正在发生的事情。(第2步)
当请求完成时,结果将反馈给客户端——可能通过数据库表或作为新页面。这取决于应用程序。基本思想是,当第 2 步注意到状态为“完成”时,它会执行任何适当的操作来验证结果。
如果客户端决定终止一个请求,它应该在步骤#1 中接收到足够的信息以将该引用传递给服务器,以便服务器可以对其进行操作。通常,您希望将请求记录的状态更新为“已终止”(或其他),然后允许子进程注意到这一点并自行终止,或者使用操作系统级别的工具来执行实际的“终止”。
顺便说一句——如果您适当地组织了其中的“上下文和参数”部分,您可能能够识别并消除重复的请求,或者至少缓存答案。