2016-10-22 12 views
0

Vertxを使用してTCPサーバーを実装しようとしています。着信接続を受け入れてから別のソケットを処理しています。各ソケットは独立して扱うことができるので、異なるソケットに属するハンドラは、異なるイベントループスレッドで同時に実行されるはずです。それらが作成され、開始メソッドは、そのイベントループで呼び出されたとき着信NetSocketハンドラを異なるイベントループスレッドにディスパッチする方法は?

Vert.x documentによれば、

標準verticlesはイベントループスレッドを割り当てられます。イベントループからコアAPI上のハンドラを受け取る他のメソッドを呼び出すと、Vert.xはそれらのハンドラが呼び出されると、同じイベントループで実行されることを保証します。

私はこのコードスニペットは、異なるスレッド名を印刷することができ、思う:

Vertx vertx = Vertx.vertx(); // The number of event loop threads is 2*core. 
vertx.createNetServer().connectHandler(socket -> { 
    vertx.deployVerticle(new AbstractVerticle() { 
     @Override 
     public void start() throws Exception { 
      socket.handler(buffer -> { 
       log.trace(socket.toString() + ": Socket Message"); 
       socket.close(); 
      }); 
     } 
    }); 
}).listen(port); 

しかし残念ながら、すべてのハンドラが同じスレッドに位置していました。

23:59:42.359 [vert.x-eventloop-thread-1] TRACE Server - [email protected]: Socket Message 
23:59:42.364 [vert.x-eventloop-thread-1] TRACE Server - [email protected]: Socket Message 
23:59:42.365 [vert.x-eventloop-thread-1] TRACE Server - [email protected]: Socket Message 
23:59:42.366 [vert.x-eventloop-thread-1] TRACE Server - [email protected]: Socket Message 
23:59:42.367 [vert.x-eventloop-thread-1] TRACE Server - [email protected]: Socket Message 
23:59:42.368 [vert.x-eventloop-thread-1] TRACE Server - [email protected]: Socket Message 
23:59:42.369 [vert.x-eventloop-thread-1] TRACE Server - [email protected]: Socket Message 
23:59:42.370 [vert.x-eventloop-thread-1] TRACE Server - [email protected]: Socket Message 
... more than 100+ lines ... 

逆の例は、this echo server written in BOOST.ASIOに似ています。スレッドプールを使用してio_service::run()を実行すると、ハンドラは異なるイベントループスレッドで実行されます。

私の質問はこれらのハンドラを同時に実行する方法です。

答えて

0

実際には、あなたは意図したものとはまったく異なる何かをします。

あなたのソケットへの接続を受信するたびに、新しい俳優を起動し、そのことを証明する

最も簡単な方法:

Vertx vertx = Vertx.vertx(); // The number of event loop threads is 2*core. 
vertx.createHttpServer().requestHandler(request -> { 

    vertx.deployVerticle(new AbstractVerticle() { 

     String uuid = UUID.randomUUID().toString(); // Some random unique number 

     @Override 
     public void start() throws Exception { 
      request.response().end(uuid + " " + Thread.currentThread().getName()); 
     } 

    }); 
}).listen(8888); 



vertx.setPeriodic(1000, r -> { 
    System.out.println(vertx.deploymentIDs().size()); // Print verticles count every second 
}); 

私はそれをブラウザで確認することが容易だという理由だけでhttpServerのを使用しています。それによっては
として間違っている、あなたはまだあなたが別のスレッドを受けるべきであることがわかります:

あなたがそれを行う必要がありますどのように今
fe931b18-89cc-4c6a-9d6a-8565bb1f1c12 vert.x-eventloop-thread-9 
277330da-4df8-4e91-bd8f-82c0f62156d0 vert.x-eventloop-thread-11 
bbd3207c-80a4-41d8-9be5-b40727badc84 vert.x-eventloop-thread-13 

// We create 10 workers 
for (int i = 0; i < 10; i++) { 
    vertx.deployVerticle(new AbstractVerticle() { 

     @Override 
     public void start() { 

      vertx.eventBus().consumer("processMessage", (request) -> { 
       // Do something smart 

       // Reply 
       request.reply("I'm on thread " + Thread.currentThread().getName()); 
      }); 
     } 
    }); 
} 

// This is your handler 
vertx.createHttpServer().requestHandler(request -> { 
    // Only one server, that should dispatch events to workers as quickly as possible 
    vertx.eventBus().send("processMessage", null, (response) -> { 
     if (response.succeeded()) { 
      request.response().end("Request :" + response.result().body().toString()); 
     } 
     // Handle errors 
    }); 
}).listen(8888); 

vertx.setPeriodic(1000, r -> { 
    System.out.println(vertx.deploymentIDs().size()); // Notice that number of workers doesn't change 
}); 
+0

まだ分かりませんでした。コードと私の違いは、作業者の頂点を配置する場所です。私はそれらをハンドラにデプロイしながら、それらを外部にデプロイします。これは、いくつかのハンドラに配備された頂点が、ハンドラを配備するスレッドを継承することを意味しますか?そうなら、それは本当に意図されていますか? –

+0

リクエストごとに頂点を作成しています。あなたはそうしてはいけません。頂点はスレッドを継承しません。私の例を実行すると、同じ方法で頂点を作成していますが、毎回別のスレッドが得られることがわかります。あなたが同じスレッドにいると思う理由はおそらくあなたがあなたのネットクライアントをどう扱うかです。しかしそれは別の問題です。 –

+0

なぜそれをしてはいけないのですか?違いは何ですか?私はvert.xドキュメントでそれを見つけることができません、または私はその実装を読む必要があります。 :) –

0

それは、どのイベントを決定することはできませんループVert.xは、詳細(例:テストマシンのコア数)なしに各頂点に割り当てます。

とにかく、着信接続ごとに頂点を配置することはお勧めできません。頂点は、Vert.xの配備の単位です。通常、「機能」ごとに1つずつ作成します。

イベントドリブンプログラミングの目的は、接続ごとにスレッドを使用することを避けることです。 複数の同時接続と1つのイベントループを処理できます。マシンに複数のコアがある場合、それらのすべてを使用するために、複数のインスタンスを展開することができます(コアごとに1つのイベントループ)。 Vertx TCP server sharing接続ハンドラで

int processors = Runtime.getRuntime().availableProcessors(); 
Vertx vertx = Vertx.vertx(); 
vertx.deployVerticle(TCPServerVerticle.class.getName(), new DeploymentOptions().setInstances(processors)); 

public class TCPServerVerticle extends AbstractVerticle { 

    @Override 
    public void start(Future<Void> startFuture) throws Exception { 
    vertx.createNetServer().connectHandler(socket -> { 
     socket.handler(buffer -> { 
     log.trace(socket.toString() + ": Socket Message"); 
     socket.close(); 
     }); 
    }).listen(port, ar -> { 
     if (ar.succeeded()) { 
     startFuture.complete(); 
     } else { 
     startFuture.fail(ar.cause()); 
     } 
    }); 
    } 
} 

ラウンドロビン方式で呼び出されます。

関連する問題