【问题标题】:GlassFish running EJBs on different physical serversGlassFish 在不同的物理服务器上运行 EJB
【发布时间】:2012-03-15 20:12:18
【问题描述】:

我有一个在 GlassFish 3.1 上运行的 Java EE 6 Web 应用程序。该应用程序使用本地Singleton EJB MySingleton 的2 个实例。 MySingleton 的每个实例都通过 API 连接到第三方软件。

MySingleton.java

@Singleton
@LocalBean
public class MySingleton { 
    @PersistenceContext private EntityManager em;    
    private ThirdPartyAPI thirdPartyAPI;
    ...
}

MySingletonManager.java

@Singleton
@LocalBean
public class MySingletonManager { 
    @EJB private MySingleton mySingletonA;
    @EJB private MySingleton mySingletonB;        ///Aargh! They can't run on the same server!!
    ...
}

以下是限制条件:

  1. 第三方软件提供商要求其软件在不同的物理服务器上运行 ThirdPartyAPI 的每个实例
  2. MySingleton 使用EntityManager 的注入实例,在同一PersistenceContext 上进行查询和事务处理。

为了满足约束 1,我认为我需要远程访问 Singleton EJB:我需要告诉应用程序服务器“在服务器 A 上运行 mySingletonA,在服务器 B 上运行 mySingletonB”。为此,我看到有可能通过JNDI 调用远程 EJB。

为了满足约束 2,我认为我需要使用 GlassFish clustering,因为 PersitenceContext 需要在 MySingleton 的 2 个实例之间共享。

不幸的是,我找不到任何关于如何同时使用这两种技术(远程 EJB 和集群)的参考资料。

我正在寻找有关此场景的首选架构的提示或建议,以及最终的一些实施指南。

【问题讨论】:

    标签: jakarta-ee glassfish ejb jms jndi


    【解决方案1】:

    几件事...

    首先,如果您要连接到外部 EIS 系统,“正确”的方法是编写 JCA 适配器并使用 @Resource 注入实例。它们写起来相当简单,Adam Bien 有一个很好的例子来写一个简单的。将@Resource 想象为为您的应用程序制作自定义数据源。一旦你弄清楚这一切,它实际上很有趣。 JEE6 规范在技术上不支持编写任何使用套接字或同步的 EJB。

    如果您这样做,那么您可以在集群的两个成员上安装此适配器。每个集群成员都可以指向第三方软件的外部实例。如果任何一个集群成员出现故障,一切都会继续运行。

    但是...如果你真的想用单例 EJB 做一些困难的事情,你可以这样做:

    首先,摆脱 MySingletonManager。集群是透明的,你不应该知道你是集群的。其次将您的单例代码更改为:

    @Singleton
    @Remote
    public class MySingleton { 
        @PersistenceContext private EntityManager em;    
        private ThirdPartyAPI thirdPartyAPI;
        ...
    
    }
    

    了解单例不能有状态很重要。如果 ThirdPartyAPI 在调用之间保持状态,就会发生有趣的事情。您还必须在thirdPartyAPI 周围放置一个循环连接代码装饰器,以便它连接到您的两个ThirdPartyServers。最后,创建一个 GlassFish 集群并跨集群部署您的 EJB。像这样将它注入你的代码中:

    @EJB MySingleton myIns;
    

    这将自动在集群中的某处定位 EJB 并为您提供处理它的句柄。现在,假设这一切正常并且我没有遗漏任何内容,您现在遇到了并发问题,因为默认情况下,对任何 EJB 的访问都是序列化的。您可以添加 @ConcurrencyAttribute(NO_LOCK) 但 EntityManager 不是线程安全的,它也是事务性的。

    总的来说,Singleton EJB 会给您带来很多问题。花时间写一个 JCA 适配器!

    【讨论】:

    • 感谢您的回答。鉴于该主题的复杂性,我需要一些时间...顺便说一句:您能否澄清(最终通过一些参考资料)“单身人士不能有状态”?
    • 刚刚发现这篇关于单身人士java.sun.com/developer/technicalArticles/Programming/singletons 的有趣文章。感谢提示
    • 集群 J2EE 环境中的单例实际上将在集群中的每个节点上拥有一个单例实例。否则,将出现单点故障......因此,在集群环境中,将状态放入单例时必须采取额外的预防措施,因为它们不是“真正的”单例。最简单的管理方法是避免将状态放入集群单例中。
    • @perissf 在旁注中,如果您确实发现我的回答很有用,我当然会感谢您的支持或接受:) :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多