Entrée de Vertx au combat réel - pour atteindre la pénétration de l'intranet du robot de clouage

Les recherches récentes sur Vetrx sont tout simplement admirables. J'ai hâte de le présenter à tout le monde.

carbone

Qu'est-ce que Vertx

  • Vertx est un ensemble d'outils qui s'exécute sur la machine virtuelle Java et est utilisé pour créer des applications réactives.
  • Bibliothèque réseau asynchrone hautes performances basée sur netty.
  • Netty est encapsulée pour fournir une API plus conviviale.
  • Dans le même temps, certaines bibliothèques basées sur des appels asynchrones sont implémentées, y compris la connexion à la base de données, la surveillance, l'authentification, la journalisation, la découverte de services, la prise en charge des clusters, etc.

Pourquoi je recommande d'étudier

En fait, avec le développement de la technologie. Les appels asynchrones deviennent de plus en plus populaires.

1. Maintenant avec la popularité de RPC. Des cadres comme Dubbo sont basés sur le concept de NIO, et la compréhension de la programmation asynchrone est utile pour apprendre à comprendre le cadre.

2. La programmation réactive pénètre progressivement du client à l'avant vers l'arrière.

3. Il est plus facile d'écrire des services asynchrones hautes performances.

Plusieurs concepts importants de Vertx

Boucle d'événement

La boucle d'événement, comme son nom l'indique, est la boucle d'événement. Pendant le cycle de vie de Vertx, les événements d'interrogation sont interrogés en continu.

Dans le modèle de programmation multithread traditionnel, chaque requête crée un nouveau thread pour traiter la requête. Un tel modèle de programmation est relativement simple à implémenter. Une connexion correspond à un thread. S'il y a un grand nombre de requêtes à traiter, un grand nombre de threads doivent être fork pour être traités. Pour le système d'exploitation, la planification d'un grand nombre de threads entraîne une augmentation de la charge système.

Ainsi, pour pouvoir traiter un grand nombre de demandes, il est nécessaire de passer à la boucle d'événement basée sur le modèle Roactor.

https://img.xilidou.com/img//event-loop.png

Cette photo sur le site officiel est très vivante. Eventloop s'entraîne en continu pour obtenir des événements et organise différents gestionnaires pour traiter les événements correspondants.

Il est à noter ici que pour assurer le fonctionnement normal du programme, l'événement doit être non bloquant. Sinon, eventloop sera bloqué, ce qui affectera les performances de Vertx. Mais en réalité, les programmes ne peuvent pas garantir qu'ils ne sont pas bloquants, et Vertx fournit également un mécanisme pour gérer les méthodes de blocage. Nous continuerons à l'introduire ci-dessous.

Verticule

Dans Vertx, nous pouvons souvent voir le composant vertical.

verticle

Verticle est un bloc de code déployé et exécuté par Vert.x. Par défaut, une instance Vert.x conserve N (par défaut, N = cœurs de processeur x 2) threads de boucle d'événements. Les instances Verticle peuvent être écrites dans n'importe quel langage de programmation pris en charge par Vert.x, et une application simple peut également contenir des Verticles écrits en plusieurs langues.

Vous pouvez considérer Verticle comme un  acteur  dans le modèle d' acteur.

Une application est généralement composée de nombreuses instances Verticle s'exécutant simultanément dans la même instance Vert.x. Différentes instances de Verticle communiquent entre elles en envoyant et en recevant des messages sur le bus d'événements.

Bus d'événement

Le bus d'événements de Vertx est plus facile à comprendre que le MQ couramment utilisé à l'arrière. En fait, Event Bus est un pont pour le transfert d'informations entre Verticles.

En d'autres termes, c'est le mode d'écoute dans le modèle de conception commun Java ou le mode de développement de message MQ que nous disons souvent.

Bus d'événement

Retour à Vertx

Nous avons discuté du modèle et du mécanisme de vertx ci-dessus, maintenant les gens verront comment utiliser vertx pour développer un programme.

Je vais l'expliquer avec plus de trois clous que j'ai écrits auparavant. Tout commence par Vertx.

    val vertx = Vertx.vertx()
复制代码

vertx est le cœur de l'ensemble du framework vert.x. De manière générale, tout le comportement de Vertx est généré à partir de la classe vertx.

