Pulsar 2.4 CentOS 7.3 安装及使用

下载安装包

http://pulsar.apache.org/en/download/

Pulsar 2.4 CentOS 7.3 安装及使用_第1张图片

使用tar -zxvf解压下载的资源包,目录结构如下

Pulsar 2.4 CentOS 7.3 安装及使用_第2张图片

显示目录:

本地单点运行,使用命令./pulsar standalone 即可,这里使用默认配置,暴露端口为6650

测试消息

发送消息 命令

./pulsar-client produce my-topic --messages "hello-pulsar"

结果

接收消息

  ./pulsar-client consume my-topic -s "first-subscription"

 

Maven的

如果您使用的是Maven,请将其添加到您的pom.xml


<pulsar.version>2.4.0pulsar.version>


<dependency>
  <groupId>org.apache.pulsargroupId>
  <artifactId>pulsar-clientartifactId>
  <version>${pulsar.version}version>
dependency>

复制

摇篮

如果您使用的是Gradle,请将其添加到您的build.gradle文件中:

def pulsarVersion = '2.4.0'

dependencies {
    compile group: 'org.apache.pulsar', name: 'pulsar-client', version: pulsarVersion
}

复制

连接URL

要使用客户端库连接到Pulsar,您需要指定Pulsar协议 URL。

Pulsar协议URL分配给特定的集群,使用该pulsar方案并具有6650的默认端口。以下是一个示例localhost

pulsar://localhost:6650

复制

如果您有多个代理,则URL可能如下所示:

pulsar://localhost:6550,localhost:6651,localhost:6652

复制

生产Pulsar集群的URL可能如下所示:

pulsar://pulsar.us-west.example.com:6650

复制

如果您正在使用TLS身份验证,则URL将如下所示:

pulsar+ssl://pulsar.us-west.example.com:6651

复制

客户端配置

您可以 仅使用目标Pulsar 集群的URL 来实例化PulsarClient对象,如下所示:

PulsarClient client = PulsarClient.builder()
        .serviceUrl("pulsar://localhost:6650")
        .build();

复制

如果你有多个经纪人,你可以像这样启动一个PulsarClient:

PulsarClient client = PulsarClient.builder()
        .serviceUrl("pulsar://localhost:6650,localhost:6651,localhost:6652")
        .build();

复制

独立群集的默认代理URL

如果您在独立模式下运行群集,pulsar://localhost:6650默认情况下,代理将在URL 处可用。

查看PulsarClient 类的Javadoc以获取可配置参数的完整列表。

除了客户端级别的配置,您还可以应用生产者和消费者特定的配置,如下面的部分所示。

生产者

在Pulsar中,制作人将信息写入主题。一旦您实例化了PulsarClient 对象(如上节所述),您就可 以为特定的Pulsar 主题创建一个Producer。

Producer<byte[]> producer = client.newProducer()
        .topic("my-topic")
        .create();

// You can then send messages to the broker and topic you specified:
producer.send("My message".getBytes());

复制

默认情况下,生成器生成由字节数组组成的消息。但是,您可以通过指定消息架构来生成不同类型。

Producer stringProducer = client.newProducer(Schema.STRING)
        .topic("my-topic")
        .create();
stringProducer.send("My message");

复制

您应该始终确保在不再需要时关闭您的生产者,消费者和客户:

producer.close();
consumer.close();
client.close();

复制

关闭操作也可以是异步的:

producer.closeAsync()
   .thenRun(() -> System.out.println("Producer closed"));
   .exceptionally((ex) -> {
       System.err.println("Failed to close producer: " + ex);
       return ex;
   });

复制

配置生产者

如果您实例化Producer仅指定主题名称的对象(如上例所示),则生产者将使用默认配置。要使用非默认配置,可以设置各种可配置参数。有关完整列表,请参阅ProducerBuilder 类的Javadoc 。这是一个例子:

Producer<byte[]> producer = client.newProducer()
    .topic("my-topic")
    .batchingMaxPublishDelay(10, TimeUnit.MILLISECONDS)
    .sendTimeout(10, TimeUnit.SECONDS)
    .blockIfQueueFull(true)
    .create();

复制

消息路由

