2010-10-17 108 views
1

问候, 我无法提供该问题的所有细节,因此这里的关键细节。如何避免性能瓶颈使用JNI时Java Web应用程序/服务

我有一个本地的dll(和相应的.so)包装静态库,这是由艾菲尔编程语言创建的。 我已经写了一个关于静态库的C++包装器,并且我已经成功地将它公开给了Java。但是,如果我在Web应用程序中使用这个DLL,事情会变得有点复杂。问题是多个Java线程将访问相同的C++代码,其中本地上下文(?)由不同类的实例在调用之间保持不变。 为了使用来自Eiffel代码的功能,必须从C++初始化Eiffel运行时,然后使用Eiffel库来利用C++中的Eiffel类。 不幸的是,这意味着所有到Java服务器端的传入请求最终都会在C++中的一个位置(在本地dll中),只有一个Eiffel运行时。 这种情况迫使我使整个Eiffel运行时线程安全,并且只有一个Java线程的操作可以通过传递JNI来使用Eiffel代码。 我有一种感觉,这可能很快成为一个可扩展性问题。

我觉得我可能需要的工艺池,每个加载同一个DLL(或.so下* nix中),这将送达从Java线程进入一个副本。所以一旦加载共享库,C++代码将创建10个进程,并且来自Java端的进入线程将通过C++代码分配给这些进程。 事件的流会是这样:

Java线程访问共享库的本机代码(C++)。 原生代码检查哪些进程可从进程池 利用通过IPC的方法之一,标志着它忙(可能使用一个线程?)

这是唯一的跨平台的方式我能想到的安全地加载相同的一段代码(Eiffel运行时和埃菲尔类),没有任何线程安全问题。

这一切都是由于艾菲尔运行时是昂贵的,和全球组件,我必须通过JNI暴露。

或者我应该简单地用线程安全的操作,其中只有一个线程从JNI提供在任何时间去? 我可以用Java做什么技巧来创建每个仅使用单个Eiffel运行时的轻量级隔离jvm容器?

您的反馈将不胜感激。

问候 谢雷夫

回答

1

第一个问题:如果你有单独的进程中加载​​,他们会正确操作DLL的多个副本?假设“是”,那么你有多个副本运行声音的想法有潜力。 (其实还有另外一个问题要问:我假设在Java中重新实现Eiffel已经被检查并且证明它太差劲?)

我的倾向首先是检查你的简单,单一的,线程安全的方法可能会提供足够好的性能。如果没有,并且您需要可扩展性,那么另一种可能性是考虑使用几个便宜的机器(或虚拟机) - 这具有简单性的优点。花费更多的机器并不需要太多的开发工作。

否则您对“服务”流程池的想法听起来像是一个合理的想法。有很多不同的进程间通信(IPC)的可能性。几乎按照定义,您在每次调用中花费了很长时间(否则您会遇到问题)服务中,因此在这种情况下,实际的IPC机制不需要进行高度优化 - 有利于简化管理。我会首先看看使用JMS的基于队列的方法 - 是的,还有很多其他选项,包括RMI或低级套接字 - 但JMS有两个优点:它非常容易和可扩展性不佳,请求者只是弹出消息一个队列,从来不需要知道可能有多少服务进程。在一些供应商平台上也有趣的是JMS的C++实现(XMS是我使用的),因此您甚至不会在服务过程中使用Java。

为了详细阐述:起始位置是

WS-Client ---WS Call ---> WS in Web App ---JNI--->C++/Eiffel 

我建议使用

WS-Client ---WS Call ---> WS in Web App --JMS enq--> Q --JMS deq--> Java---JNI--->C++/Eiffel 

WS-Client ---WS Call ---> WS in Web App --JMS enq--> Q --XMS deq--->C++/Eiffel 

反应可以在temparary响应队列与所述请求消息中返回含有回复Q的名称和相关信息。

碰巧这后一种模式几乎是我目前的应用程序正在做的很好的性能。我认为在C++/Eiffel引擎中没有Java可能是一个胜利。如果这种对JMS的伪同步使用看起来没有吸引力,那么我的选择是使用带有远程接口的EJB。这个想法再次将所有的可扩展性工作推到基础架构中。

+0

埃菲尔代码基数很大,目前没有重写它的机会。我正在研究创建多个沙盒jvms或应用服务器实例,这些实例在后台都使用单线程安全dll。我看不到如何使用JMS与传入的Web服务请求,需要连接到jni后端,你能解释一点吗?无论如何感谢您的回应。 – mahonya 2010-10-17 16:47:18

+0

我扩大了一点。我们正在使用这种模式取得一些成功。 – djna 2010-10-18 05:48:07

+0

看起来很有希望,感谢您的更新。我不确定我能否得到返回响应的机制。我可能会让Web服务调用等待,直到它收到来自jms队列的请求的响应。这可能是确保线程安全性的一种更好的方式,而不必考虑C++或JNI线程安全机制的具体细节。 – mahonya 2010-10-19 10:51:32