Pulsar详解1—简介 & 基本概念(示例:Go语言)

Pulsar 详解 - 索引目录

一、Pulsar简介

Pulsar是一个由Apache软件基金会开发和维护的分布式消息系统,它具有高吞吐量、低延迟和可水平扩展性的特点。

1、历史背景

1.1 起源

Pulsar的起源可以追溯到Yahoo时期,最初是由Yahoo开发的一个内部项目。在处理大规模的实时数据流时,Yahoo团队需要一个可靠、可扩展且高性能的消息传递系统。为了满足这些需求,他们创建了Pulsar。

1.2 发展历程

随着时间的推移,Pulsar逐渐成熟并引起了广泛关注。Yahoo将Pulsar捐赠给Apache软件基金会,成为一个开源项目。这使得更多的开发者和组织能够参与其发展,并且Pulsar得以在更广泛的应用场景中发挥作用。

2、系统比较

2.1 Pulsar与Kafka的比较

  1. 架构设计:

    • Pulsar: Pulsar采用分层架构,分离了存储和计算,允许无缝地扩展。这种设计使Pulsar更容易管理和扩展。
    • Kafka: Kafka的架构较为简单,采用分布式发布-订阅模型。存储和计算更为紧密集成。
  2. 多租户支持:

    • Pulsar: Pulsar天生支持多租户,可以在同一集群上隔离多个租户的数据。
    • Kafka: Kafka在这方面相对较弱,多租户支持需要一些自定义的工作。
  3. 消息保留策略:

    • Pulsar: Pulsar支持更灵活的消息保留策略,可以根据主题设置不同的保留时间和存储策略。
    • Kafka: Kafka对消息保留的策略相对较为简单,通常是基于时间或大小的保留。
  4. 动态扩展:

    • Pulsar: Pulsar允许动态地添加和删除主题,而无需中断生产者和消费者。
    • Kafka: Kafka的扩展需要更多的手动干预,可能会导致一些中断。
  5. 协议支持:

    • Pulsar: Pulsar支持多种协议,包括Kafka协议,这使得迁移现有Kafka应用程序到Pulsar更为容易。
    • Kafka: Kafka使用自己的协议,与其他系统集成可能需要一些额外的工作。

2.2 Pulsar与RabbitMQ的比较

  1. 消息模型:

    • Pulsar: Pulsar是一种分布式消息系统,适用于高吞吐量和低延迟的场景。
    • RabbitMQ: RabbitMQ更倾向于传统的消息队列模型,适用于较轻量级的消息传递。
  2. 分布式支持:

    • Pulsar: Pulsar天生支持分布式架构,可水平扩展。
    • RabbitMQ: RabbitMQ在分布式方面相对较弱,需要通过集群来实现高可用性和负载均衡。
  3. 协议支持:

    • Pulsar: Pulsar支持多种协议,包括Kafka协议,更容易与其他系统整合。
    • RabbitMQ: RabbitMQ使用AMQP协议,与其他系统集成可能需要额外的工作。
  4. 可靠性:

    • Pulsar: Pulsar确保消息的可靠传递,即使在节点故障的情况下也能保证消息不会丢失。
    • RabbitMQ: RabbitMQ提供一定程度的可靠性,但在某些情况下可能需要额外的配置。

3、特点优势

3.1 Pulsar的设计理念

  1. 分层架构: Pulsar采用分层架构,将存储和计算分离开来。这种设计使得Pulsar能够轻松地扩展和管理,同时提供高吞吐量和低延迟。

  2. 多租户支持: Pulsar天生支持多租户,允许在同一集群上隔离多个租户的数据。这种设计使得Pulsar非常适合在大规模的多组织或多项目环境中使用。

  3. 持久性和可靠性: Pulsar确保消息的可靠传递,即使在节点故障的情况下也能保证消息不会丢失。这是通过使用持久性存储和复制机制来实现的。

  4. 灵活的数据保留策略: Pulsar支持多种消息保留策略,可以根据主题设置不同的保留时间和存储策略。这种灵活性使得Pulsar适用于不同类型的应用场景。

  5. 动态消息路由: Pulsar允许动态地添加和删除主题,而无需中断生产者和消费者。这使得系统更具弹性,能够适应不断变化的需求。

