如何隔离Java EE中的用户会话?

fer*_*olo 8 java session isolation java-ee

我们正在考虑在Java EE中开发关键任务应用程序,并且让我印象深刻的一件事是平台中缺少会话隔离.让我解释一下这个场景.

我们有一个原生的Windows应用程序(一个完整的ERP解决方案),每月从稀疏的贡献者那里获得大约2k LoC和50个bug修复.它还支持脚本,因此客户可以添加自己的逻辑,我们不知道这样的逻辑是做什么的.每个服务器节点都有一个代理和一个进程池,而不是使用线程池.代理接收客户端请求,将其排队直到池化实例空闲,向该实例发送请求,向客户端传递响应,并将实例释放回进程池.

这种体系结构非常强大,因为有这么多稀疏贡献和自定义脚本,所以部署版本有一些严重的错误,例如无限循环,长时间等待的悲观锁定,内存损坏或内存泄漏,这种情况并不少见.我们实现了内存限制,请求超时和简单的监视器.只要某个进程无法正确及时地回答,代理就会杀死它,因此看门狗会检测并启动另一个实例.如果进程在开始响应请求之前崩溃,则代理会将相同的请求发送到另一个池化实例,并且用户不知道服务器端的任何故障(管理日志除外).这很好,因为有些实例在处理请求时会被伪代码慢慢删除.因为大多数会话数据都保存在客户端或(在极少数情况下)共享存储中,所以它似乎完美无缺.

现在考虑转向Java EE,我在规范或流行的应用程序服务器上找不到类似的东西,比如Glassfish和JBoss.是的,我知道大多数集群实现都使用会话复制进行透明故障转移,但是我们有一些小公司在一个简单的双节点集群上使用我们的系统(我们也有冒险者在单节点服务器上使用该系统) .使用线程池,我理解一个错误的线程可以使整个节点关闭,因为服务器无法检测并安全地杀死它.将整个节点关闭比杀死单个进程要糟糕得多 - 我们有部署,其中每个节点有大约100个池化流程实例.

我知道IBM和SAP已经意识到了这个问题

, 分别.但基于最近的JSR,论坛和开源工具,社区上没有太多活动.

现在问题来了!

  1. 如果你有类似的场景并使用Java EE,你是如何解决的?

  2. 您是否了解即将推出的开源产品或Java EE规范中可以解决此问题的更改?

  3. .NET有同样的问题吗?你能解释或引用参考文献吗?

  4. 您是否了解一些可以解决此问题的现代开放平台,并且值得完成ERP业务逻辑的任务?

拜托,我不得不告诉你不要做更多的测试或任何类型的QA投资,因为我们不能强迫我们的客户在他们自己的脚本上做这个.我们还有一些案例,其中紧急错误修复必须绕过QA,并且当我们强迫客户接受此时,我们不能让他接受有缺陷的软件部分会影响一系列不相关的功能.这个问题是关于健壮的架构,而不是开发过程.

感谢您的关注!

Wil*_*ung 6

您偶然发现的是使用Java和"恶意"应用程序的基本问题.

这不仅是Java EE级别的基本问题,而且是核心JVM级别的基础问题.可用的典型JVM在加载"不安全代码"时存在各种问题.从内存泄漏,类加载器泄漏,资源耗尽和不清洁的线程杀死,典型的JVM根本不够健壮,无法在共享环境中很好地处理性能不佳的代码.

一个简单的例子是Java堆的内存耗尽.作为一个基本规则,NOBODY(并且没有人,我特别指的是核心java库以及几乎所有其他第三方库)捕获OutOfMemory异常.有少数人这样做,但即便他们也无能为力.典型的代码处理他们"期望"处理的异常,但让其他人失败.运行时异常(其中OOM是其中一个)将很快通过调用堆栈一直到顶部,留下未经检查的关键路径代码的残骸,使所有类型的事物处于未知状态.

诸如构造函数或静态初始化器之类的东西,"不能失败",留下未初始化的类成员,这些成员"永不为空".这些受损的班级根本不知道他们受损了.没人知道它们已经损坏了,而且没有办法清理它们.击中OOM的堆是一个不安全的图像,几乎需要重新启动(当然,除非你自己编写或审核了所有代码,当然,你不会 - 谁会这样做?).

现在,可能有特定于供应商的JVM,它们表现得更好并且可以让您更好地控制.基于Sun/Oracle JVM(即大多数)的那些不支持.

因此,它不一定是Java EE问题,它是JVM问题.

在JVM中托管恶意代码是个坏主意.唯一可行的方法是,如果您托管脚本语言,并且该脚本语言实现某种资源控制.这可以做到,你可以调整现有的作为开始(JavaScript,Groovy,JPython,JRuby).这些语言允许用户直接访问Java库这一事实使它们具有潜在的危险性,因此您可能必须将其限制为仅由脚本处理程序包装的方面.但是,在这一点上,"为什么要使用Java"问题浮出水面.

您会注意到Google App Engine不会执行这些操作.它为每个正在运行的应用程序分离一个单独的JVM,但即便如此,它也极大地限制了在这些JVM中可以完成的工作,特别是通过现有的Java安全模型.这里的区别在于这些实例往往"长寿",以免承受启动和关闭的处理成本.我应该说,它们应该是长寿的,而那些不存在的则会产生这些代价.

您可以自己创建JVM的几个实例,为它们提供一些基础结构来处理逻辑请求,为它们提供自定义类加载器逻辑以尝试防止类加载器泄漏,并且最低限度地让您终止实例(它们只是简单的一个过程)如果你想.这可以工作,并且可能工作"ok",具体取决于调用的粒度,以及逻辑的"启动"时间.启动时间最低限度是从运行到运行的逻辑类的加载,仅此一点可能会使这个想法变坏.它肯定不会是"Java EE".Java EE没有设置为执行此类操作.但是你还不清楚你正在寻找什么样的Java EE功能.

实际上,这就是Apache和"mod_php"的作用.有几个实例,作为进程,单独处理请求,一旦被扼杀就会表现得很糟糕.这就是PHP在共享托管业务中很常见的原因.在这种结构中,它基本上是"安全的".