1. 程式人生 > >小白入門微服務(2) - 訊息佇列初體驗

小白入門微服務(2) - 訊息佇列初體驗

概述

  • 前言
  • 訊息佇列使用場景
  • 什麼是訊息佇列
  • 常用訊息佇列庫對比
  • Kafka 初體驗
  • RabbitMQ 初體驗
  • 後記

前言

前面兩篇我們學習了
- 小白入門微服務(0) - 什麼是微服務
- 小白入門微服務(1) - RPC 初體驗

接下來我們來學習微服務中的非同步通訊 - 訊息佇列。在這篇文章的學習中,預設你已經掌握了 Docker、docker-compose 的知識。如果你還沒有掌握,可以翻閱我的歷史文章。如果我的文章對你有幫助,歡迎關注、點贊、轉發,這樣我會更有動力做原創分享。

訊息佇列的使用場景

非同步處理

場景描述:在正常的使用者註冊流程中,使用者註冊完成都需要,傳送郵件與簡訊,其中傳統情況下,有序列與並行兩種方式。

序列
註冊成功之後,寫入資料庫,寫完之後,再發郵件,最後再發簡訊。總體耗時:

50 + 50 + 50 = 150 ms

並行
註冊成功之後,寫入資料庫,並行發郵件和發簡訊。總體耗時:

50 + 50 = 100 ms

訊息佇列+非同步
註冊成功之後,寫入資料庫,將寫入成功的資訊,傳送至訊息佇列,由於消費者自己去訊息佇列中取訊息,這樣在寫入訊息之後,即可成功返回。總體耗時:

50 + 5 = 55 ms

三個資料一對比,誰優誰劣就很明顯了

應用解耦

場景說明:使用者下單後,需要減去庫存系統中相應數量的庫存。

傳統呼叫方式
在傳統模式下(上圖),如果庫存系統出現錯誤,則訂單建立失敗,而且兩者過度耦合,對後面的新需求與維護也是相當大的挑戰。在原有的架構上進行升級,則有下圖:

訊息佇列呼叫方式
- 訂單系統:使用者下單後,訂單系統進行資料持久化處理,然後將訊息寫入訊息佇列,返回訂單建立成功
- 庫存系統:訂閱訊息,獲取下單資訊,庫存系統根據訂單資訊,進行庫存操作。

當下,兩者就解耦了,庫存系統出現錯誤,也可以正常進行下單了。因為只是入門文章,應用場景就先介紹到這裡。更多使用場景請自行百度、Google。

什麼是訊息佇列

訊息佇列

如圖,P 為 producer 生產者,C 為 consumer 消費者,紅色部分為訊息佇列。通俗地解釋一下訊息佇列,你想象一個場景:你到報社訂閱了一份報紙,報社每日生產一份新報紙,便將新報紙發往郵局並告訴郵局你的地址,郵遞員將你的報紙送往你的郵箱,你便可以愉快地閱讀今天的時事新聞了。當然,可能一個人訂閱了好幾家報社,一家報社也可以被多個人訂閱。在這個場景中,訊息佇列就擔任了,郵箱、郵局、郵遞員的角色。

常用訊息佇列庫對比

在網路上搜索到一個比較全面的對比圖,我這邊就直接引用原圖,不再造輪子了。原圖地址:(https://cloud.tencent.com/developer/article/1006035
訊息佇列庫對比
廣泛來說,電商、金融等對事務性要求很高的,可以考慮RabbitMQ和RocketMQ,對效能要求高的可考慮Kafka。

Kafka 初體驗

kafka 術語:

  • Broker:Kafka 叢集包含一個或多個伺服器,這種伺服器被稱為 broker。
  • Topic:每條釋出到 Kafka 叢集的訊息都有一個類別,這個類別被稱為 Topic。(物理上不同 Topic 的訊息分開儲存,邏輯上一個 Topic 的訊息雖然保存於一個或多個 broker 上,但使用者只需指定訊息的 Topic 即可生產或消費資料而不必關心資料存於何處)。
  • Partition:Partition 是物理上的概念,每個 Topic 包含一個或多個 Partition。
  • Producer:負責釋出訊息到 Kafka broker。
  • Consumer:訊息消費者,向 Kafka broker 讀取訊息的客戶端。
  • Consumer Group:每個 Consumer 屬於一個特定的 Consumer Group(可為每個 Consumer 指定 group name,若不指定 group name 則屬於預設的 group)。

安裝單節點 kafka

由於這裡只是入門,就只使用單節點了。這裡使用 Docker 來構建 kafka,其程式碼如下:docker-compose.yaml

version: '3'
services:
#<!--定義zk層服務-->
  zookeeper:
    image: wurstmeister/zookeeper
    ports:
      - "2181:2181"
#<!--定義Kafka層-->
  kafka:
    image: wurstmeister/kafka
    depends_on: [ zookeeper ]
    ports:
      - "9092:9092"
    environment:
      KAFKA_ADVERTISED_HOST_NAME: 123.45.567.89
      KAFKA_CREATE_TOPICS: "test:1:1"
      KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock

docker-compose up 啟動 kafaka。

nodejs 與 python 互調

我們先來看看,nodejs 為 producer ,python 為 comsumer 的情況:
python consumer

nodejs producer

再看看,python 為 producer,nodejs 為consumer 的情況:
nodejs consumer

python producer

程式碼展示

nodejs producer

var kafka = require('kafka-node'),
    Producer = kafka.Producer,
    KeyedMessage = kafka.KeyedMessage,
    client = new kafka.KafkaClient({kafkaHost: '123.45.567.89:9092'}),
    producer = new Producer(client),
    payloads = [
        { topic: 'my_favorite_topic', messages: 'produce by nodejs', partition: 0 }
    ];
producer.on('ready', function () {
    producer.send(payloads, function (err, data) {
        console.log(data);
    });
});
producer.on('error', function (err) {})

nodejs consumer

var kafka = require('kafka-node'),
    Consumer = kafka.Consumer,
    client = new kafka.KafkaClient({kafkaHost: '123.45.567.89:9092'}),
    consumer = new Consumer(
        client,
        [
            {topic: 'my_favorite_topic', partition: 0}
        ],
        {
            autoCommit: false
        }
    );
consumer.on('message', function (message) {
    console.log(message);
});

python producer

from kafka import KafkaProducer
producer = KafkaProducer(bootstrap_servers=['123.45.567.89:9092'],
                         api_version=(0, 10, 1)
                         )  # 此處ip可以是多個['0.0.0.1:9092','0.0.0.2:9092','0.0.0.3:9092' ]
for _ in range(100):
    producer.send('my_favorite_topic', b'produce by python')
producer.close()

python consumer

from kafka import KafkaConsumer
consumer = KafkaConsumer('my_favorite_topic', bootstrap_servers=['123.45.567.89:9092'], api_version=(0, 10, 1)
for msg in consumer:
    print(msg)

RabbitMq 初體驗

介紹過 Kafka 之後,RabbitMQ 就不在詳細介紹了,請看原始碼了。

後記

不知不覺,訊息佇列也講完了,要真真切切地區實踐,才能真正地掌握。
個人的知識儲備總是有限的,如有錯誤的地方,還請大佬斧正。點選閱讀原文,連結到我的知乎,我會在知乎上對文章錯誤的地方進行修改。

本篇文章首發於公眾號「zone7」,關注公眾號獲取最新推文,後臺回覆【小白微服務】獲取原始碼。