3.2 Pulsar的主要优势

  1. 高可扩展性: Pulsar的分层架构和多租户支持使其能够轻松地扩展,适应不断增长的数据规模和工作负载。

  2. 多协议支持: Pulsar支持多种协议,包括自有的Pulsar协议和Kafka协议。这种灵活性使得Pulsar更容易与现有系统集成,同时提供了迁移现有Kafka应用程序的便利性。

  3. 低延迟和高吞吐量: Pulsar的设计使其能够实现低延迟和高吞吐量,使其非常适用于实时数据处理和分析场景。

  4. 容错和可靠性: Pulsar的架构和复制机制保证了系统的容错性和可靠性,即使在节点故障的情况下也能保持消息的可靠传递。

  5. 社区支持和开源: 作为Apache软件基金会的项目,Pulsar得到了广泛的社区支持,有着活跃的开发者和用户社群。这也确保了Pulsar的持续发展和改进。

二、Pulsar的基本概念

1、主题(Topics)

在Pulsar中,主题(Topics)是消息传递的基本单元。它是消息的逻辑容器,用于将消息从生产者传递给消费者。

1.1 持久主题与非持久主题

  • 持久主题: 持久主题是指存储在Pulsar中的消息将持久保存,即使没有消费者订阅该主题,消息仍然会被保留。这使得消费者在稍后加入时可以接收到之前发布的消息。

  • 非持久主题: 非持久主题则不会保存消息,如果没有活跃的订阅者,消息将会被丢弃。这种类型的主题适用于实时性要求高、不需要历史消息的场景。

1.2 主题的命名规则

主题的命名规则在Pulsar中非常灵活,但通常遵循一些基本原则:

  • 主题名称由多个部分组成,使用斜杠(/)进行层级划分,形成一个层次结构。
  • 层级结构可以帮助组织和分类主题,使其更易于管理。
  • 示例主题名称:persistent/public/default/my-topic,其中persistent表示这是一个持久主题,public/default是命名空间,my-topic是主题的名称。
  • non-persistent表示非持久主题。

1.3 示例(Go语言)

示例1:创建一个持久主题
package main

import (
	"fmt"
	"github.com/apache/pulsar/pulsar-client-go/pulsar"
)

func main() {
    
    
	client, _ := pulsar.NewClient(pulsar.ClientOptions{
    
    
		URL: "pulsar://localhost:6650",
	})

	defer client.Close()

	topicName := "persistent/public/default/my-persistent-topic"

	// 创建持久主题
	_, err := client.CreateProducer(pulsar.ProducerOptions{
    
    
		Topic: topicName,
	})
	if err != nil {
    
    
		fmt.Println("Error creating producer:", err)
		return
	}

	fmt.Println("Persistent topic created successfully.")
}
示例2:创建一个非持久主题
package main

import (
	"fmt"
	"github.com/apache/pulsar/pulsar-client-go/pulsar"
)

func main() {
    
    
	client, _ := pulsar.NewClient(pulsar.ClientOptions{
    
    
		URL: "pulsar://localhost:6650",
	})

	defer client.Close()

	topicName := "non-persistent/public/default/my-non-persistent-topic"

	// 创建非持久主题
	_, err := client.CreateProducer(pulsar.ProducerOptions{
    
    
		Topic:                      topicName,
		MessageRoutingMode:         pulsar.SinglePartition,
		MessageRouter:              pulsar.RoundRobinDistribution,
		BlockIfQueueFull:           true,
		BatchingMaxPublishDelay:    10,
		BatchingMaxPublishDelayMs:  10,
		BatchingMaxMessages:        1000,
		BatchingMaxBytes:           128 * 1024,
		BatchingType:               pulsar.BatchingTypeRegular,
		BatchingMaxAllowedMsgBytes: 128 * 1024,
		BatchingMaxAllowedMessages: 1000,
	})

	if err != nil {
    
    
		fmt.Println("Error creating producer:", err)
		return
	}

	fmt.Println("Non-persistent topic created successfully.")
}

