2016-04-29 5 views
3

J'ai application simple vert.x:vert.x multi-thread web socket

public class Main { 
public static void main(String[] args) { 
    Vertx vertx = Vertx.vertx(new VertxOptions().setWorkerPoolSize(40).setInternalBlockingPoolSize(40)); 
    Router router = Router.router(vertx); 
    long main_pid = Thread.currentThread().getId(); 
    Handler<ServerWebSocket> wsHandler = serverWebSocket -> { 
     if(!serverWebSocket.path().equalsIgnoreCase("/ws")){ 
      serverWebSocket.reject(); 
     } else { 
      long socket_pid = Thread.currentThread().getId(); 
      serverWebSocket.handler(buffer -> { 
       String str = buffer.getString(0, buffer.length()); 
       long handler_pid = Thread.currentThread().getId(); 
       log.info("Got ws msg: " + str); 
       String res = String.format("(req:%s)main:%d sock:%d handlr:%d", str, main_pid, socket_pid, handler_pid); 
       try { 
        Thread.sleep(500); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
       serverWebSocket.writeFinalTextFrame(res); 
      }); 
     } 
    }; 
    vertx 
     .createHttpServer() 
     .websocketHandler(wsHandler) 
     .listen(8080); 
} 
} 

Lorsque je connecte ce serveur avec plusieurs clients, je vois que cela fonctionne dans un thread. Mais je veux gérer chaque connexion client parallèlement. Comment je devrais changer ce code pour le faire?

+1

Je voudrais envelopper dans un 'Verticle' et démarrer le' Verticle' avec le 'DeploymentOptions.setInstances()' plusieurs fois. Je peux donner un exemple, si c'est ce que vous voulez. – alexvetter

+0

Merci, c'est ce que j'ai déjà fait exactement)) Juste eu des hésitations. –

+1

S'il vous plaît, considérez la réponse de Will. Vous devriez probablement regarder [Concurrence événementielle] (http://berb.github.io/diploma-thesis/community/055_events.html) et E/S asynchrones. – alexvetter

Répondre

3

Ce:

nouvelles VertxOptions() setWorkerPoolSize (40) .setInternalBlockingPoolSize (40)

semble que vous essayez de créer votre propre pool de connexion HTTP, ce qui est probablement pas. ce que tu veux vraiment.

L'idée de Vert.x et d'autres non-blocage event-loop cadres basés, est que nous ne cherchons pas l'affinité 1 thread -> 1 connection, plutôt, lorsqu'une demande, actuellement desservie par le fil de boucle d'événements est en attente pour IO - EG la réponse à partir d'un DB - ce thread de boucle d'événements est libéré pour desservir une autre connexion. Cela permet ensuite à un thread de boucle d'événement unique de gérer plusieurs connexions de manière concurrente.

Si vous souhaitez utiliser pleinement toutes les ressources de votre machine, et que vous n'allez exécuter qu'un seul verticle, définissez le nombre d'instances sur le nombre de cœurs lorsque vous déployez votre verticle.

IE

Vertx.vertx().deployVerticle("MyVerticle", new DeploymentOptions().setInstances(Runtime.getRuntime().availableProcessors())); 
1

vert.x est un cadre reactive, ce qui signifie qu'il utilise un seul modèle de thread pour gérer toutes vos applications de charge. Ce modèle est known pour mieux évoluer que le modèle fileté.

Le point clé à savoir est que tout le code que vous mettez dans un gestionnaire ne doit jamais bloquer (comme votre Thread.sleep) car il va bloquer le thread principal. Si vous avez un code de blocage (disons par exemple un appel JDBC) vous devez envelopper votre code de blocage dans un gestionnaire executingBlocking, par exemple:

serverWebSocket.handler(buffer -> { 
    String str = buffer.getString(0, buffer.length()); 
    long handler_pid = Thread.currentThread().getId(); 
    log.info("Got ws msg: " + str); 
    String res = String.format("(req:%s)main:%d sock:%d handlr:%d", str, main_pid, socket_pid, handler_pid); 
    vertx.executeBlocking(future -> { 
    try { 
     Thread.sleep(500); 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } 
    serverWebSocket.writeFinalTextFrame(res); 
    future.complete(); 
    }); 
}); 

Maintenant, tout le code de blocage sera exécuté sur un thread du pool de fil que vous peut configurer comme déjà montré dans d'autres réponses. Si vous souhaitez éviter d'écrire tous ces gestionnaires de blocage d'exécution et que vous savez que vous devez effectuer plusieurs appels bloquants, vous devriez envisager d'utiliser un worker verticle, car ceux-ci seront mis à l'échelle au niveau du bus d'événements. Une note finale pour le multi-threading est que si vous utilisez plusieurs threads, votre serveur ne sera pas aussi efficace qu'un seul thread, par exemple il ne sera pas capable de gérer 10 millions de websockets depuis 10 millions d'événements threads sur un moderne machine (nous sommes en 2016) mettra votre ordonnanceur OS à genoux.