Apache Pulsar 發佈訂閱消息系統

Apache Pulsar 發佈訂閱消息系統


Apache Pulsar

Apache Pulsar is an open-source distributed pub-sub messaging system originally created at Yahoo and now part of the Apache Software Foundation

Apache Pulsar是一個開源的分佈式pub-sub消息系統,最初由雅虎開發,現在是Apache軟件基金會的一個孵化器項目。

1. Topic
Topic名稱的URL結構:{persistent|non-persistent}:\tenant\namespace\topic

persistent|non-persistent 表示數據是否持久化
tenant 表示租戶
namespace 聚合一系列相關的Topic,一個租戶可以有多個namespace

在這裏插入圖片描述
2.發送模式
producer可以同步或者異步是的方式發佈消息到broker

同步發送 發送消息後,producer等待broker的確認,沒有收到確認,會認爲發送失敗。
異步發送 producer把消息放入blocking隊列,立馬返回,客戶端將會在背後把消息發送給broker。如果隊列滿了,根據傳給producer的參數,可能阻塞或者返回失敗。

3.接收模式
消息可以通過同步或者異步的方式從broker接收。

同步接收 同步接收將會阻塞,直到消息可用。
異步接收 異步接收立即返回future值,java中的completableFuture。一旦消息可用,即刻完成。

3.訂閱模型
在這裏插入圖片描述
(1)Exclusive(獨佔) Exclusive模式爲默認訂閱模式。
獨佔模式,只能有一個消費者綁定到訂閱subscription上,如果多於一個消費者嘗試以同樣的方式訂閱主題,消費者將會收到錯誤。
(2)Shared(共享)
多個消費者可以綁定到同一個訂閱上,消費通過輪詢機制分發給不同的消費者,每個消息僅會被分發給一個消費者。當消費者斷開連接,所有被髮送給他,但沒有被確認的消息將重新被安排,分發給其他存活的消費者。
(3)Failover(災備)
多個consumer可以綁定到同一個 subscription。consumer會按字典順序排序,第一個consumer被初始化爲唯一接收消息的消費者,作爲master consumer。當斷開時,所有的消息(未被確認和後續進入的)將被分發給列中的下一個consumer。

GitHub: link.

項目整合Pulsar

	<dependency>
            <groupId>org.apache.pulsar</groupId>
            <artifactId>pulsar-client</artifactId>
            <version>2.2.0</version>
	</dependency>

1.PulsarClient(Client創建)

private static final Logger LOG = LoggerFactory.getLogger(PulsarService.class);
    private PulsarClient pulsarClient;
    private Gson gson;

    @Value("${pulsarServiceUrl}")
    private String pulsarServiceUrl;

    @PostConstruct
    public void init() {
        gson = new Gson();
        try {
            pulsarClient = PulsarClient.builder()
                    .serviceUrl(pulsarServiceUrl)
                    .build();
        } catch (PulsarClientException e) {
            LOG.error("PulsarClient build failure!! error={}", e.getMessage());
        }
    }

2.生產者(發佈消息)

public String produce(String topic, String message) {
        try {
            Producer<String> producer = pulsarClient.newProducer(Schema.STRING)
                    .topic("persistent://public/default/" + topic)
                    .create();
            MessageId messageId = producer.send(message);
            producer.close();
            LOG.info("topic={} message={} messageId={}", topic, message, messageId);
            return "topic=" + topic + " message=" + message + " messageId=" + messageId;
        } catch (Exception e) {
            LOG.error("Pulsar produce failure!! error={}", e.getMessage());
            return "Pulsar produce failure!! error=" + e.getMessage();
        }
    }

3.消費者(消費消息)

public void consume(String topic) {
        new Thread(() -> {
            try {
                Consumer<String> consumer = pulsarClient.newConsumer(Schema.STRING)
                        .topic(topic)
                        .subscriptionName(topic)
                        .subscribe();
                while (!Thread.currentThread().isInterrupted()) {
                    Message<String> message = consumer.receive();
                    String data = new String(message.getData());
                    consumer.acknowledge(message);
                    MessageId messageId = message.getMessageId();
                    LOG.info("topic={},message={},messageId={}", topic, data, messageId.toString());
                    Thread.sleep(20);
                }
            } catch (Exception e) {
                LOG.error("Pulsar consume failure!! error={}", e.getMessage());
            }
        }).start();
    }

4.閱讀器(從指定messageId處讀取消息)

public void read(String topic, String offset) {
        new Thread(() -> {
            try {
                String[] offsetSplit = offset.split(":");
                MessageId msgId = new BatchMessageIdImpl(Long.parseLong(offsetSplit[0]), Long.parseLong(offsetSplit[1]), Integer.parseInt(offsetSplit[2]), Integer.parseInt(offsetSplit[3]));
                Reader<String> reader = pulsarClient.newReader(Schema.STRING)
                        .topic(topic)
                        .startMessageId(msgId)
                        .create();
                while (!Thread.currentThread().isInterrupted()) {
                    Message message = reader.readNext();
                    String data = new String(message.getData());
                    MessageId messageId = message.getMessageId();
                    LOG.info("topic={},message={},messageId={}", topic, data, messageId.toString());
                    Thread.sleep(20);
                }
            } catch (Exception e) {
                LOG.error("Pulsar read failure!! error={}", e.getMessage());
            }
        }).start();
    }

GitHub: link.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章