2012-02-01 4 views
9

kullanarak Netty'de canlı iletileri tutma Netty 3.2.7 kullanıyorum. İstemcimde işlevsellik yazmaya çalışıyorum, öyle ki, belirli bir süre sonra mesaj yazılmazsa (30 saniyede), sunucuya "canlı kal" mesajı gönderilir.WriteTimeoutHandler

Bazı kazma işleminden sonra, WriteTimeoutHandler'in bunu yapmamı sağladığını buldum. Bu açıklamayı burada buldum: https://issues.jboss.org/browse/NETTY-79.

Netty belgelerinde verilen örnektir: benim test istemcisi olarak

public ChannelPipeline getPipeline() { 
    // An example configuration that implements 30-second write timeout: 
    return Channels.pipeline(
     new WriteTimeoutHandler(timer, 30), // timer must be shared. 
     new MyHandler()); 
} 

, sadece bu yaptık. MyHandler, ben de exceptionCaught() yöntemini overrided: istemci kanalına şey yazmaz neyi süresi olursa olsun

public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) { 
    if (e.getCause() instanceof WriteTimeoutException) { 
     log.info("Client sending keep alive!"); 
     ChannelBuffer keepAlive = ChannelBuffers.buffer(KEEP_ALIVE_MSG_STR.length()); 
     keepAlive.writeBytes(KEEP_ALIVE_MSG_STR.getBytes()); 
     Channels.write(ctx, Channels.future(e.getChannel()), keepAlive); 
    } 
} 

, ben geçersiz kıldık exceptionCaught() yöntemi asla denir. WriteTimeoutHandler kaynağı baktığımızda

, onun writeRequested() uygulamasıdır. Burada

public void writeRequested(ChannelHandlerContext ctx, MessageEvent e) 
     throws Exception { 

    long timeoutMillis = getTimeoutMillis(e); 
    if (timeoutMillis > 0) { 
     // Set timeout only when getTimeoutMillis() returns a positive value. 
     ChannelFuture future = e.getFuture(); 
     final Timeout timeout = timer.newTimeout(
       new WriteTimeoutTask(ctx, future), 
       timeoutMillis, TimeUnit.MILLISECONDS); 

     future.addListener(new TimeoutCanceller(timeout)); 
    } 

    super.writeRequested(ctx, e); 
} 

, uygulama yazma başarılı olduğunda, yeni bir zaman aşımı yapmak bir yazma istendiğinde" diyor görünüyor , zaman aşımını iptal et. "

Bir hata ayıklayıcısını kullanarak, bunun gerçekleştiği görülüyor. Yazma tamamlandığında, zaman aşımı iptal edilir. Bu istediğim davranış değil. İstediğim davranış: "İstemci 30 saniye boyunca herhangi bir bilgi kanalına yazmamışsa, bir WriteTimeoutException atın."

Bu yüzden WriteTimeoutHandler bunun için uygun değil midir? Bu, çevrimiçi okuduklarımdan nasıl yorumladım, ancak uygulama bu şekilde çalışmıyor gibi görünüyor. Yanlış mı kullanıyorum? Başka bir şey kullanmalı mıyım? Aynı istemcinin Mina versiyonunda yeniden yazmaya çalışıyorum, istediğim davranışa ulaşmak için sessionIdle() yönteminin geçersiz kıldığını görüyorum, ancak bu yöntem Netty'de mevcut değil.

cevap

5

IdleStateHandler'u eklemeyi ve ardından boşta kalma durumuna tepki verebilen IdleStateAwareUpstreamHandler özel uygulamanızı eklemenizi öneririm. Bu benim için pek çok farklı projede çok iyi çalışıyor.

Javadocs size uygulamasının temel olarak kullanabileceği, şu örneği listelemek: Netty 4.0 ve yeni İçin

public class MyPipelineFactory implements ChannelPipelineFactory { 

    private final Timer timer; 
    private final ChannelHandler idleStateHandler; 

    public MyPipelineFactory(Timer timer) { 
     this.timer = timer; 
     this.idleStateHandler = new IdleStateHandler(timer, 60, 30, 0); 
     // timer must be shared. 
    } 

    public ChannelPipeline getPipeline() { 
     return Channels.pipeline(
      idleStateHandler, 
      new MyHandler()); 
    } 
} 

// Handler should handle the IdleStateEvent triggered by IdleStateHandler. 
public class MyHandler extends IdleStateAwareChannelHandler { 

    @Override 
    public void channelIdle(ChannelHandlerContext ctx, IdleStateEvent e) { 
     if (e.getState() == IdleState.READER_IDLE) { 
      e.getChannel().close(); 
     } else if (e.getState() == IdleState.WRITER_IDLE) { 
      e.getChannel().write(new PingMessage()); 
     } 
    } 
} 

ServerBootstrap bootstrap = ...; 
Timer timer = new HashedWheelTimer(); 
... 
bootstrap.setPipelineFactory(new MyPipelineFactory(timer)); 
... 
+0

On dakikadan kısa bir sürede önerdiğiniz değişiklikleri uygulayabildim ve mükemmel çalışıyor. Teşekkürler bayım! – ImmuneEntity

+1

Dokümanlar, [IdleStateHandler.html] (http://static.netty.io/3.6/api/org/jboss/netty/handler/timeout/IdleStateHandler.html), [IdleStateAwareChannelHandler.html] (http: // adresine taşındı. static.netty.io/3.6/api/org/jboss/netty/handler/timeout/IdleStateAwareChannelHandler.html) – mxro

8

, sen IdleStateHandler documentation gelen örnekte olduğu gibi ChannelDuplexHandler uzatmak olmalıdır:

// An example that sends a ping message when there is no outbound traffic 
// for 30 seconds. The connection is closed when there is no inbound traffic 
// for 60 seconds. 

public class MyChannelInitializer extends ChannelInitializer<Channel> { 
    @Override 
    public void initChannel(Channel channel) { 
     channel.pipeline().addLast("idleStateHandler", new IdleStateHandler(60, 30, 0)); 
     channel.pipeline().addLast("myHandler", new MyHandler()); 
    } 
} 

// Handler should handle the IdleStateEvent triggered by IdleStateHandler. 
public class MyHandler extends ChannelDuplexHandler { 
    @Override 
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { 
     if (evt instanceof IdleStateEvent) { 
      IdleStateEvent e = (IdleStateEvent) evt; 
      if (e.state() == IdleState.READER_IDLE) { 
       ctx.close(); 
      } else if (e.state() == IdleState.WRITER_IDLE) { 
       ctx.writeAndFlush(new PingMessage()); 
      } 
     } 
    } 
}