作为服务与大型 java 程序交互?

Interacting with a large java program as a service?

我怎样才能做到以下几点?

我想做的是一次加载 Stanford NLP,然后通过 HTTP 或其他端点与其交互。原因是加载时间很长,不可能每一个字符串都加载来分析。

例如,这是一个加载 jar 的简单 C# 程序中的斯坦福 NLP 加载...我正在寻找我在下面所做的事情,但在 java:

    Reading POS tagger model from edu/stanford/nlp/models/pos-tagger/english-left3words/english-left3words-distsim.tagger ... done [9.3 sec]. 
    Loading classifier from D:\Repositories\StanfordNLPCoreNLP\stanford-corenlp-3.6.0-models\edu\stanford\nlp\models\ner\english.all.3class.distsim.crf.ser.gz ... done [12.8 sec]. 
    Loading classifier from D:\Repositories\StanfordNLPCoreNLP\stanford-corenlp-3.6.0-models\edu\stanford\nlp\models\ner\english.muc.7class.distsim.crf.ser.gz ... done [5.9 sec]. 
    Loading classifier from D:\Repositories\StanfordNLPCoreNLP\stanford-corenlp-3.6.0-models\edu\stanford\nlp\models\ner\english.conll.4class.distsim.crf.ser.gz ...  done [4.1 sec]. 
done [8.8 sec]. 

Sentence #1 ...

这超过了 30 秒。如果这些都必须每次都加载,哎呀。为了展示我想在 java 中做什么,我用 C# 编写了一个工作示例,这个完整的示例有一天可能会对某人有所帮助:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.IO;
using java.io;
using java.util;
using edu.stanford.nlp;
using edu.stanford.nlp.pipeline;
using Console = System.Console;

namespace NLPConsoleApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            // Path to the folder with models extracted from `stanford-corenlp-3.6.0-models.jar`
            var jarRoot = @"..\..\..\..\StanfordNLPCoreNLP\stanford-corenlp-3.6.0-models";
            // Text for intial run processing
            var text = "Kosgi Santosh sent an email to Stanford University. He didn't get a reply.";
            // Annotation pipeline configuration
            var props = new Properties();
            props.setProperty("annotators", "tokenize, ssplit, pos, lemma, ner, parse, sentiment"); 
            props.setProperty("ner.useSUTime", "0");
            // We should change current directory, so StanfordCoreNLP could find all the model files automatically
            var curDir = Environment.CurrentDirectory;
            Directory.SetCurrentDirectory(jarRoot);
            var pipeline = new StanfordCoreNLP(props);
            Directory.SetCurrentDirectory(curDir);
            // loop
            while (text != "quit")
            {
                // Annotation
                var annotation = new Annotation(text);
                pipeline.annotate(annotation);
                // Result - Pretty Print
                using (var stream = new ByteArrayOutputStream())
                {
                    pipeline.prettyPrint(annotation, new PrintWriter(stream));
                    Console.WriteLine(stream.toString());
                    stream.close();
                }
                edu.stanford.nlp.trees.TreePrint tprint = new edu.stanford.nlp.trees.TreePrint("words");
                Console.WriteLine();
                Console.WriteLine("Enter a sentence to evaluate, and hit ENTER (enter \"quit\" to quit)");
                text = Console.ReadLine();
            } // end while
        }
    }
}

所以它需要 30 秒来加载,但每次你在控制台上给它一个字符串时,它会花费最少的几分之一秒来解析和标记该字符串。

您可以看到我在 while 循环之前加载了 jar 文件。

这可能最终成为一个套接字服务,HTML,或者其他可以接受请求(以字符串的形式)并返回解析的东西。

我的最终目标是在 Nifi 中使用一种机制,通过一个可以发送要解析的字符串的处理器,并在不到一秒的时间内返回它们,而如果使用传统的 Web 服务器线程示例(例如实例)被使用。每个请求都会加载整个东西 30 秒,然后开始做生意。我希望我说清楚了!

如何操作?

您列出的任何机制都是通过 Apache NiFi 利用该服务的完全合理的前进路线。根据您的需要,与 NiFi 标准版本捆绑在一起的一些处理器和扩展可能足以与您提议的 Web 服务或类似产品进行交互。

如果您正在努力在 NiFi 本身内执行所有这些操作,自定义 Controller Service 可能是向 NiFi 提供此资源的好方法,它属于应用程序本身的生命周期。

NiFi 可以通过控制器服务和自定义处理器等项目进行扩展,我们有一些 documentation 可以帮助您开始这条道路。

其他详细信息肯定有助于提供更多信息。请随时在这里跟进并发表更多评论 and/or 通过我们的 mailing lists.

与社区联系

如果不清楚 NiFi 是 JVM 驱动的并且工作将以 Java 或 JVM 友好语言完成,我确实想提出一个项目。

你应该看看 the new CoreNLP Server which Stanford NLP introduced in version 3.6.0. It seems like it does just what you want? Some other people such as ETS 做过类似的事情。

要点:如果大量使用它,您可能(目前)想从 github HEAD 获取最新的 CoreNLP 代码,因为它包含一些对服务器的修复,将在下一个版本中。