使用分区主题时,只要使用生产者发布消息,就可以指定路由模式。有关使用Java客户端指定路由模式的更多信息,请参阅分区主题菜谱。

异步发送

您还可以使用Java客户端异步发布消息。使用异步发送,生产者将消息放入阻塞队列并立即返回。然后,客户端库将在后台将消息发送给代理。如果队列已满(最大大小可配置),则在调用API时,生产者可能会被阻塞或立即失败,具体取决于传递给生产者的参数。

这是一个异步发送操作示例:

producer.sendAsync("my-async-message".getBytes()).thenAccept(msgId -> {
    System.out.printf("Message with ID %s successfully sent", msgId);
});

复制

从上面的示例中可以看出,异步发送操作返回一个 包含在其中的MessageIdCompletableFuture

配置消息

除了值之外,还可以在给定消息上设置其他项:

producer.newMessage()
    .key("my-message-key")
    .value("my-async-message".getBytes())
    .property("my-key", "my-value")
    .property("my-other-key", "my-other-value")
    .send();

复制

对于前一种情况,也可以终止构建器链sendAsync()并返回将来的情况。

消费者

在Pulsar中,消费者订阅主题并处理生产者发布到这些主题的消息。您可以通过首先实例化PulsarClient对象并将其传递给Pulsar代理的URL(如上所述)来实例化新的使用者。

一旦实例化了PulsarClient 对象,就可以 通过指定主题和订阅来创建Consumer。

Consumer consumer = client.newConsumer()
        .topic("my-topic")
        .subscriptionName("my-subscription")
        .subscribe();

复制

subscribe方法将自动将使用者订阅到指定的主题和订阅。让消费者倾听主题的一种方法是设置while循环。在此示例循环中,使用者侦听消息,打印所接收的任何消息的内容,然后确认消息已被处理。如果处理逻辑失败,我们使用否定确认 来在稍后的时间点重新传递消息。

while (true) {
  // Wait for a message
  Message msg = consumer.receive();

  try {
      // Do something with the message
      System.out.printf("Message received: %s", new String(msg.getData()));

      // Acknowledge the message so that it can be deleted by the message broker
      consumer.acknowledge(msg);
  } catch (Exception e) {
      // Message failed to process, redeliver later
      consumer.negativeAcknowledge(msg);
  }
}

复制

配置消费者

如果您实例化Consumer仅指定主题和订阅名称的对象(如上例所示),则使用者将使用默认配置。要使用非默认配置,可以设置各种可配置参数。有关完整列表,请参阅ConsumerBuilder 类的Javadoc 。这是一个例子:

这是一个示例配置:

Consumer consumer = client.newConsumer()
        .topic("my-topic")
        .subscriptionName("my-subscription")
        .ackTimeout(10, TimeUnit.SECONDS)
        .subscriptionType(SubscriptionType.Exclusive)
        .subscribe();

复制

异步接收

receive方法将同步接收消息(消息进程将被阻止,直到消息可用)。您还可以使用异步接收,它将立即返回一个CompletableFuture在新消息可用时完成的对象。

这是一个例子:

CompletableFuture asyncMessage = consumer.receiveAsync();

复制

异步接收操作返回一个 包含在一个内部的消息CompletableFuture

多主题订阅

除了将消费者订阅到单个Pulsar主题之外,您还可以使用多主题订阅同时订阅多个主题。要使用多主题订阅,您可以提供正则表达式(正则表达式)或List主题。如果您通过正则表达式选择主题,则所有主题必须位于相同的Pulsar名称空间内。

这里有些例子:

import org.apache.pulsar.client.api.Consumer;
import org.apache.pulsar.client.api.PulsarClient;

import java.util.Arrays;
import java.util.List;
import java.util.regex.Pattern;

ConsumerBuilder consumerBuilder = pulsarClient.newConsumer()
        .subscriptionName(subscription);

// Subscribe to all topics in a namespace
Pattern allTopicsInNamespace = Pattern.compile("persistent://public/default/.*");
Consumer allTopicsConsumer = consumerBuilder
        .topicsPattern(allTopicsInNamespace)
        .subscribe();

// Subscribe to a subsets of topics in a namespace, based on regex
Pattern someTopicsInNamespace = Pattern.compile("persistent://public/default/foo.*");
Consumer allTopicsConsumer = consumerBuilder
        .topicsPattern(someTopicsInNamespace)
        .subscribe();

