0

私が4つのレガシーjarを持っているとしましょう:

  1. my-library.jar
  2. my-app.jar
  3. my-other-app.jar
  4. log4j.jar

「MyApp」と「MyOtherApp」は無関係なアプリケーションであり、どちらもmain()関数を備えています。どちらも「my-library-app」のさまざまなライブラリ関数を使用しています。3つすべてがlog4jを介してロギングを行います(実際にはslf4jですが、例を単純にしておきたいだけです)。

現在、2つのアプリケーションは2つの異なるlog4j構成ファイルでセットアップされているため、2つの異なるファイルにログが記録されます。

今、私はすべてをOSGiに変換したいと思います。そこで、最初の3つをそれぞれ個別のバンドルとしてバンドルし、実際のアプリのmain()をアクティベーターに変換して、バンドルするか、log4jの既存のバンドルを見つけます。同じOSGiフレームワークで両方のアプリを起動します。

しかし、2つの異なるアプリが異なるファイルにログインしなくなりました。右?JVMで実行されているlog4jのインスタンスは1つだけであり、その構成は1つのlog4j.propertiesファイルから取得されます。

したがって、4つのjarファイルをそれぞれ個別にバンドルする代わりに、3つのバンドルを作成します。

  1. 私の図書館
  2. 私のアプリとlog4j
  3. 私の他のアプリとlog4j

これで、2つの異なるアプリの異なるログ構成ファイルを取得できます。しかし、マイライブラリからのログ呼び出しはどうですか?My Libraryバンドルはlog4jの2つのコピーの1つにラッチされ、My Libraryから生成されたすべてのログメッセージは、2つのログファイルの1つ(たとえば、My App用)に出力されます。ただし、他のアプリからの呼び出しによるマイライブラリからのログメッセージであっても、それは当てはまります。彼らは間違ったログファイルに行きます。

だから多分バンドル:

  1. マイライブラリとlog4j
  2. 私のアプリとlog4j
  3. 私の他のアプリとlog4j

これで、マイライブラリからのログメッセージは独自のログファイルに送られます。これは、一部のメッセージが間違ったアプリのログファイルに送られるよりも優れていると思いますが、それでもあまり良くありません。そのファイルには両方のアプリからのログメッセージが含まれており、どちらのアプリを対象としたログファイルにもそれらのアプリからのすべてのログメッセージは含まれていません。

だから多分バンドル:

  1. マイアプリとマイライブラリとlog4j
  2. 私の他のアプリと私のライブラリとlog4j

しかし今、OSGiのポイントは何ですか?マイライブラリまたはlog4jの使用を共有していません。実際には、さらに悪化する可能性があります。実際のすべてのアプリバンドルに複数のコピーを貼り付ける必要があるjarがたくさんあります。これは、それらの原因となったアプリに関連付けられたログメッセージを確認したいからです。

したがって、バックアップして別のことを試してみてください。これはlog4jでは不可能だと思いますが、(たとえば)slf4jでは元のバンドルプランに戻ることができます。

  1. 私の図書館
  2. 私のアプリ
  3. 私の他のアプリ
  4. log4j

次に、スレッドがどのアプリからのものであるかを示すMDC情報を各スレッドに入れるようなことをします。そのMDC情報に反応して、どのログファイルに入るのかを判断します。

しかし、それもうまくいかないようです!マイアプリのスレッドからマイライブラリの関数を呼び出すと、マイライブラリから新しいスレッドが生成される可能性がありますが、これは必ずしもそのMDCに関連付けられているとは限りません。

そして、それよりも悪いことです。マイライブラリには、マイライブラリを使用するアプリで共有されるスレッドが含まれている可能性があるため、そのようなマーカーに関連付けることはできません。

だから、全体として、私は困惑しています。任意の提案をいただければ幸いです。前もって感謝します。

4

3 に答える 3

3

