0

假设我有四个遗留罐子:

  1. 我的库.jar
  2. 我的应用程序.jar
  3. 我的其他应用程序.jar
  4. log4j.jar

“我的应用程序”和“我的其他应用程序”是不相关的应用程序,都具有 main() 函数。他们都使用“my-library-app”中的各种库函数。这三个都通过 log4j 进行日志记录(真的是 slf4j,但我只是想让示例保持简单)。

目前,这两个应用程序设置了两个不同的 log4j 配置文件,这导致它们登录到两个不同的文件。

现在我想把所有东西都转换成 OSGi。因此,我将前三个分别捆绑为一个单独的捆绑包,将实际应用程序的 main() 转换为 Activators,然后捆绑或找到现有的 log4j 捆绑包。我在同一个 OSGi 框架中启动这两个应用程序。

但是现在这两个不同的应用程序不再登录到不同的文件!正确的?只有一个 log4j 实例在 JVM 中运行,它从一个 log4j.properties 文件中获取其配置。

所以也许不是分别捆绑我的四个罐子,我做了三个捆绑:

  1. 我的图书馆
  2. 我的应用程序加 log4j
  3. 我的其他应用程序加 log4j

现在我可以为两个不同的应用程序获取不同的日志记录配置文件。但是来自我的图书馆的日志调用呢?My Library 捆绑包将锁定到 log4j 的两个副本之一,现在从 My Library 生成的所有日志消息都将出现在两个日志文件中的一个特定文件中 - 比如说我的应用程序中的那个。但即使它是我的图书馆由于来自我的其他应用程序的调用而发出的日志消息也是如此!他们会转到错误的日志文件。

所以也许捆绑:

  1. 我的图书馆加 log4j
  2. 我的应用程序加 log4j
  3. 我的其他应用程序加 log4j

现在,我的库中的日志消息将转到他们自己的日志文件,我想这比其中一些转到错误的应用程序的日志文件要好,但仍然不是很好。该文件包含来自两个应用程序的日志消息,并且打算用于任一应用程序的日志文件都没有来自这些应用程序的所有日志消息。

所以也许捆绑:

  1. 我的应用程序加我​​的库加 log4j
  2. 我的其他应用程序加上我的图书馆加上 log4j

但是现在 OSGi 的意义何在?我没有分享我的图书馆或 log4j 的使用。实际上,情况可能会更糟——我必须将一堆 jar 包粘贴到我所有的实际应用程序包中,这仅仅是因为我想查看它们的日志消息与导致它们的应用程序相关联。

所以也许备份并尝试不同的东西:我认为这在 log4j 中是不可能的,但在(比如说)slf4j 中我可以回到原来的捆绑计划:

  1. 我的图书馆
  2. 我的应用
  3. 我的其他应用
  4. 日志4j

然后我做一些事情,比如把 MDC 信息放在每个线程中,说明线程来自哪个应用程序。对该 MDC 信息做出反应以确定它进入哪个日志文件。

但好像也行不通!从我的应用程序中的某个线程调用我的库中的某个函数可能会导致从我的库中生成一个新线程,这不一定与该 MDC 相关联。

更糟糕的是:我的图书馆可能有一些线程被任何使用我的图书馆的应用程序共享,所以不可能与一些这样的标记相关联。

所以,总而言之,我被难住了。任何建议将不胜感激。提前致谢。

4

3 回答 3

3

如果我理解正确:

  • 您曾经有两个完全独立的应用程序,在不同的 JVM 中运行。他们确实共享了一个库,但仅在文件系统级别上,应用程序彼此不知道。
  • 现在您使用一个 JVM,并且应用程序相互干扰(目前是 log4j,但可能还有其他问题),您想使用 OSGi 来解决这个问题。

我认为问题在于您将 OSGi 用作应用程序容器,就像将隔离不同应用程序的 servlet 容器一样。您希望 MyLibrary “属于” MyApp 或 MyOther 应用程序。据我所知,您真的不希望这些应用程序共享任何东西,只是为了在单个 JVM 中运行良好。

这并不是 OSGi 的真正目的,但我可以想到一些可能性:

  • 新的 OSGi 规范确实支持这个(称为子系统),但它是非常新的,对于您的用例来说可能有点过于复杂,而且据我所知还没有实现。我暂时不建议走这条路。

  • 你可以复制包,如果你给它们一个不同的符号名称,你可以依赖于特定的包,使用 Require-Bundle。然后我认为它应该工作,但坦率地说我认为它有点愚蠢。OSGi 然后什么都不添加,只是使事情复杂化,因为您最终会得到许多几乎相同的包。

  • 您可以在单个 JVM 中启动两个 OSGi 实例,每个实例都有自己的捆绑包。这应该以一种优雅的方式将您的两个应用程序分开(在此处查看 Neil 的答案)。运行多个 OSGi 实例非常轻量级,您可以使用相同的包(在文件系统级别),如果您确实想要共享代码,您可以将这些包添加到 org.osgi.framework.system.packages.extra 属性。我认为这是你最好的选择。

  • 最后,一些 OSGi 容器以专有方式支持这一点,例如 Eclipse Virgo 和 Apache Karaf。(在处女座称为“计划”,在卡拉夫称为“实例” )。可能值得一看,这实际上取决于您的情况。

希望能帮助到你,

坦率

于 2012-08-07T21:06:48.107 回答
2

最好的方法是从两个应用程序中删除日志记录设置(至少从您在 OSGi 中部署的 jars 中删除)。然后将 pax 日志添加到您的 OSGi 容器。Pax 日志支持 OSGi 上所有常见的日志 API。它可以配置一个 log4j 配置。在配置中,您可以设置 log4j 记录器和附加器来区分这两个应用程序。因此,您可以随心所欲地登录一两个文件。

您还可以将您的 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 实现(SLF4JBasicMDCAdapterLogbackMDCAdapter)使用InheritableThreadLocal. 新线程从父线程继承 MDC。但是,这需要通过您正在使用的实际实现进行验证。

另一种选择是在生成新线程时复制/复制库代码中的 MDC。

第三种选择是允许应用程序代码将记录器注入库运行时。因此,库代码将使用应用程序代码传递的记录器,而不是按类记录器方法。

于 2012-08-08T06:51:34.303 回答