复制

您还可以订阅明确的主题列表(如果您愿意,可以跨命名空间):

List topics = Arrays.asList(
        "topic-1",
        "topic-2",
        "topic-3"
);

Consumer multiTopicConsumer = consumerBuilder
        .topics(topics)
        .subscribe();

// Alternatively:
Consumer multiTopicConsumer = consumerBuilder
        .topics(
            "topic-1",
            "topic-2",
            "topic-3"
        )
        .subscribe();

复制

您还可以使用subscribeAsync方法而不是同步subscribe方法异步订阅多个主题。这是一个例子:

Pattern allTopicsInNamespace = Pattern.compile("persistent://public/default.*");
consumerBuilder
        .topics(topics)
        .subscribeAsync()
        .thenAccept(this::receiveMessageFromConsumer);

private void receiveMessageFromConsumer(Consumer consumer) {
    consumer.receiveAsync().thenAccept(message -> {
                // Do something with the received message
                receiveMessageFromConsumer(consumer);
            });
}

复制

订阅模式

Pulsar有各种订阅模式以匹配不同的场景。主题可以具有多个具有不同订阅模式的订阅。但是,订阅一次只能有一种订阅模式。

订阅使用订阅名称标识,订阅名称一次只能指定一种订阅模式。您可以更改订阅模式,但必须首先让此订阅的所有现有使用者脱机。

不同的订阅模式具有不同的消息分发模式 本节介绍订阅模式的差异以及如何使用它们。

为了更好地描述它们之间的差异,假设您有一个名为“my-topic”的主题,并且生产者已发布了10条消息。

Producer producer = client.newProducer(Schema.STRING)
        .topic("my-topic")
        .enableBatch(false)
        .create();
// 3 messages with "key-1", 3 messages with "key-2", 2 messages with "key-3" and 2 messages with "key-4"
producer.newMessage().key("key-1").value("message-1-1").send();
producer.newMessage().key("key-1").value("message-1-2").send();
producer.newMessage().key("key-1").value("message-1-3").send();
producer.newMessage().key("key-2").value("message-2-1").send();
producer.newMessage().key("key-2").value("message-2-2").send();
producer.newMessage().key("key-2").value("message-2-3").send();
producer.newMessage().key("key-3").value("message-3-1").send();
producer.newMessage().key("key-3").value("message-3-2").send();
producer.newMessage().key("key-4").value("message-4-1").send();
producer.newMessage().key("key-4").value("message-4-2").send();

复制

独家

创建新的使用者并使用Exclusive订阅模式订阅。

Consumer consumer = client.newConsumer()
        .topic("my-topic")
        .subscriptionName("my-subscription")
        .subscriptionType(SubscriptionType.Exclusive)
        .subscribe()

复制

只有第一个消费者被允许订阅,其他消费者会收到错误。第一个消费者接收所有10个消息,消费订单与生产订单相同。

注意:

如果topic是分区主题,则第一个使用者订阅所有分区主题,其他使用者未分配分区并收到错误。

故障转移

创建新的消费者并使用Failover订阅模式订阅。

Consumer consumer1 = client.newConsumer()
        .topic("my-topic")
        .subscriptionName("my-subscription")
        .subscriptionType(SubscriptionType.Failover)
        .subscribe()
Consumer consumer2 = client.newConsumer()
        .topic("my-topic")
        .subscriptionName("my-subscription")
        .subscriptionType(SubscriptionType.Failover)
        .subscribe()
//conumser1 is the active consumer, consumer2 is the standby consumer.
//consumer1 receives 5 messages and then crashes, consumer2 takes over as an  active consumer.

  

复制

多个消费者可以附加到同一订阅,但只有第一个消费者处于活动状态,而其他消费者处于待机状态。当活动消费者断开连接时,消息将被分派给备用消费者之一,备用消费者成为活动消费者。

如果第一个活动消费者收到5条消息并且已断开连接,则备用消费者将成为活动消费者 消费者1将获得:

("key-1", "message-1-1")
("key-1", "message-1-2")
("key-1", "message-1-3")
("key-2", "message-2-1")
("key-2", "message-2-2")

复制

