安庆饭店推荐:1.1.2 基于开源框架实现消息方式的系统间通信(2)

来源:百度文库 编辑:偶看新闻 时间:2024/05/07 06:41:51

1.1.2  基于开源框架实现消息方式的系统间通信(2)

在使用Mina 2.0之前的版本时,以下几个方面值得注意:

使用自定义的ThreadModel

通过SocketConnectorConfig.setThreadModel(ThreadModel.MANUAL)将线程模式改为自定义模式,否则Mina会自行启动一个最大线程数为16个的线程池来处理具体的消息,这对于多数应用而言都不适用,因此最好是自行控制具体处理消息的线程池。

合理配置IO处理线程池

在创建SocketAcceptor或SocketConnector时要提供一个线程池及最大的线程数,也就是Mina用于IO事件处理的线程数,通常建议将这个线程数配置为CPU核数+1。

监听是否成功写入操作系统的发送缓冲区

在调用IoSession.write时,Mina并不确保其会成功写入操作系统的发送缓冲区中(例如写入时连接刚好断开),为了确定是否成功,可采用如下方法:

  1. WriteFuture writeResult=session.write(data);  
  2. writeResult.addListener(new IoFutureListener() {  
  3.     public void operationComplete(IoFuture future){  
  4.         WriteFuture wfuture=(WriteFuture)future;  
  5.         // 写入成功  
  6.         if(wfuture.isWritten()){  
  7.             return;  
  8.         }  
  9.             // 写入失败,自行进行处理  
  10.     }  
  11. }); 

这对于同步请求而言特别重要,通常同步请求时都会设置一个等待响应的超时时间,如果不去监听是否成功写入的话,那么同步的请求一直要等到设定的超时时间才能返回。

监听写超时

当接收消息方的接收缓冲区占满时,发送方会出现写超时的现象,这时Mina会向外抛出WriteTimeoutException,如有必要,可在IoHandler实现的exceptionCaught方法里进行处理。

借助Mina IoSession上未发送的bytes信息实现流控

当IoSession上堆积了过多未发送的byte时,会造成jvm内存消耗过多的现象。因此通常要控制IoSession上堆积的未发送的byte量,此值可通过Mina IoSession的getScheduledWriteBytes来获取,从而进行流控。

messageReceived方法占用IO处理线程

在使用Thread.MANUAL的情况下,IOHandler里的messageReceived方法会占用Mina的IO处理线程,为了避免业务处理接收消息的速度影响IO处理性能,建议在此方法中另起线程来做业务处理。

序列化/反序列化过程会占用IO处理线程

由于Mina的序列化/反序列化过程是在FilterChain上做的,同样会占据IO处理线程。Mina将同一连接上需要发送和接收的消息放在队列中串行处理。如果序列化/反序列化过程耗时较长,就会造成同一连接上其他消息的接收或发送变慢。

反序列化时注意继承CumulativeProtocolDecoder

在使用NIO的情况下,每次读取的流并不一定完整,因此要通过继承CumulativeProtocolDecoder来确保当流没读完时,下次接着读,这同时也要求应用在协议头中保持此次发送流的长度信息。

Mina 1.1.6及以前的版本中sessionClosed可能会不被调用的bug

在某些高压力的情况下,当连接断开时,Mina 1.1.6及以前的版本并不会调用IoHandler中的sessionClosed方法,这对于某些要在sessionClosed做相应处理的应用来说会出现问题,这个bug 在Mina 1.1.7的版本中已修复。

除了Mina之外,JBoss Netty也是现在一个广受关注的Java通信框架,其作者也是Mina的作者(Trustin Lee),据评测JBoss Netty的性能好于Mina ,如读者感兴趣,可访问http://www.jboss.org/netty来了解更多的细节。

以上两节介绍了基于Java自身包及开源通信框架来实现消息方式的系统间通信,Java系统内的通信都是以Java对象调用的方式来实现的,例如A a =new AImpl();a.call();,但当系统变成分布式后,就无法用以上的方式直接调用了,因为在调用端并不会有AImpl这个类。这时如果通过基于以上的消息方式来做,对于开发而言就会显得比较晦涩了,因此Java中也提供了各种各样的支持对象方式的系统间通信的技术,例如RMI、WebService等。同样,在Java中也有众多的开源框架提供了RMI、WebService的实现和封装,例如Spring RMI、CXF等,下面来看看基于远程调用方式如何实现系统间的通信。