Ne nous appelez pas, nous vous appellerons

Vert.x est un framework piloté par les événements. Le soi-disant événementiel signifie effectuer cette action lorsque quelque chose se produit.

Revenons au titre, "Ne nous appelez pas, nous vous appellerons" Ce principe est en fait lorsque nous constatons que vous pouvez terminer ce travail, nous vous trouverons. Vous n'avez pas besoin de prendre l'initiative de me contacter.

Nous utilisons du code pour comprendre comment Vertx met en œuvre ce principe:

    server.requestHandler(request -> {
      request.response().end("hello world!");
    });
复制代码

La signification de ce bloc de code est que chaque fois que la requête du serveur est appelée, une est retournée hello world.

Donc, «vous» j dans Vertx est une variété de gestionnaires. La plupart du temps, lorsque nous écrivons des programmes Vertx, nous écrivons en fait le comportement du gestionnaire. Dites ensuite à Vertx que chaque fois qu'un événement XXX est déclenché, vous appelez XXX Handler.

Ne me bloque pas

Vertx est basé sur des événements. Nous avons mentionné Event Loop ci-dessus. Dans Vertx, EventLoop est une abeille travailleuse, constamment à la recherche des événements qui sont déclenchés. Exécutez ensuite le gestionnaire correspondant. Si le thread exécutant Hanlder est le thread de boucle d'événements. Si le temps d'exécution de Handler est trop long. La boucle d'événement sera bloquée. Lorsque d'autres événements sont déclenchés. La boucle d'événement prend également beaucoup de temps pour traiter le gestionnaire. La boucle d'événements ne répond pas aux autres événements en temps opportun.

Mais en réalité, il est impossible que tous les événements ne soient pas bloquants. Par exemple, interrogez la base de données, appelez l'interface distante, etc., que devons-nous faire?

Dans le modèle événementiel, il existe probablement deux types de routines pour résoudre ce problème. Par exemple, dans Redis, Redis fera très attention de maintenir un fragment de temps. Lorsqu'une personne exécute un événement trop longtemps, l'état de l'événement en cours est enregistré, puis l'événement en cours est suspendu et planifié à nouveau par la boucle d'événement. Empêche la boucle d'événements d'être bloquée par des événements.

Il existe également une routine pour transférer les événements bloqués à d'autres threads pour exécution. La boucle d'événement peut continuer la boucle d'événement pour éviter d'être bloquée. Vertx le fait en fait.

    vertx.executeBlocking(promise -> {
      // Call some blocking API that takes a significant amount of time to return
      String result = someAPI.blockingMethod("hello");
      promise.complete(result);
    }, res -> {
      System.out.println("The result is: " + res.result());
    });
复制代码

Si nous réalisons que ce gestionnaire est un blocage lors de notre développement, nous devons dire à vertx qu'il s'agit d'un blocage et qu'il doit être transféré à d'autres threads pour être traité.

Traitement asynchrone coordonné

Comme mentionné ci-dessus. Vertx gère les événements via des gestionnaires. Cependant, dans de nombreux cas, une opération nécessite généralement plusieurs gestionnaires pour traiter les données. Si vous utilisez toujours la méthode de rappel, des codes de flèche seront formés. Il y a un problème avec le rappel de l'enfer.

En tant que framework asynchrone, Vertx utilise généralement Future pour résoudre le problème de l'enfer de rappel. Comprendre l'avenir dans Vertx est au cœur de l'écriture d'un bon code.

Habituellement, nous comprenons que Future n'est qu'un espace réservé, représentant le résultat d'une opération à un moment donné dans le futur. Si vous n'êtes pas clair, vous pouvez lire mon article précédent.

Il convient de souligner que Vertx l'avenir et Jdk à l' intérieur du CompletableFutureprincipe et de la philosophie est similaire, mais leur utilisation est très différent.

Jdk l' intérieur CompletableFuturepeut être utilisé directement result()bloqué en attendant les résultats, mais Vertx l'avenir si elle est directement utilisé result(), les résultats seront immédiatement retiré de l'avenir, plutôt que de bloquer l' attente des résultats, il est facile de récolter un nul.

Après avoir clarifié cette différence, vous ne ferez aucune erreur lors de l'écriture du code.

