Maison  >  Article  >  développement back-end  >  Conception basée sur les événements avec Log Events et RabbitMQ dans Golang

Conception basée sur les événements avec Log Events et RabbitMQ dans Golang

WBOY
WBOYoriginal
2024-07-23 11:30:321015parcourir

Event-driven design with Log Events and RabbitMQ in Golang

L'adoption d'une architecture événementielle est en hausse à mesure que les équipes recherchent des solutions plus adaptables, évolutives et agiles pour répondre aux exigences des applications contemporaines. Les architectures basées sur les événements prennent en charge les mises à jour en temps réel et rationalisent l'intégration entre différents systèmes en permettant la communication via des événements standardisés et structurés.

Dans un article de blog précédent, j'ai expliqué comment les webhooks dans Auth0 peuvent transmettre des événements, tirant ainsi parti de ces événements pour lancer l'exécution logique. Dans cet article, je vais approfondir les aspects techniques de cette architecture et démontrer comment Go (Golang) peut être utilisé pour construire un tel système.

Principaux composants :

Jetons d'abord un coup d'œil aux principaux composants qui pilotent ce système.

Événements de journal :

Auth0 enregistre les événements associés à chaque activité au niveau du locataire. Ces événements peuvent être utilisés à des fins de surveillance ou d’audit. Les codes de chaque événement peuvent être consultés ici

Webhooks :

Nous utilisons des webhooks auth0 pour transmettre des événements filtrés à notre producteur. Nous filtrons ces événements puisque nous ne nous intéressons qu’à une poignée.

LapinMQ

RabbitMQ prend en charge plusieurs protocoles de messagerie, et celui que nous utilisons pour acheminer les messages est le Advanced Messaging Queuing Protocol (AMQP). AMQP comprend trois entités principales : files d'attente, échanges et liaisons.

Dans les coulisses

Lorsqu'un événement est déclenché dans Auth0, il est immédiatement envoyé via webhook à notre éditeur, qui le publie ensuite en fonction du type d'événement. Une fois publié, l'événement fait l'objet d'un échange. L'échange dirige le message vers les files d'attente connectées, où les consommateurs le reçoivent. Pour permettre ce processus, nous établissons un canal. Ce canal nous permet de publier des messages à échanger et de déclarer des files d'attente pour l'abonnement.

Pour créer une nouvelle file d'attente, nous utilisons la fonction QueueDeclare fournie par le package sur le canal, spécifiant les propriétés de file d'attente souhaitées. Une fois la file d'attente créée, nous pouvons utiliser la fonction Publier de la chaîne pour envoyer un message.

Ensuite, nous créons un consommateur qui se connecte à notre RabbitMQ et établit un canal de communication. En utilisant ce canal, nous pouvons consommer des messages en utilisant la méthode Consume définie pour celui-ci.

Travaux préparatoires

Nous utilisons le package de gestion golang-auth0 pour travailler sur les événements du journal et pour les actions de file d'attente, nous utilisons github.com/rabbitmq/amqp091-go.

Vous trouverez ci-dessous les extraits :

Édition:

Une structure détaillée du journal peut être trouvée ici

    for _, auth0log := range payload.Logs {

        switch auth0log.Data.Type {
        case "slo":
            _, err = c.Publish(ctx, PublishRequest{
                ---your logic---
            })

        case "ss":
            _, err = c.Publish(ctx,PublishRequest{
                    -- your logic -----
                })

        }
    }

Échange:

    if consumeOptions.BindingExchange != "" {
        for _, routingKey := range routingKeys {
            err = consumer.chManager.channel.QueueBind(
                queue,
                routingKey,
                consumeOptions.BindingExchange,
                consumeOptions.BindingNoWait,
                tableToAMQPTable(consumeOptions.BindingArgs),
            )
            if err != nil {
                return err
            }
        }
    }

Consommant:

func (c *Client) Consume() {
    err := c.consumer.StartConsuming(
        func(ctx context.Context, d queue.Delivery) bool {
            err := c.processMessages(ctx, d.Body, d.Exchange)
            if err != nil {
                c.log.Error().Ctx(ctx).Err(err).Str("exchange", d.Exchange).Msg("failed publishing")
                return nack // send to dlx
            }
            return ack // message acknowledged
        },
        c.queueName,
        []string{c.queueRoutingKey},
        func(opts *queue.ConsumeOptions) {
            opts.BindingExchange = c.queueBidingExchange
            opts.QueueDurable = true
            opts.QueueArgs = map[string]interface{}{
                "x-dead-letter-exchange": c.queueBidingExchangeDlx,
            }
        },
    )
    if err != nil {
        c.log.Fatal().Err(err).Msg("consumer: Failed to StartConsuming")
    }

    // block main thread so consumers run forever
    forever := make(chan struct{})
    <-forever
}   

Ainsi, en tirant parti des webhooks dans Auth0 pour déclencher des événements et en utilisant RabbitMQ pour une mise en file d'attente et une livraison fiables des messages, nous pouvons créer des applications évolutives et réactives. Cette approche améliore non seulement la flexibilité, mais prend également en charge un traitement transparent des événements, permettant une gestion efficace des opérations asynchrones.

J'espère que cet article vous a été utile et qu'il pourra s'avérer bénéfique dans votre parcours événementiel.

Bon codage :)

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Article précédent:Cartes dans GoArticle suivant:Cartes dans Go