Hace poco tiempo que trabajo con colas de RabbitMQ, como cualquier otra mecanismo asíncrono tiene sus pros y contras.

Como cualquier otra tecnología, tendemos a acuñarla y aplicarla en absolutamente todos los niveles de negocio, obviando muchas veces alternativas más adecuadas y eficiente. Muchas veces cayendo en anti patrones, como puede ser el MQ over Batch (obviamente cuanto tiene sentido).

Por otro lado, también tenemos alternativas como pueden ser pub/sub. La aplicación de pub/sub o MQ depende de cómo escalará la aplicación y que tenemos que «ceder», para usar uno u otro. Espero hablar de esto en un post con más detalle.

Repositorio

Si os sirve de ayuda el código en el repositorio una estrellita no estaría de más

Enlace: Github repo (Golang)

Publicar mensajes RabbitMQ con GO

En este post sólo pondremos la parte de publicación de un mesare con go y seguramente en una parte 2, pondremos como consumir estos msg.

La estructura del proyecto, como sólo tiene este pequeño ejemplo es bastante simple:

Hablando de dependencia

Para esta pequeña aplicación, tan sólo necesitamos la dependencia de: github.com/streadway/amqp, que nos ofrece la gestión de conexiones, colas, publicación y consumo entre otras cosas.

module apascualco.com/rabbitmq-publisher-example

go 1.15

require github.com/streadway/amqp v1.0.0

Nuestro fichero main

El ejemplo es bastante sencillo y he evitado poner excesivo ruido para que sea practico al entender o utilizar en vuestro proyecto.

package main

import (
	"log"
	"time"

	"github.com/streadway/amqp"
)

const QUEUE = "example_task_queue"

func connectRabbitMQ() *amqp.Connection {
	conn, err := amqp.Dial("amqp://guest:guest@localhost:5672/apascualco")
	if err != nil {
		log.Fatalf("Failed to connect to RabbitMQ: %s", err)
	}
	return conn
}

func openChannel(conn *amqp.Connection) *amqp.Channel {
	c, err := conn.Channel()
	if err != nil {
		log.Fatalf("Failed to open a channel: %s", err)
	}
	return c
}

func declareQueue(channel *amqp.Channel) amqp.Queue {
	q, err := channel.QueueDeclare(QUEUE, true, false, false, false, nil)
	if err != nil {
		log.Fatalf("Failed to declare a queue: %s", err)
	}
	return q
}

func publish(text string, channel *amqp.Channel, queue amqp.Queue) {
	err := channel.Publish(
		"",
		queue.Name,
		false,
		false,
		amqp.Publishing{
			DeliveryMode: amqp.Persistent,
			ContentType:  "text/plain",
			Body:         []byte(text),
		})
	if err != nil {
		log.Fatalf("Failed to publish a message: %s", err)
	}
}

func generateMessages(count int) {
	n := 0
	for n < count {
		n++ 
		publish("apascualco : "+time.Now().String(),.channel,.queue)¬
	}
}

func main() {
	conn := connectRabbitMQ()
	defer conn.Close()

	channel := openChannel(conn)
	defer channel.Close()

	queue := declareQueue(channel)

	publish("apascualco: "+time.Now().String(), channel, queue)

}

Si veis, la función main, podéis ver los pasos que se siguen para hacer la publicación:

  • Obtener la conexión de rabbit
  • Abrir un canal con la conexión obtenida
  • Declarar una cola
  • Publicar msg

How to use it

Para comprobar el funcionamiento, primero tenemos que tener un RabbitMQ, corriendo y acceso a el (para validar de forma más cómoda que se publica el msg).

Para ello, he añadido en el repo un Docker compone que levantara un rabbit y su herramienta de administración. Para lanzarlo tan solo tenéis que lanzar el comando

docker-composer up -d

Esto, nos levantará on Docker con el rabbit, preparado para ser utilizado. Podéis comprobarlo de la siguiente manera:

Si no os funciona el ejemplo por lo menos tenéis un RabbitMQ en local :).

Una vez que tenemos la infra necesaria, construimos el ejecutable lanzando y luego lo ejecutas:

go build cmd/publish_example.go

./publish_example

Esto provocará que si entramos en nuestro RabbitMQ, seguramente en la dirección: http://localhost:15672 (guest/guest)

Ya hemos publicado nuestro primer msg!

Deja una respuesta