Bus d'événement

Si vous avez utilisé le système de messagerie dans le développement quotidien, il est facile de comprendre le bus d'événements dans Vertx. La documentation officielle compare le bus d'événements au système nerveux de Vertx. En fait, nous pensons que le bus d'événements est le système de messagerie de Vertx, très bien.

Développement de Dingding Intranet Penetrating Agent

Ce petit moineau de démonstration est petit mais contient plusieurs composants clés de Vertx. Quand j'écrivais cette démo, j'apprenais le Kotlin, donc je l'ai écrit en kotlin. Si vous avez écrit Java ou Typescript, vous pouvez facilement le comprendre.

Le projet contient

  • Le service HTTP est utilisé pour recevoir un rappel de clou
  • Le service WebSocket est utilisé pour pousser le rappel reçu vers le client pour atteindre l'objectif de pénétration intranet.
  • Vertx Config est utilisé pour configurer les paramètres liés au projet pour une utilisation facile
  • L'utilisation d'Event Bus est utilisée pour transférer des messages entre le service Http et WebSocket.

Tout d'abord un Verticle

Le fichier de configuration Gradle est d'abord introduit comme suit:

    implementation ("io.vertx:vertx-core:3.8.5")
    implementation ("io.vertx:vertx-web:3.8.5")
    implementation ("io.vertx:vertx-lang-kotlin:3.8.5")
复制代码

Ci-dessus, nous avons présenté ce qu'est Verticle. Afin de faciliter le développement, Vertx nous fournit une classe abstraite AbstractVerticle. Héritage direct:

    class DingVerticle : AbstractVerticle() {
    }
复制代码

AbstractVerticle Il contient quelques méthodes courantes de Vericle.

Nous pouvons réécrire la start()méthode pour initialiser notre comportement Verticle.

Création de HttpService

    override fun start() {
        val httpServer = vertx.createHttpServer()
        val router = Router.router(vertx)
        router.post("/ding/api").handler{event ->
            val request = event.request()
            request.bodyHandler { t ->
                println(t)
            }
            event.response().end();
        }
        httpServer.requestHandler(router);
        httpServer.listen(8080);
    }
复制代码

Le code est relativement simple:

  1. Créer un httpService
  2. Configurez un routeur si vous avez écrit du code associé à Spring Mvc. Le routeur ici est similaire à RequestMapping dans le contrôleur. Utilisé pour spécifier un gestionnaire correspondant à l'URI et à la méthode de demande Http. Le gestionnaire ici est une expression lambda. Il imprime simplement le corps de la demande.
  3. Ajoutez le routeur à httpService et écoutez le port 8080.

WebSocketService

Le protocole webSocket est la clé de ce proxy, car WebSocket est différent de Http et communique dans les deux sens. En s'appuyant sur cette fonctionnalité, nous pouvons "pousser" le message vers l'intranet. Atteindre l'objectif de "pénétrer" l'intranet.

    httpServer.webSocketHandler { webSocket: ServerWebSocket ->
        val binaryHandlerID = webSocket.binaryHandlerID()
        webSocket.endHandler() {
            log.info("end", binaryHandlerID)
        }
        webSocket.writeTextMessage("欢迎使用 xilidou 钉钉 代理")
        webSocket.writeTextMessage("连接成功")
    }
复制代码

Le code est relativement simple, qui consiste à enregistrer un gestionnaire pour gérer WebSocket avec Vertx.

Utilisation du bus d'événements

Comme la fonction principale de l'agent est de transmettre le message de rappel enrichi. Comme je l'ai dit précédemment, Event Bus joue un "rôle nerveux" dans Vertx. En fait, en d'autres termes, lorsque le service HTTP reçoit le rappel, il peut passer Le bus d'événements envoie un message. Lorsque WebSocket reçoit le message du bus d'événements, il le transmet au client. Voir l'image ci-dessous:

Pour faciliter la compréhension, nous utilisons les concepteurs et consommateurs habituels de MQ.

Nous utilisons donc pour enregistrer un producteur dans HttpService et transmettre le message après avoir reçu le rappel de Dingding.