consumer2将收到:

("key-2", "message-2-3")
("key-3", "message-3-1")
("key-3", "message-3-2")
("key-4", "message-4-1")
("key-4", "message-4-2")

复制

注意:

如果主题是分区主题,则每个分区仅具有一个活动消费者,一个分区的消息仅分发给一个消费者,多个分区的消息分发给多个消费者。

共享

创建新的消费者并订阅Shared订阅模式:

Consumer consumer1 = client.newConsumer()
        .topic("my-topic")
        .subscriptionName("my-subscription")
        .subscriptionType(SubscriptionType.Shared)
        .subscribe()
  
Consumer consumer2 = client.newConsumer()
        .topic("my-topic")
        .subscriptionName("my-subscription")
        .subscriptionType(SubscriptionType.Shared)
        .subscribe()
//Both consumer1 and consumer 2 is active consumers.

复制

在共享订阅模式中,多个消费者可以附加到相同的订阅,并且消息在消费者的循环分发中递送。

如果代理一次只调度一条消息,则consumer1将收到:

("key-1", "message-1-1")
("key-1", "message-1-3")
("key-2", "message-2-2")
("key-3", "message-3-1")
("key-4", "message-4-1")

复制

消费者2将收到:

("key-1", "message-1-2")
("key-2", "message-2-1")
("key-2", "message-2-3")
("key-3", "message-3-2")
("key-4", "message-4-2")

复制

Shared订阅ExclusiveFailover订阅模式不同。Shared订阅具有更好的灵活性,但不能提供订单保证。

Key_shared

这是自2.4.0发布以来的新订阅模式,创建新的消费者并订阅Key_Shared订阅模式:

Consumer consumer1 = client.newConsumer()
        .topic("my-topic")
        .subscriptionName("my-subscription")
        .subscriptionType(SubscriptionType.Key_Shared)
        .subscribe()
  
Consumer consumer2 = client.newConsumer()
        .topic("my-topic")
        .subscriptionName("my-subscription")
        .subscriptionType(SubscriptionType.Key_Shared)
        .subscribe()
//Both consumer1 and consumer2 are active consumers.

复制

Key_Shared订阅就像Shared订阅一样,所有消费者都可以附加到同一订阅。但它与Key_Shared订阅不同,具有相同密钥的消息按顺序仅传递给一个消费者。消息在不同消费者之间的可能分布(默认情况下,我们事先不知道哪些密钥将分配给消费者,但密钥只会同时分配给消费者。)。

consumer1将收到:

("key-1", "message-1-1")
("key-1", "message-1-2")
("key-1", "message-1-3")
("key-3", "message-3-1")
("key-3", "message-3-2")

复制

消费者2将收到:

("key-2", "message-2-1")
("key-2", "message-2-2")
("key-2", "message-2-3")
("key-4", "message-4-1")
("key-4", "message-4-2")

复制

注意:

如果未指定消息密钥,则默认情况下,不带密钥的消息将按顺序分派给一个使用者。

读者界面

通过阅读器界面,Pulsar客户端可以在主题中“手动定位”自己,从之后的指定消息中读取所有消息。Pulsar API for Java使您可以 通过指定主题,MessageId 和ReaderConfiguration来创建 Reader对象 。

这是一个例子:

ReaderConfiguration conf = new ReaderConfiguration();
byte[] msgIdBytes = // Some message ID byte array
MessageId id = MessageId.fromByteArray(msgIdBytes);
Reader reader = pulsarClient.newReader()
        .topic(topic)
        .startMessageId(id)
        .create();

while (true) {
    Message message = reader.readNext();
    // Process message
}

复制

在上面的示例中,Reader为特定主题和消息(通过ID)实例化对象; 然后,读取器在标识的消息之后迭代主题中的每个消息msgIdBytes(如何获得该值取决于应用程序)。

上面的代码示例显示将Reader对象指向特定消息(通过ID),但您也可以使用MessageId.earliest指向主题上最早的可用消息MessageId.latest来指向最新的可用消息。

架构

在Pulsar中,所有消息数据都由“引擎盖下”的字节数组组成。消息模式使您可以在构造和处理消息时使用其他类型的数据(从简单类型(如字符串到更复杂的特定于应用程序的类型))。如果你构造一个生产者而没有指定一个模式,那么生产者只能生成类型的消息byte[]。这是一个例子:

