EJB或CDI bean中套接字客户端的最佳实践

时间:2014-01-20 10:09:08

标签: java sockets java-ee ejb

我的应用程序必须打开到服务器的tcp套接字连接,并定期收听传入消息。

在JEE 7应用程序中实现此目的的最佳实践是什么?

现在我有这样的事情:

@javax.ejb.Singleton
public class MessageChecker {

   @Asynchronous
   public void startChecking() {

     // set up things
     Socket client = new Socket(...);
     [...]


     // start a loop to retrieve the incoming messages
     while((line = reader.readLine())!=null){

        LOG.debug("Message from socket server: " + line);

    }

   }
}

使用@PostConstruct方法从@Startup bean调用MessageChecker.startChecking()函数。

@javax.ejb.Singleton
@Startup
public class Starter() {

   @Inject
   private MessageChecker checker;


   @PostConstruct
   public void startup() {
     checker.startChecking();
   }

}

您认为这是正确的做法吗? 实际上它运作不佳。应用程序服务器(JBoss 8 Wildfly)挂起,不再对关闭或重新部署命令作出反应。我觉得它会在while(...)循环中陷入困境。

干杯 弗兰克

1 个答案:

答案 0 :(得分:6)

Frank,在EJB上下文中执行任何I / O操作都是不好的做法。这背后的原因很简单。在群集中工作时:

  1. 在等待I / O连接超时和所有其他与I / O相关的等待超时时,它们将固有地相互阻塞。也就是说,如果连接没有阻塞超过一段时间,那么在这种情况下你将不得不创建另一个扫描死连接的线程。
  2. 只有一个EJB能够连接并发送/接收信息,其他EJB将排队等候。这样您的系统就无法扩展。无论您在群集中拥有多少EJB,实际上只有一个EJB可以完成其工作。
  3. 显然你已经遇到了问题:) Jboss 8似乎无法正确创建和销毁bean。
  4. 现在,我知道你的bean是@Singleton,因此你的架构不依赖于事务性,集群和从该套接字读取的分布。所以你可能会对此感到满意。

    但是:D,你要求的是符合java EE标准的解决方法。这是应该做的:

    • 重新设计您的解决方案以配合JMS。它“闻起来”就像你试图提供异步messaging功能(发送消息并等待回复)。您可能正在使用同步协议来执行异步消息传递。试一试。
    • 创建一个符合JCA的适配器,它将作为@Resource注入EJB中
      • 您将在AS级别配置连接池(因此您可以为不同的环境设置不同的值
      • 您将拥有事务性和回滚。当然,回滚行为必须由您编码
      • 您可以通过@Resource注释
      • 注入它

    有一些适配器,有些适合像手套,有些可能有点过度设计。

    Oracle JCA Adapter