【问题标题】:Nashorn: concurrent eval with singleton ScriptEngine ? thread safe?Nashorn:使用单例 ScriptEngine 进行并发评估?线程安全吗?
【发布时间】:2016-07-26 01:18:41
【问题描述】:

我们想在一个 servlet 中使用 Nashorn。这个想法是使用在每个请求中重用的 ScriptEngine 的单例实例。在每次请求时,都会创建一个新的 EngineScope 绑定,并使用该绑定运行 eval。然后绑定被清除。没有共享对象被传递给绑定(只有来自 servlet 的请求/响应对象)。

在 servlet 中,ScriptEngine 的单例实例可能会在不同的线程中同时进行评估,这会正常工作还是会遇到线程问题?这是一些给出这个想法的代码:

ScriptEngine engine = getNashornSingleton();

ScriptContext newContext = new SimpleScriptContext();
newContext.setBindings(engine.createBindings(), ScriptContext.ENGINE_SCOPE);
Bindings engineScope =newContext.getBindings(ScriptContext.ENGINE_SCOPE);

engineScope.put("request", request);
engineScope.put("response", response);

engine.eval(jsCode, engineScope);
engineScope.clear();

【问题讨论】:

    标签: multithreading servlets nashorn


    【解决方案1】:

    我对自己问题的回答:我不会使用上述的单例。尽管存在一些潜在的线程问题,但您可能不希望在每次请求时破坏绑定(因为它可能需要重新编译脚本)。我们最终做的是创建一个引擎池及其关联的范围绑定。引擎/绑定对。

    在每个 servlet 请求中,我们从池中获取一个引擎/绑定对,将请求/响应放入绑定中,然后执行脚本。无需担心线程问题,因为给定的引擎/绑定对一次只能由一个线程执行。请求完成后,引擎/绑定对将返回到池中。看起来效果不错。

    【讨论】:

    • 我只是想知道您是否可以提供更多有关您的设置的详细信息。我们在 web 应用程序(使用 React 的服务器端渲染)中遇到了与 Nashorn 类似的并发问题。我们尝试将引擎包装在 ThreadLocal 中,但性能非常差。我们现在正在试验 CompiledScript 和 Invocable。你的游泳池有多大?我想如果你得到的请求数等于线程池大小,你会遇到问题......
    • 我选择了一个 nashorn 引擎池。我的第一次尝试是只拥有一个引擎池,并且每次都重新创建新的绑定(但这似乎会在每次调用脚本时强制重新编译 nashorn 脚本。所以,我创建了一个包装器对象来保存引擎及其关联的绑定。这不需要每次 servlet 调用相同的脚本时都重新编译脚本。一旦 servlet 完成,包装器对象将返回到池中。
    • 每隔一段时间就会调用一个收割线程来破坏未使用的引擎/绑定。性能足够好。比常规 servlet 稍慢,但很好。关于如何在不重新编译的情况下从文件加载脚本有很多小细节。我正在考虑开源它,你怎么看?
    • nsahorn sripts 不运行是一个单独的线程,但与 servlet 线程在同一个线程中。因此,无需担心每个请求添加更多线程。该池不是线程,而是可重用的 nashorn 引擎/绑定。
    • 关于池大小,它是动态增长的。如果池中没有引擎空闲引擎,它会创建一个新引擎并将其添加到池中。游泳池可以变大,但这没什么大不了的。一旦负载下降,它们最终将被收割线程收集。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多