Producer<byte[]> producer = client.newProducer()
        .topic(topic)
        .create();

复制

上面的生产者等同于a Producer(事实上​​,你应该总是明确指定类型)。如果您想将生产者用于不同类型的数据,则需要指定一个模式,通知Pulsar将通过该主题传输哪种数据类型。

架构示例

假设您有一个SensorReading类,您希望通过Pulsar主题传输:

public class SensorReading {
    public float temperature;

    public SensorReading(float temperature) {
        this.temperature = temperature;
    }

    // A no-arg constructor is required
    public SensorReading() {
    }

    public float getTemperature() {
        return temperature;
    }

    public void setTemperature(float temperature) {
        this.temperature = temperature;
    }
}

复制

然后你可以像这样创建一个Producer(或Consumer):

Producer producer = client.newProducer(JSONSchema.of(SensorReading.class))
        .topic("sensor-readings")
        .create();

复制

Java目前可以使用以下模式格式:

  • 没有架构或字节数组架构(可以使用Schema.BYTES):

    Producer<byte[]> bytesProducer = client.newProducer(Schema.BYTES)
          .topic("some-raw-bytes-topic")
          .create();
    

    复制

    或者,等效地:

    Producer<byte[]> bytesProducer = client.newProducer()
          .topic("some-raw-bytes-topic")
          .create();
    

    复制

  • String对于正常的UTF-8编码的字符串数据。可以使用Schema.STRING以下方法应用此架构:

    Producer stringProducer = client.newProducer(Schema.STRING)
          .topic("some-string-topic")
          .create();
    

    复制

  • 可以使用JSONSchema该类为POJO创建JSON模式。这是一个例子:

    Schema pojoSchema = JSONSchema.of(MyPojo.class);
    Producer pojoProducer = client.newProducer(pojoSchema)
          .topic("some-pojo-topic")
          .create();
    

    复制

认证

Pulsar目前支持两种身份验证方案:TLS和Athenz。Pulsar Java客户端可以与两者一起使用。

TLS身份验证

要使用TLS,您需要将TLS设置为true使用该setUseTls方法,将Pulsar客户端指向TLS证书路径,并提供证书和密钥文件的路径。

这是一个示例配置:

Map authParams = new HashMap<>();
authParams.put("tlsCertFile", "/path/to/client-cert.pem");
authParams.put("tlsKeyFile", "/path/to/client-key.pem");

Authentication tlsAuth = AuthenticationFactory
        .create(AuthenticationTls.class.getName(), authParams);

PulsarClient client = PulsarClient.builder()
        .serviceUrl("pulsar+ssl://my-broker.com:6651")
        .enableTls(true)
        .tlsTrustCertsFilePath("/path/to/cacert.pem")
        .authentication(tlsAuth)
        .build();

复制

Athenz

要将Athenz用作身份验证提供程序,您需要使用TLS并为哈希中的四个参数提供值:

  • tenantDomain
  • tenantService
  • providerDomain
  • privateKey

您也可以设置一个可选项keyId。这是一个示例配置:

Map authParams = new HashMap<>();
authParams.put("tenantDomain", "shopping"); // Tenant domain name
authParams.put("tenantService", "some_app"); // Tenant service name
authParams.put("providerDomain", "pulsar"); // Provider domain name
authParams.put("privateKey", "file:///path/to/private.pem"); // Tenant private key path
authParams.put("keyId", "v1"); // Key id for the tenant private key (optional, default: "0")

Authentication athenzAuth = AuthenticationFactory
        .create(AuthenticationAthenz.class.getName(), authParams);

PulsarClient client = PulsarClient.builder()
        .serviceUrl("pulsar+ssl://my-broker.com:6651")
        .enableTls(true)
        .tlsTrustCertsFilePath("/path/to/cacert.pem")
        .authentication(athenzAuth)
        .build();

复制

支持的模式格式

privateKey参数支持以下三种模式格式:

  • file:///path/to/file
  • file:/path/to/file
  • data:application/x-pem-file;base64,

https://github.com/xsm110/demo/tree/master/pulsar-demo-master

 

你可能感兴趣的:(kafka)