2、生产者(Producers)

在Pulsar中,生产者(Producers)负责将消息发布到主题。

2.1 生产者的创建和配置

要创建一个Pulsar生产者,首先需要连接到Pulsar集群,并指定要生产消息的主题。

以下是创建生产者的基本步骤:

package main

import (
	"fmt"
	"github.com/apache/pulsar/pulsar-client-go/pulsar"
)

func main() {
    
    
	client, _ := pulsar.NewClient(pulsar.ClientOptions{
    
    
		URL: "pulsar://localhost:6650",
	})

	defer client.Close()

	topicName := "persistent/public/default/my-topic"

	// 创建生产者
	producer, err := client.CreateProducer(pulsar.ProducerOptions{
    
    
		Topic: topicName,
	})
	if err != nil {
    
    
		fmt.Println("Error creating producer:", err)
		return
	}

	defer producer.Close()

	fmt.Println("Producer created successfully.")
}

在上述示例中,我们使用Pulsar Go客户端创建了一个生产者,连接到本地Pulsar集群,并指定了要生产消息的主题。

创建生产者后,务必使用defer语句关闭生产者以释放资源。

2.2 消息发送机制

一旦创建了生产者,我们可以使用生产者发送消息到指定的主题。

以下是消息发送的基本步骤:

package main

import (
	"fmt"
	"github.com/apache/pulsar/pulsar-client-go/pulsar"
)

func main() {
    
    
	client, _ := pulsar.NewClient(pulsar.ClientOptions{
    
    
		URL: "pulsar://localhost:6650",
	})

	defer client.Close()

	topicName := "persistent/public/default/my-topic"

	// 创建生产者
	producer, err := client.CreateProducer(pulsar.ProducerOptions{
    
    
		Topic: topicName,
	})
	if err != nil {
    
    
		fmt.Println("Error creating producer:", err)
		return
	}

	defer producer.Close()

	// 发送消息
	message := pulsar.ProducerMessage{
    
    
		Payload: []byte("Hello, Pulsar!"),
	}

	// 发送消息并获取消息ID
	msgID, err := producer.Send(message)
	if err != nil {
    
    
		fmt.Println("Error sending message:", err)
		return
	}

	fmt.Printf("Message sent successfully. Message ID: %v\n", msgID)
}

在上述示例中,我们创建了一个ProducerMessage结构体,其中包含要发送的消息的有效载荷(Payload)。然后,我们使用producer.Send()方法发送消息,并获取消息的ID。

上述示例演示了如何使用Go语言创建一个Pulsar生产者,以及如何发送消息到指定的主题。运行这个示例将在指定主题上发布一条消息,可以在消费者端订阅该主题以接收消息。

3、消费者(Consumers)

在Pulsar中,消费者(Consumers)用于订阅主题并接收发布到该主题的消息。

3.1 消费者的创建和配置

要创建一个Pulsar消费者,首先需要连接到Pulsar集群,并指定要订阅的主题。

以下是创建消费者的基本步骤:

package main

import (
	"context"
	"fmt"
	"github.com/apache/pulsar/pulsar-client-go/pulsar"
)

func main() {
    
    
	client, _ := pulsar.NewClient(pulsar.ClientOptions{
    
    
		URL: "pulsar://localhost:6650",
	})

	defer client.Close()

	topicName := "persistent/public/default/my-topic"

	// 创建消费者
	consumer, err := client.Subscribe(pulsar.ConsumerOptions{
    
    
		Topic:            topicName,
		SubscriptionName: "my-subscription",
		Type:             pulsar.Shared,
	})
	if err != nil {
    
    
		fmt.Println("Error creating consumer:", err)
		return
	}

	defer consumer.Close()

	fmt.Println("Consumer created successfully.")
}

