我需要以多线程方式执行 R eval
,这是 Rserve
提供的很好的方式。
但是,如果一个实例的评估花费的时间太长,我需要能够关闭正在计算阻塞评估的实例。据我测试,给定的实例将拒绝关闭,直到 eval 完成(显然,它需要在再次监听之前获取结果)。所以这是我的问题:
有没有办法在阻塞实例上获取 java 句柄(类似于 Process
对象),这样我就可以暴力终止/终止 eval(类似于 process.destroy ()
)?
换句话说,当我请求一个 eval(创建一个连接,抛出一个命令)时,我如何通过 java 在正在处理的 eval 和与之相关的 Rsere 实例之间建立关系?
或者我错过了 Rserve 的一些东西,它已经可以处理这种需求了?
注意:我已经尝试通过 serverEval()
而不是运行计算的常规 eval
来运行所有内容(所有评估)在主实例上,但这当然不能令人满意,因为它只使用一个进程(主进程)。我可以杀死那个,但我的主要目标是能够单独关闭在单个实例上运行的阻塞评估。而且,自然地,保持我的 8 个 CPU 内核的优势,也就是说,保持并行性。否则没有必要使用 Rserve(在这种情况下,JRI 引擎就足够了)。
注意:我想避免这种事情(thread),在不同端口上处理主服务器本身的多个实例。那不是一个选择。
我已经尝试获取有关 Rserve 邮件列表的信息,但没有得到答复。 我希望我说得足够清楚,可以在这里得到答案或有用的评论。如果没有,请询问详细信息。非常感谢。
编辑:我还测试了RCaller ,它处理一个需要的 R 实例,但是,因为它正在将结果写入 XML 文件以便以后从 Java 端解析(不像 Rserve 那样真正使用通信协议(protocol)),所以它对于我必须做的事情来说太慢了执行...
最佳答案
好的,这可以通过这种方式完成(从一些最终在 Rserve 开发邮件列表上回答我的好人那里得到的):
在运行 eval
的线程中应该是阻塞或太长,并假设 Rserve 已启动:
private RConnection rEngine = null;
private int rServePid = -1;
//...
// Keep an opened instance and store the related pid
RConnection rconn = new RConnection();
this.rServePid = rconn.eval("Sys.getpid()").asInteger();
this.rEngine = rconn;
LOG.info("Rserve: started instance with pid '" + this.rServePid + "'.");
//...
this.rEngine.eval("some consuming code...");
它允许跟踪与所述 eval
相关的实例的 pid(R 提供 Sys.getpid()
)。
然后停止/中止/取消,因为一个简单的 this.rEngine.close()
不会停止服务器端正在处理的任务,而只会关闭连接,我们需要终止有针对性的 Rserve 实例。这可以通过调用 tools::pskill()
(或任何其他系统调用,例如 kill -9 my_pid
(UNIX*)、TASKKILL/PID my_pid/F
(Windows),...,取决于平台),显然来自与上述线程不同的另一个线程(正在等待“评估部分”返回):
// Terminate.
RConnection c2 = new RConnection();
// SIGTERM might not be understood everywhere: so using SIGKILL signal, as well.
c2.eval("tools::pskill("+ this.rServePid + ")");
c2.eval("tools::pskill("+ this.rServePid + ", tools::SIGKILL)");
c2.close();
LOG.info("Rserve: terminated instance with pid '" + this.rServePid + "'.");
它具有独立于平台的优势。
希望对您有所帮助。
关于java - 保留服务器 : how to terminate a blocking instance (eval taking forever)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27066588/