2016-04-11 6 views
1

このコードスニペットでは、shutdownGracefully()。syncUninterruptibly()は返されません。 これは予想される動作ですか、何か誤解しましたか? ネッティー4.0.35.FinalShutdownGracefully()が返さない

public class ShutdownGracefullyDemo { 
    private ServerBootstrap bootstrap; 

    public static void main(String[] args) throws Exception { 
     new ShutdownGracefullyDemo().initialize(); 
    } 

    private void initialize() throws InterruptedException { 
     NioEventLoopGroup group = new NioEventLoopGroup(); 
     bootstrap = new ServerBootstrap(); 
     bootstrap.group(group) 
      .channel(NioServerSocketChannel.class) 
      .handler(new LoggingHandler(LogLevel.INFO)) 
      .childHandler(new MyInboundHandler()) 
      .bind(2025) 
      .sync() 
      .channel() 
      .closeFuture() 
      .sync(); 
    } 

    @ChannelHandler.Sharable 
    private class MyInboundHandler extends SimpleChannelInboundHandler<ByteBuf> { 
     Charset charset = Charset.forName("US-ASCII"); 

     @Override 
     protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) 
      throws Exception { 
      String data = msg.toString(charset); 
      System.out.println("Received: " + data); 
      if ("quit\r\n".equals(data)) { 
       shutdown(); 
      } 
     } 
    } 

    private void shutdown() { 
     if (bootstrap != null && bootstrap.group() != null) { 
      bootstrap.group().shutdownGracefully().syncUninterruptibly(); 
      System.out.println("shutdown completed"); 
     } 
    } 
} 

答えて

0

あなたがシャットダウンし、以下のようなコードを使用してすることができますでテスト:

public void shutdown() { 
    LOG.info("Gracefully shutdown http server ..."); 
    bossGroup.shutdownGracefully(2, 2, TimeUnit.SECONDS); 
    workerGroup.shutdownGracefully(2, 2, TimeUnit.SECONDS); 
} 

方法 "syncUninterruptibly()" ソースコードクラスの「io.netty.util.concurrent .DefaultPromise ":タスクは待ち()メソッドでブロック

@Override 
public Promise<V> awaitUninterruptibly() { 
    if (isDone()) { 
     return this; 
    } 

    boolean interrupted = false; 
    synchronized (this) { 
     while (!isDone()) { 
      checkDeadLock(); 
      incWaiters(); 
      try { 
       wait(); 
      } catch (InterruptedException e) { 
       // Interrupted while waiting. 
       interrupted = true; 
      } finally { 
       decWaiters(); 
      } 
     } 
    } 

    if (interrupted) { 
     Thread.currentThread().interrupt(); 
    } 

    return this; 
} 

、()に通知するまで、それが継続したことがないことになるため、アプリケーションがシャットダウン完了することはできません。

+0

あなたの答えはDerekに感謝します!私のスニペットではNorman Maurerの本 "Netty in action"からインスピレーションを得ました。シャットダウンの例では、 'future.syncUninterruptibly()'メソッドは 'shutdownGracefully()'の後に呼び出され、実際にはシャットダウンを呼び出し、操作が完了したら私には意味があります。しかし何らかの理由で私がうんざりしていると、誰も待っているスレッドに通知していないので、これは期待どおりに機能しません。 – staedler

+0

サーバがすべてのクライアントチャネルを閉じるのを待っていて、デッドロックのようにこのチャネル上でタスクが実行されるため、新しいスレッドを作成してシャットダウンすることができます。 –

1

問題はデッドロックを作成していることです。

現在のイベントループ内のスレッドからshutdownGracefullyを呼び出すと、シャットダウンをスケジュールするようになり、続行する前にすべてのスレッドがシャットダウンするまで待機します。ループがシャットダウンするまで待っているため、すべてのスレッドがシャットダウンされず、事実上デッドロックが発生します。大規模なアプリケーションにおいて

、これを解決する複数の方法がある:マスター・スレッドを使用し

このシャットダウンメソッドを呼び出すグローバル・アプリケーションのメインスレッドを有することによって解くあります。すなわちシャットダウン法からスタックをアンワインドすることを可能にするよう

shutdownGracefully().addListener(e -> {System.out.println("shutdown completed");}) 

を行う

.shutdownGracefully().syncUninterruptibly(); 
System.out.println("shutdown completed"); 

代わりの:正常なシャットダウンにリスナーを追加

そのスレッドを正しく閉じる。

+0

ありがとう@Ferrybig、今私はそれを得た。あなたの最後のアドバイスに関しては、shutdownをすべきではありません。少なくともそれは私がnettyのドキュメントを読んで理解するものです:[link](http://netty.io/wiki/user-guide-for-4.x.html#shutting-down-your-application) "... EventLoopGroupが完全に終了し、そのグループに属するすべてのチャンネルが閉じられたときに通知する未来 " – staedler

+0

@staedlerあなたは最後のポイントが正しいと確信しています.nettyはエグゼキュータの子をシャットダウンしてチャンネルをシャットダウンします – Ferrybig

関連する問題