2013-08-20 47 views
1

我是vert.x的新手。我正在嘗試vert.x「NetServer」功能。 http://vertx.io/core_manual_java.html#writing-tcp-servers-and-clients,它的功能就像一個魅力。vertx中的多線程

不過,我也讀了「A verticle實例是嚴格單線程的。

如果您創建一個簡單的TCP服務器和部署,那麼所有該服務器的處理器是始終在同一個執行它的單個實例事件循環(線程)「。

目前,對於我的實現,我想要接收TCP字節流,然後觸發另一個組件。但是這不應該是Verticle的「開始」方法中的阻塞調用。那麼,在啓動方法中編寫執行程序是否是一種好的做法?或者vertx自動處理這種情況。

這裏是一個片段

public class TCPListener extends Verticle { 

    public void start(){ 

     NetServer server = vertx.createNetServer(); 

     server.connectHandler(new Handler<NetSocket>() { 
      public void handle(NetSocket sock) { 
       container.logger().info("A client has connected"); 
       sock.dataHandler(new Handler<Buffer>() { 
        public void handle(Buffer buffer) { 
         container.logger().info("I received " + buffer.length() + " bytes of data"); 

         container.logger().info("I received " + new String(buffer.getBytes())); 
         //Trigger another component here. SHould be done in a sperate thread. 
         //The previous call should be returned . No need to wait for component response. 
        } 
       }); 
      } 
     }).listen(1234, "host"); 
    } 
} 

應該是什麼樣的機制,使之成爲非阻塞調用。

+1

您可能會在[vert.x google group](https://groups.google.com/forum/#!forum/vertx)中發佈此問題的答案更快。但是,只要你不需要第二個模塊的回覆,你應該只能在MessageBus上發送一條消息,並且忽略該消息的響應。 –

回答

5

我不認爲這是去vert.x.方式

更好的方法是正確使用事件總線而不是執行程序。讓工作人員在公交車上回應事件,進行處理,並在總線完成時發出信號。

創建線程失敗了使用vert.x.的目的。

1

最靈活的方法是創建一個ExecutorService並處理它的請求。這對工作者的線程模型(固定或可變數量的線程,應該在單個線程上串行執行哪些工作等)進行細粒度控制。

修改樣本可能是這樣的:

public class TCPListener extends Verticle { 

    private final ExecutorService executor = Executors.newFixedThreadPool(10); 

    public void start(){ 

     NetServer server = vertx.createNetServer(); 

     server.connectHandler(new Handler<NetSocket>() { 
      public void handle(final NetSocket sock) { // <-- Note 'final' here 
       container.logger().info("A client has connected"); 
       sock.dataHandler(new Handler<Buffer>() { 
        public void handle(final Buffer buffer) { // <-- Note 'final' here 

         //Trigger another component here. SHould be done in a sperate thread. 
         //The previous call should be returned . No need to wait for component response. 
         executor.submit(new Runnable() { 

          public void run() { 
           //It's okay to read buffer data here 
           //and use sock.write() if necessary 
           container.logger().info("I received " + buffer.length() + " bytes of data"); 
           container.logger().info("I received " + new String(buffer.getBytes())); 
          } 
         } 
        } 
       }); 
      } 
     }).listen(1234, "host"); 
    } 
} 
+2

它有點違背了使用vertx的目的,如果你使用一個ExecutorService。我認爲消息傳遞(即事件總線)是一個更好的解決方案。 –

+0

@AdamGent:我不同意你在這裏:首先,EventBus僅支持一組有限的消息類型。通常,在I/O線程上預處理消息並將繁重的同步處理委託給單獨的線程而沒有串行化開銷會更有效。其次,EventBus使用FixedThreadPool。明確定義ExecutorService可以讓你更快地使用某些東西(比如環形隊列),如果它成爲瓶頸的話。第三,單個EventBus並不那麼靈活:不可能優先考慮消息,需要對特定消息類型進行串行處理等。 – Wildfire

+0

首先,我認爲當你不知道他的規模或要求是什麼時,你會過於自信。其次,由於ExecutorService綁定到單個JVM,而Vert.x和它的EventBus允許您避免,所以他不能輕鬆添加另一臺機器來完成工作。最後,序列化並不是一個真正的問題,它依賴於你的序列化過程。我懷疑它會比串行化的時間要長,因爲這可能是外部數據的輸入。上次我檢查了EventBus支持原始字節。用你的解決方案,他可能會使用一個普通的servlet容器。 –

0

由於duffymo提到的創建線程失敗了使用vertx的目的。最好的方法是在事件總線中寫入一條消息,並創建一個新的處理程序,以偵聽來自事件總線的消息。更新了代碼以展示這一點。將消息寫入「next.topic」主題,並註冊處理程序以讀取來自「next.topic」主題的消息。

public class TCPListener extends Verticle { 

public void start(){ 

    NetServer server = vertx.createNetServer(); 

    server.connectHandler(new Handler<NetSocket>() { 
     public void handle(NetSocket sock) { 
      container.logger().info("A client has connected"); 
      sock.dataHandler(new Handler<Buffer>() { 
       public void handle(Buffer buffer) { 
        String recvMesg = new String(buffer.getBytes()); 
        container.logger().info("I received " + buffer.length() + " bytes of data"); 

        container.logger().info("I received " + recvMesg); 
        //Writing received message to event bus 
        vertx.eventBus().send("next.topic", recvMesg); 
       } 
      }); 
     } 
    }).listen(1234, "host"); 

    //Registering new handler listening to "next.topic" topic on event bus 
    vertx.eventBus().registerHandler("next.topic", new Handler<Message<String>() { 
     public void handle(Message<String> mesg) { 
      container.logger.info("Received message: "+mesg.body()); 
     } 
    }; 

} 
}