Pour faciliter l'écriture, nous pouvons écrire un HttpHandler séparément

    //1
    class HttpHandler(private val eventBus: EventBus) : Handler<RoutingContext> {

        private val log = LoggerFactory.getLogger(this.javaClass);

        override fun handle(event: RoutingContext) {
            val request = event.request()
            request.bodyHandler { t->
                    val jsonObject = JsonObject(t)
                    val toString = jsonObject.toString()
                    log.info("request is {}",toString);
                    // 2
                    eventBus.publish("callback", toString)
            }
            event.response().end("ok")
        }
    }
复制代码

Il y a quelques problèmes à noter ici:

  1. Nous devons utiliser Event Bus pour envoyer des messages, nous devons donc passer dans un Event Bus dans le constructeur
  2. Après réception du message, vous pouvez d' abord convertir les données en chaîne JSON, puis envoyer un message, faites attention ici utilisent les publish()moyens de diffusion, de sorte que tous les clients peuvent souscrire à recevoir de nouveaux messages.

Avec le producteur et les données envoyées, nous pouvons consommer ce message dans WebSocket et le pousser vers le client

Écrivons un gestionnaire WebSocket

    //1
    class WebSocketHandler(private val eventBus: EventBus) : Handler<ServerWebSocket> {

        private val log = LoggerFactory.getLogger(this.javaClass)

        override fun handle(webSocket: ServerWebSocket) {
            val binaryHandlerID = webSocket.binaryHandlerID()

            //2
            val consumer = eventBus.consumer<String>("callback") { message ->
                val body = message.body()
                log.info("send message {}", body)
                //3
                webSocket.writeTextMessage(body)
            }
            webSocket.endHandler() {
                log.info("end", binaryHandlerID)
                //4
                consumer.unregister();
            }
            webSocket.writeTextMessage("欢迎使用 xilidou 钉钉 代理")
            webSocket.writeTextMessage("连接成功")
        }
    }
复制代码

Il y a quelques problèmes à noter ici:

  1. EventBus doit être injecté lors de l'initialisation
  2. Écrire un consumer()message de HttpHandler des consommateurs envoyés
  3. Écrire un message sur webSocket et l'envoyer au client
  4. Le consommateur doit être recyclé après la déconnexion de WebSocket

Initialiser Vertx

Avec autant de préparation, nous pouvons enfin initialiser notre Vertx

    class DingVerticleV2: AbstractVerticle(){
        override fun start() {

            //2
            val eventBus = vertx.eventBus()
            val httpServer = vertx.createHttpServer()

            val router = Router.router(vertx);
            //3
            router.post("/api/ding").handler(HttpHandler(eventBus));
            httpServer.requestHandler(router);

            //4
            httpServer.webSocketHandler(WebSocketHandler(eventBus));
            httpServer.listen(8080);
        }
    }

    //1
    fun main() {
        val vertx = Vertx.vertx()
        vertx.deployVerticle(DingVerticleV2())
    }
复制代码

Il y a quelques problèmes à noter ici:

  1. Initialisez Vertx et déployez-le
  2. Initialiser eventBus
  3. Enregistrer HttpHandler
  4. Enregistrer WebSocketHandler

Résumé

  • Vertx est un outil, pas un framework, il peut donc être facilement combiné avec d'autres frameworks.
  • Vertx est un framework asynchrone basé sur Netty. Nous pouvons écrire du code asynchrone tout comme nous écrivons du code synchrone.
  • vertx a deux fonctions principales dans le code, l'une consiste à initialiser le composant, comme:
    val eventBus = vertx.eventBus()
    val httpServer = vertx.createHttpServer()
复制代码

Une autre consiste à s'inscrire Handler:

     httpServer.webSocketHandler(WebSocketHandler(eventBus));
复制代码
  • Event Bus est un système de messagerie. Utilisé pour transférer des données directement vers différents gestionnaires, simplifiant le développement.

Connexions associées

  1. Tutoriel ongles rappel robot au sein du réseau via un proxy - articles d'utilisation
  2. Github 地址: Github
  3. 官 网 教程 :Un guide doux pour la programmation asynchrone avec Eclipse Vert.x pour les développeurs Java ;
  4. Manuel Vert.x Core

Je suppose que tu aimes

Origine juejin.im/post/5e932d76f265da47b554f34c
conseillé
Classement