2015-09-16 10 views
18

私はJavaライブラリ、実際にはClojureライブラリを作成していますが、この質問のために重要なのはJVM上で動作することです。このライブラリはJavaScriptを実行する必要があります。 I tried with Nashornしかし、私は克服するのが難しいかもしれないいくつかの制限に遭遇する。代わりに、私はNodeJSを試してみたいです。JavaアプリケーションからNodeJSを実行するにはどうすればよいですか?

私はライブラリを自己完結型にしたいので、NodeJSを単独で実行しているシステムに依存しないようにしてください。そして、JavaとNodeJS成果物を適切な場所に配置して、 。しかし、このアプローチにはいくつかの問題があります。

私はNodeJSとHTTPで話していますが、NodeJSが特定のポートを開くことは望ましくありません。ランダムな未使用のものを見つけて、衝突がないようにしたい。また、NodeJSのログをどこのアプリケーションと一緒に保管するかを制御する必要があります。最後に、私のアプリは、NodeJSがクラッシュして再実行したときを検出したり、情報のエラーを報告したりすることができます。

このアプローチにはどのような方法が最適ですか?このような方法で子プロセスを管理するためのJavaライブラリがありますか?特にNodeJS側から行うべきことは何でもあります(私はNodeJSを初めて使ったことがあります。

+0

私はそれはあなたのライブラリーが消費されることを意図しているかによって異なりますが、その作業を達成するために、ライブラリの打ち上げを有するヘビー級サーバー・プロセスはコードのにおいのように思えるとします。 –

+0

あなたはアバターのことを聞いたことがありますか?私はいくつかの問題を抱えていましたが、nodejsモジュールを使うことはできませんでしたが、アバターがギャップを埋めました:https://strongloop.com/strongblog/how-to-run-node-js-on-the-jvm-with-avatar- js-and-loopback/ – Tiago

+0

ちょうど答えを絞り込む...あなたは正確に遭遇した制限は何ですか? nashornを使用したサーバーサイドスクリプティングでは、avgに6msが追加されます。最終的にあなたのポストのレスポンスタイムがあるので、パフォーマンスはそれらの1つではないと思います – cviejo

答えて

9

私のソリューションは、このようProcessBuilderを使用することでした。 inheritIOは、その出力を現在のプロセスの出力に移動させ、stdoutとstderrを効果的にマージします。そのNodeJSの上に

は、ポート番号として0を指定することにより、ランダムなポートを開き、ファイルに書き込み:

その後、Java側で開かれ
(let [app (-> (express) 
       (.use (cookie-parser)) 
       (.get "/" (fn [_req res] (.send res "Universal JavaScript engine for server side pre-rendering single page applications."))) 
       (.get "/render" render)) 
     server (.createServer http app)] 
    (.listen server 0 (fn [] (.writeFile fs (:port-file options) (.-port (.address server))))))))) 

(それが表示されるのを待っています):

(defn get-port-number [js-engine] 
    (or (with-timeout 
     (:start-timeout js-engine) 
     (loop [port-number (read-port-file js-engine)] 
      (if (string/blank? port-number) 
      (if (is-running? js-engine) 
       (do (Thread/sleep 100) 
        (recur (read-port-file js-engine))) 
       (throw (Exception. (str "While waiting for port number, process died: " (:path js-engine))))) 
      port-number))) 
     (throw (Exception. (str "Waited for " (:start-timeout js-engine) " for " (:path js-engine) " to start and report its port number but it timed out."))))) 
+0

http://nodyn.io/はどうですか? – Stanimir

+0

@Pablo 0でリッスンしているNode.jsが必ずしも期待どおりに動作しない場合があります。参照してください[ここ](http://stackoverflow.com/a/10266225/4133078) –

+0

@Stanimirどのように完全なnodyn.ioであることがわかりませんでした、それは非常に完了していないと、プロジェクトは正式に放棄されます。 – Pablo

6

Javaでjavascriptを実行するには、かなり良い答えhereがあります。そのようなものは、あなたの事件のために実行可能であろうか?そうでない場合は、ここでいくつかのリソースは次のとおりです。

  • Random port in nodejsあなたはビルド中に開いているポートを検索したり、自分のノードのアプリが、それはグラブのポートに基づいてJavaサーバーにHTTPリクエストを発射持つようにさらに別のサービスを打つことができました。
  • Winstonは、私が見つけた最も優れたログライブラリです。同じパスにログを記録する際に問題があってはいけません。
  • ForeverおよびPM2は、ノードを実行し続ける共通ノードプロセスマネージャです。私は現在、永遠に好きです(理由はわかりません)

ノード内で多くのCPUを使用しているようです。その場合、おそらくcluster moduleを使用することになります(したがって、nodejsは複数のコアを利用できます)。イベントループをブロックすると(CPUベースの処理が行われる場合は、フォークされたプロセスごとに1つの同時要求しか実行できません)。

+0

あなたが指摘した他の質問については、いいえ、すでにNashornを試してみました。 NodeJSのようなものが必要です。 – Pablo

4

Nashornには、いくつかのAPI(ドキュメントがたくさん残っています)に関する情報の検索や遅い起動など、いくつかの問題があります。

私が代わりに推薦する何を:サービスない子プロセスとして、サーバー側のレンダリングを扱います。

つまり、ポート10015の内部ネット上でNode.jsインスタンスを実行し、ローカル接続のみを許可することができます(任意の場所にログを送信することもできます)。次に、localhost:10015/posts/のように、レンダリングしたいページを持つサービスにリクエストを行い、Node.jsアプリケーションでヘッドレスブラウザの内部にページをレンダリングさせます(PhantomやSlimerのようなものを使用します)。事前レンダリングチームが作ったもの

は、あなたが見て可能性があり、あなたがForeversupervisordを使用することができますし、あなたがより速くトラクションを得るのを助けるために、あなたのノードサーバを維持するには、次の https://github.com/prerender/prerender-node

4

私は同様の位置にされていますここで私はpythonスクリプトからfortranを実行しなければならなかったので、ここに私の2セントがあります。このようなJavaでターミナルコマンドを使ってNode.jsのスクリプトを実行します。セットアップを

Runtime rt = Runtime.getRuntime(); 
String[] commands = {"node example.js", "args"}; 
Process proc = rt.exec(commands); 

BufferedReader stdInput = new BufferedReader(new 
    InputStreamReader(proc.getInputStream())); 

BufferedReader stdError = new BufferedReader(new 
    InputStreamReader(proc.getErrorStream())); 

// read the output from the command 
System.out.println("Here is the standard output of the command:\n"); 
String s = null; 
while ((s = stdInput.readLine()) != null) { 
    System.out.println(s); 
} 

// read any errors from the attempted command 
System.out.println("Here is the standard error of the command (if any):\n"); 
while ((s = stdError.readLine()) != null) { 
    System.out.println(s); 
} 

あなたのノードプログラムにパラメータを渡すと応答を得ることができます。 node.jsプログラムを何を使用しているのか分かりませんが、これが役立つかどうかはわかりません。

(defn create-process-builder [js-engine] 
    (doto (ProcessBuilder. ["node" (:path js-engine) 
          "--port-file" (:port-file js-engine) 
          "--default-ajax-host" (:default-ajax-host js-engine) 
          "--default-ajax-port" (str (:default-ajax-port js-engine))]) 
    .inheritIO)) 

し、それに開始を呼び出す:最後に

+0

この方法で注意すべき点の1つは、ノードプロセスが各コールでブートするのに約30msかかることです。 –

+0

また、私はOPがシステムにインストールされているノードに依存したくないと理解しました – cviejo

関連する問題