在上述示例中,我们使用Pulsar Go客户端创建了一个消费者,连接到本地Pulsar集群,并指定了要订阅的主题。

创建消费者后,务必使用defer语句关闭消费者以释放资源。

2.2 消息接收机制

一旦创建了消费者,我们可以使用消费者接收从主题发布的消息。

以下是消息接收的基本步骤:

package main

import (
	"context"
	"fmt"
	"github.com/apache/pulsar/pulsar-client-go/pulsar"
)

func main() {
    
    
	client, _ := pulsar.NewClient(pulsar.ClientOptions{
    
    
		URL: "pulsar://localhost:6650",
	})

	defer client.Close()

	topicName := "persistent/public/default/my-topic"

	// 创建消费者
	consumer, err := client.Subscribe(pulsar.ConsumerOptions{
    
    
		Topic:            topicName,
		SubscriptionName: "my-subscription",
		Type:             pulsar.Shared,
	})
	if err != nil {
    
    
		fmt.Println("Error creating consumer:", err)
		return
	}

	defer consumer.Close()

	// 接收消息
	for {
    
    
		msg, err := consumer.Receive(context.Background())
		if err != nil {
    
    
			fmt.Println("Error receiving message:", err)
			return
		}

		fmt.Printf("Received message: %s\n", string(msg.Payload()))

		// 确认消息已被消费
		consumer.Ack(msg)
	}
}

在上述示例中,我们使用consumer.Receive()方法接收消息。处理完消息后,使用consumer.Ack()方法确认消息已被消费。这是为了确保消息不会再次传递给同一消费者。

上述示例演示了如何使用Go语言创建一个Pulsar消费者,并通过循环接收消息。运行这个示例将使消费者订阅指定主题,然后打印接收到的消息内容。

4、订阅(Subscriptions)

在Pulsar中,订阅(Subscriptions)用于定义如何将消息传递给消费者。

订阅模式包括独占订阅(Exclusive)、共享订阅(Shared)、故障转移订阅(Failover)和键共享订阅(Key_Shared)。

4.1 订阅模式

  • 独占订阅(Exclusive): 在独占订阅模式下,一个主题只能有一个活跃的订阅者消费消息。其他订阅者无法接收相同主题的消息。这种模式适用于需要确保每条消息只被一个消费者处理的场景。

  • 共享订阅(Shared): 共享订阅模式允许多个订阅者同时消费同一主题的消息。每个订阅者都接收主题的部分消息,以实现负载均衡。适用于需要多个消费者共同处理消息的场景。

  • 故障转移订阅(Failover): 故障转移订阅模式是独占订阅的一种变体,但它支持故障转移。如果活跃的订阅者出现故障,Pulsar会将订阅切换到下一个可用的订阅者,确保消息不会丢失。

  • 键共享订阅(Key_Shared): 键共享订阅模式允许多个订阅者按照消息的键(Key)进行分区。每个订阅者负责处理特定键的消息,以确保相同键的消息由同一订阅者处理。

4.2. 订阅的管理

在Pulsar中,订阅的管理涉及创建、删除和管理订阅。

示例演示如何创建一个共享订阅:

package main

import (
	"context"
	"fmt"
	"github.com/apache/pulsar/pulsar-client-go/pulsar"
)

func main() {
    
    
	client, _ := pulsar.NewClient(pulsar.ClientOptions{
    
    
		URL: "pulsar://localhost:6650",
	})

	defer client.Close()

	topicName := "persistent/public/default/my-topic"

	// 创建共享订阅
	consumer, err := client.Subscribe(pulsar.ConsumerOptions{
    
    
		Topic:            topicName,
		SubscriptionName: "my-shared-subscription",
		Type:             pulsar.Shared,
	})
	if err != nil {
    
    
		fmt.Println("Error creating shared subscription:", err)
		return
	}

	defer consumer.Close()

	fmt.Println("Shared subscription created successfully.")
}

