浅聊消息队列 | 青训营笔记

147 阅读4分钟

这是我参与「第五届青训营 」笔记创作活动的第4天

一、本堂课重点内容:

  • 消息队列的简介、使用和选型

二、详细知识点介绍:

  • 消息中间件

消息中间件(Message-Oriented Middleware,MOM)是一种通信架构,用于在不同的应用程序之间传递消息。它可以帮助解决应用程序之间的通信问题,并且提供了一些强大的特性,例如:异步通信、消息缓存、路由、集群等。

通过使用消息中间件,应用程序可以解除耦合,并通过发送消息来与其他应用程序通信,而不需要直接了解对方的实现细节。这对于分布式系统和微服务架构尤其有用,因为它们需要灵活的通信方式来处理大量的请求和数据

消息中间件通常使用一个中间件服务器来实现,该服务器提供了一个消息队列,可以用来存储和转发消息。应用程序可以通过与该服务器的连接来发送和接收消息

一句话来讲:消息中间件是一种用来在不同应用程序间传递消息的桥梁(通信架构)

  • 发布订阅模式

发布订阅模式是一种软件设计模式,允许对象或组件订阅主题或事件,并在其发生时被通知。它建立在一种中介者模式上,即发布者和订阅者之间存在一个中间件,可以将消息从发布者传递到订阅者。

这种模式的优点在于,它可以减少代码的耦合性,并在不同对象之间创建更灵活的通信关系

  • 事件驱动架构

事件驱动架构(Event-Driven Architecture, EDA)是一种软件设计模式,它将系统中的数据和行为视为事件,并以事件的形式在系统内部进行通信。这种架构通常由多个独立的组件组成,每个组件都是一个事件的生产者或消费者。当事件生产者生成事件时,消费者将对事件进行响应,可以对其进行处理或将其转发给其他组件。

优点:

1.  灵活性:每个组件可以独立于其他组件运行,并且可以更容易地添加或删除组件。
2.  可扩展性:随着系统的发展,可以很容易地添加新的组件。
3.  可靠性:每个组件都是独立的,因此只有一个组件出现故障时,其他组件不会受到影响。

缺点:

1.  复杂性:事件驱动架构可能会变得非常复杂,特别是当系统中存在许多事件和组件时。
2.  延迟:事件驱动架构可能存在延迟,因为事件可能需要经过多个组件才能得到处理。
  • 消息队列的作用
    • 异步
    • 解耦
    • 削峰

三、实践练习例子:

  1. RabbitMQ: RabbitMQ 是一个开源的消息队列系统,支持多种语言,包括 golang。以下是使用 golang 和 RabbitMQ 进行消息队列实践的示例:
package main

import (
    "fmt"
    "github.com/streadway/amqp"
)

func failOnError(err error, msg string) {
    if err != nil {
        panic(fmt.Sprintf("%s: %s", msg, err))
    }
}

func main() {
    conn, err := amqp.Dial("amqp://guest:guest@localhost:5672/")
    failOnError(err, "Failed to connect to RabbitMQ")
    defer conn.Close()

    ch, err := conn.Channel()
    failOnError(err, "Failed to open a channel")
    defer ch.Close()

    q, err := ch.QueueDeclare(
        "hello",
        false,
        false,
        false,
        false,
        nil,
    )
    failOnError(err, "Failed to declare a queue")

    body := "Hello World!"
    err = ch.Publish(
        "",
        q.Name,
        false,
        false,
        amqp.Publishing{
            ContentType: "text/plain",
            Body:        []byte(body),
        },
    )
    failOnError(err, "Failed to publish a message")
    fmt.Println(" [x] Sent ", body)
}
  1. Kafka 实现消息队列的示例:

  2. 生产者代码:

package main

import (
	"fmt"

	"github.com/Shopify/sarama"
)

func main() {
	config := sarama.NewConfig()
	config.Producer.RequiredAcks = sarama.WaitForAll
	config.Producer.Retry.Max = 5
	config.Producer.Return.Successes = true

	brokers := []string{"localhost:9092"}

	producer, err := sarama.NewSyncProducer(brokers, config)
	if err != nil {
		panic(err)
	}
	defer producer.Close()

	topic := "test"
	key := sarama.StringEncoder("key")
	value := sarama.StringEncoder("value")

	msg := &sarama.ProducerMessage{
		Topic: topic,
		Key:   key,
		Value: value,
	}

	partition, offset, err := producer.SendMessage(msg)
	if err != nil {
		panic(err)
	}

	fmt.Printf("Message is stored in partition %d, offset %d\n", partition, offset)
}
  1. 消费者代码
package main

import (
	"fmt"

	"github.com/Shopify/sarama"
)

func main() {
	broker := "localhost:9092"

	config := sarama.NewConfig()
	config.Version = sarama.V2_1_0_0

	consumer, err := sarama.NewConsumer([]string{broker}, config)
	if err != nil {
		panic(err)
	}
	defer consumer.Close()

	partitions, _ := consumer.Partitions("test")
	for partition := range partitions {
		pc, _ := consumer.ConsumePartition("test", int32(partition), sarama.OffsetNewest)

		defer pc.Close()

		for msg := range pc.Messages() {
			fmt.Printf("Partition:%d, Offset:%d, Key:%s, Value:%s\n", msg.Partition, msg.Offset, string(msg.Key), string(msg.Value))
		}
	}
}

四、课后个人总结:

  • 本章有什么知识点不容易掌握?
    1. Sarama 库的使用:Apache Kafka 是使用 Go 语言开发的,因此可以使用 Sarama 库与 Kafka 进行交互。需要了解 Sarama 库的基本使用方法,包括如何安装和配置。
    2. Kafka 生产者:需要了解如何使用 Sarama 库创建生产者,向 Kafka 集群发送消息,设置生产者配置信息等。
    3. Kafka 消费者:需要了解如何使用 Sarama 库创建消费者,从 Kafka 集群中消费消息,并处理消息。
  • 什么地方容易与其他内容混淆?
    1. Sarama 库与其他 Go 语言库的区别:在 Go 语言中,还有许多其他可以与 Kafka 进行交互的库,如 Confluent-kafka-go,因此容易与其他库混淆。
    2. 生产者和消费者的工作原理:生产者和消费者是 Kafka 消息队列中的两个重要组件,它们的工作原理有一定的差异,因此容易与其他内容混淆。

五、引用参考: