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

Fra*_*ank 0 java sockets ejb java-ee

我的应用程序必须打开到服务器的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);

    }

   }
}
Run Code Online (Sandbox Code Playgroud)

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

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

   @Inject
   private MessageChecker checker;


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

}
Run Code Online (Sandbox Code Playgroud)

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

干杯弗兰克

vic*_*tor 6

Frank,在EJB环境中进行任何I/O操作都是不好的做法.这背后的原因很简单.在群集中工作时:

  1. 在等待I/O连接超时和所有其他I/O相关的等待超时时,它们将固有地相互阻塞.也就是说,如果连接没有阻塞超过指定的时间,在这种情况下,您将不得不创建另一个扫描死连接的线程.
  2. 只有一个EJB能够连接并发送/接收信息,其他EJB将排队等候.这样您的系统就无法扩展.无论您在群集中拥有多少EJB,实际上只有一个EJB可以完成其工作.
  3. 显然你已经遇到了问题:) Jboss 8似乎无法正确创建和销毁bean.

现在,我知道你的bean是一个@Singleton所以你的架构不依赖于事务性,集群和从该套接字读取的分布.所以你可能会对此感到满意.

但是:D,您要求采用符合Java EE的方式解决此问题.这是应该做的:

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

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

Oracle JCA适配器