私があなたを正しく理解していれば:

  • 以前は、別々の JVM で実行されている 2 つの完全に別々のアプリケーションがありました。それらはライブラリを共有していましたが、ファイル システム レベルでのみ、アプリケーションは互いを認識していませんでした。
  • 現在、1 つの JVM を使用しており、アプリケーションが相互に干渉しています (現時点では log4j ですが、他の問題もある可能性があります)。OSGi を使用してこの問題を解決したいと考えています。

問題は、さまざまなアプリケーションを分離するサーブレット コンテナのように、OSGi をアプリケーション コンテナとして使用していることだと思います。MyLibrary を MyApp または MyOther アプリのいずれかに「所属」させたいとします。私の知る限り、単一の JVM 内で適切に動作するためだけに、これらのアプリケーションが何かを共有することは本当に望んでいません。

これは実際には OSGi が構築された目的ではありませんが、いくつかの可能性を考えることができます。

  • 新しい OSGi 仕様これ (サブシステムと呼ばれる) をサポートしていますが、これは非常に新しいものであり、ユース ケースにはおそらく少し複雑すぎます。また、私が知る限り、まだ実装はありません。今のところ、この道を歩くことはお勧めしません。

  • バンドルを複製できます。別のシンボル名を付ければ、Require-Bundle を使用して特定のバンドルに依存できます。それならうまくいくはずだと思いますが、率直に言って、少しばかげていると思います。その後、OSGi は何も追加せず、物事を複雑にするだけです。ほとんど同じバンドルがたくさんできてしまうからです。

  • 単一の JVM で 2 つの OSGi インスタンスを開始し、それぞれ独自のバンドル セットを使用できます。これにより、2 つのアプリケーションが一種のエレガントな方法で分離されます (ここでニールの回答を確認してください)。複数の OSGi インスタンスを実行するのは非常に軽量です。(ファイル システム レベルで) 同じバンドルを使用できます。また、コードを共有たい場合は、それらのパッケージを org.osgi.framework.system.packages.extra プロパティに追加できます。これが最善の策だと思います。

  • 最後に、一部の OSGi コンテナーは、Eclipse Virgo や Apache Karaf など、独自の方法でこれをサポートしています。(乙女座では「計画」、カラフでは「インスタンス」と呼ばれます)。一見の価値があるかもしれませんが、実際には状況によって異なります。

それが役に立てば幸い、

フランク

于 2012-08-07T21:06:48.107 に答える
2

これを行う最善の方法は、両方のアプリケーションから (少なくとも OSGi にデプロイする jar からは) ロギングの設定を削除することです。次に、OSGi コンテナーに pax ロギングを追加します。Pax ロギングは、OSGi 上のすべての一般的なログ API をサポートします。1 つの log4j 構成で構成できます。config では、2 つのアプリケーションを区別するために log4j ロガーとアペンダーを設定できます。そのため、好きなように 1 つまたは 2 つのファイルにログインできます。

OSGi アプリを、すでに pax ロギングが含まれている Apache Karaf にデプロイすることもできます。したがって、自分で設定する必要はありません。

参照: http://team.ops4j.org/wiki/display/paxlogging/Pax+Logging

http://karaf.apache.org/

于 2012-08-08T05:54:14.297 に答える
1

これは実際にはOSGiに固有のものではありません(Frankがすでに書いているように)。

MDCを使用することは、一般に、アプリケーション/ランタイム固有の情報でロギングコンテキストを強化するための優れたアプローチです。MDCを使用する機会があるかもしれません。一部のMDC実装(SLF4JBasicMDCAdapterおよびLogbackMDCAdapter)はを使用しInheritableThreadLocalます。新しいスレッドは、親スレッドからMDCを継承します。ただし、これは、使用している実際の実装で確認する必要があります。

もう1つのオプションは、新しいスレッドを生成するときに、ライブラリコード内のMDCをコピー/複製することです。

3番目のオプションは、アプリケーションコードがライブラリランタイムにロガーを挿入できるようにすることです。したがって、ライブラリコードは、クラスごとのロガーアプローチではなく、アプリケーションコードによって渡されたロガーを使用します。

于 2012-08-08T06:51:34.303 に答える