在上述示例中,我们使用Pulsar Go客户端创建了一个共享订阅。请根据实际需求选择适当的订阅模式,并确保在创建订阅时指定唯一的订阅名称。

5、命名空间(Namespaces)

在Pulsar中,命名空间(Namespaces)是用于隔离和组织主题(Topics)的逻辑容器。命名空间允许在Pulsar中创建多个独立的主题集合,以便更好地组织和管理消息传递。

5.1 命名空间的作用

  • 隔离和组织: 命名空间提供了一种在Pulsar中隔离和组织主题的方式。通过将主题置于特定命名空间中,可以在不同应用、团队或用例之间实现逻辑隔离。

  • 资源分配: 命名空间允许对消息传递资源进行更好的管理和分配。不同的命名空间可以具有不同的配额和配置,以满足特定需求。

  • 权限控制: Pulsar提供了对命名空间的权限控制,可以通过命名空间级别的权限设置来限制用户对主题的访问和操作。

5.2 命名空间的管理

在Pulsar中,命名空间的管理涉及创建、删除和配置命名空间。

示例演示如何使用Go语言创建一个命名空间:

package main

import (
	"fmt"
	"github.com/apache/pulsar/pulsar-client-go/pulsar"
)

func main() {
    
    
	client, _ := pulsar.NewClient(pulsar.ClientOptions{
    
    
		URL: "pulsar://localhost:6650",
	})

	defer client.Close()

	namespaceName := "public/default"

	// 创建命名空间
	err := client.CreateNamespace(namespaceName)
	if err != nil {
    
    
		fmt.Println("Error creating namespace:", err)
		return
	}

	fmt.Printf("Namespace '%s' created successfully.\n", namespaceName)
}

在上述示例中,我们使用Pulsar Go客户端创建了一个命名空间。请根据实际需求选择唯一的命名空间名称,并确保在创建主题时将其置于相应的命名空间中。

6、租户(Tenants)

在Pulsar中,租户(Tenants)是用于隔离和管理资源的顶级组织单位。租户是一个逻辑概念,用于将Pulsar的资源划分为不同的组,以便实现多租户的隔离和管理。

6.1 租户的概念

  • 隔离和资源管理: 租户允许在Pulsar中创建多个独立的资源集合,包括命名空间、主题和订阅。通过租户,可以实现资源的逻辑隔离,确保不同组织或应用之间的资源不会相互干扰。

  • 权限控制: Pulsar提供了对租户的权限控制,可以通过租户级别的权限设置来限制用户对资源的访问和操作。这有助于确保每个租户只能访问其拥有的资源。

6.2 租户的管理

在Pulsar中,租户的管理涉及创建、删除和配置租户。

示例演示如何使用Go语言创建一个租户:

package main

import (
	"fmt"
	"github.com/apache/pulsar/pulsar-client-go/pulsar"
)

func main() {
    
    
	client, _ := pulsar.NewClient(pulsar.ClientOptions{
    
    
		URL: "pulsar://localhost:6650",
	})

	defer client.Close()

	tenantName := "my-tenant"

	// 创建租户
	err := client.CreateTenant(tenantName)
	if err != nil {
    
    
		fmt.Println("Error creating tenant:", err)
		return
	}

	fmt.Printf("Tenant '%s' created successfully.\n", tenantName)
}

在上述示例中,我们使用Pulsar Go客户端创建了一个租户。根据实际需求选择唯一的租户名称,并确保在创建资源时将其置于相应的租户中。

猜你喜欢

转载自blog.csdn.net/weixin_49015143/article/details/135079277
今日推荐