php| 初探 rabbitmq

date: 2018-09-03 21:30:23
title: php| 初探 rabbitmq
description: 零零散散折騰了 rabbitmq 幾次, 歸納總結(jié)一下先

經(jīng)常看到消息隊(duì)列( MQ ), 實(shí)戰(zhàn)中比較少, 說說我的一些粗線的理解:

  • 引入消息隊(duì)列, 使系統(tǒng)之間解耦 -> 當(dāng)然還有很多 小型項(xiàng)目 使用 重項(xiàng)目 的方式(系統(tǒng)拆分, 不存在的!); 解耦這部分的內(nèi)容, 后來還會講到
  • 通過將流程 異步化, 增加每部分的吞吐能力, 從而實(shí)現(xiàn)最終增加系統(tǒng)性能, 這一點(diǎn)有點(diǎn)類似服務(wù)器領(lǐng)域的 同步 -> 異步/協(xié)程, 可以參考 swoole| swoole 協(xié)程初體驗(yàn)

當(dāng)然, 實(shí)踐出真知, 還是希望能在業(yè)務(wù)中多實(shí)戰(zhàn), 或者參與相關(guān)的開源項(xiàng)目~

相關(guān)教程

老生常談, 生命周期思維方式, 想一想消息是怎么在整個(gè)消息隊(duì)列系統(tǒng)中流動的.

應(yīng)用場景: 冗余 解耦 流量削峰 異步通信 擴(kuò)展新 排序保證 -> 隊(duì)列結(jié)構(gòu)的中間件
隊(duì)列介質(zhì): mysql redis 消息隊(duì)列服務(wù)(rabbitmq kafka)
觸發(fā)機(jī)制: 死循環(huán)while 定時(shí)腳本cron 守護(hù)進(jìn)程daemon(fpm)
場景一 訂單系統(tǒng)/配送系統(tǒng)解耦: 訂單系統(tǒng) -> 隊(duì)列表 -> 配送系統(tǒng)
場景二 流量削峰: redis list類型實(shí)現(xiàn)定長隊(duì)列, 請求先入隊(duì)列, 超出隊(duì)列長度后的請求丟棄
rabbitmq架構(gòu)和原理: 完整實(shí)現(xiàn)AMQP 集群簡化 持久化 跨平臺

基于 AMQP(advanced message queue protocol, 高級消息隊(duì)列協(xié)議)
集群模式: 表達(dá)式配置 HA模式 鏡像隊(duì)列模式
保證數(shù)據(jù)不丟失/高可靠/高可用

安裝 rabbitmq

老生常談, 直接上 docker:

docker-compose, 使用 rabbitmq 官方鏡像:

version: '3'
services:
    rabbitmq: # https://hub.docker.com/_/rabbitmq/
        image: rabbitmq:3.7.7-management-alpine
        hostname: myrabbitmq
        ports:
            - "5672:5672" # mq
            - "15672:15672" # admin

就這么幾行, rabbitmq 就配置好了, 使用 docker-compose up -d rabbit 啟動, 大功告成

這里使用的 management 版本的 rabbitmq, 管理控制臺地址 http://localhost:15672, 初始密碼 guest/guest

進(jìn)入容器內(nèi)部看看:

# 進(jìn)入容器
docker-compose exec rabbitmq bash 

# 查看啟動的服務(wù)
bash-4.4# ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
rabbitmq     1  0.0  0.0   1612  1012 ?        Ss   06:25   0:00 /bin/sh /opt/rabbitmq/sbin/rabbitmq-server
rabbitmq    90  0.0  0.0   1068   660 ?        S    06:25   0:00 /usr/lib/erlang/erts-9.3/bin/epmd -daemon
rabbitmq   158  0.5  3.9 1707624 81152 ?       Sl   06:25   0:37 /usr/lib/erlang/erts-9.3/bin/beam.smp -W w -A 64 -MBas ageffcbf -MHas ageffcbf -MBlmbcs 512 -MHlmbcs 512 -MMmcs 30 -P 1048576 -t 5000000 -s
rabbitmq   265  0.0  0.0    752   536 ?        Ss   06:25   0:00 erl_child_setup 1048576
rabbitmq   306  0.0  0.0    772     4 ?        Ss   06:25   0:00 inet_gethost 4
rabbitmq   307  0.0  0.0    772    32 ?        S    06:25   0:00 inet_gethost 4
root      3258  0.0  0.0   6364  2004 pts/0    Ss   07:25   0:00 bash
root      6813  0.0  0.0   5696   628 pts/0    R+   08:23   0:00 ps aux

# rabbitmq 相關(guān)命令行命令
bash-4.4# rabbitmq 
rabbitmq-defaults     rabbitmq-diagnostics  rabbitmq-env          rabbitmq-plugins      rabbitmq-server       rabbitmqadmin         rabbitmqctl
  • rabbitmqctl: rabbitmq control
  • rabbitmq-plugins: 也可以通過 rabbitmq-plugins 來開啟管理控制臺

更多配置, 可以訪問 rabbitmq鏡像官網(wǎng) 進(jìn)行查看

快速開始

rabbitmq 官方文檔 非常完善與清晰, 值得花時(shí)間看看

新手快速入門文檔, 代碼 - rabbitmq/rabbitmq-tutorials

rabbitmq 支持多種語言的 client, 這里說明支持的 php client:

  • php-amqplib: compoer package, 入門 rabbitmq 最簡單的方式, composer require 即可完成安裝
  • ext-amqp: PHP擴(kuò)展, 需要安裝 ext-amqp 擴(kuò)展, 性能更優(yōu)

queue-interop 按下不表, 還沒進(jìn)入 PSR.

官方的快速入門手冊:

  • hello world

消息隊(duì)列最基礎(chǔ)的三個(gè)概念, 生產(chǎn)者producer + 消息隊(duì)列MQ + 消費(fèi)者consumer

image
  • work queues

如果 消費(fèi)者的消費(fèi)能力不足 怎么辦? 多開幾個(gè) consumer 唄. 多個(gè) consumer 怎么分擔(dān) MQ 中的消息呢? 所以在 消息隊(duì)列MQ 和 消費(fèi)者consumer 之間進(jìn)行 負(fù)載均衡LB. LB并不是準(zhǔn)去的說法, 通常的說法是消費(fèi)者 訂閱 消息隊(duì)列的內(nèi)容. 在我看來, LB 更有表現(xiàn)力 -- 消費(fèi)能力不足導(dǎo)致需要多個(gè)消費(fèi)者, 怎么和 web server 并發(fā)不夠, 加機(jī)器加 LB 有些像呢?

這里我使用的 LB 這樣的概念, 目的在于 LB 在服務(wù)器領(lǐng)域太常見了, 包含很多內(nèi)容, 需要細(xì)細(xì)體會

image
  • pub/sub

發(fā)布訂閱, 看起來像多個(gè) hello world, 注意圖里多了一個(gè) rabbitmq 中的新概念 交換器exchange(圖中簡寫為 X), 在 生產(chǎn)者producer 和 消息隊(duì)列MQ 之間, 由 exchange 來決定消息 分發(fā) 到哪個(gè) MQ 中

image
  • routing/topic

兩個(gè)新的概念, 路由功能主體訂閱 功能, 而這些都和 交換器exchange 有關(guān), 涉及到的配置: 交換器類型(exchange type) + 路由key(routing key) + 綁定key(binding key). 為啥會這么復(fù)雜呢? 干嘛要這么多配置?

一言以蔽之, 決定 生產(chǎn)者producer 產(chǎn)生的消息, 投遞到哪個(gè) 消息隊(duì)列MQ 中, 最終又由哪個(gè) consumer 消費(fèi)

routing

topic
  • RPC

新玩法, 通過消息隊(duì)列實(shí)現(xiàn) 遠(yuǎn)程過程調(diào)用RPC 的效果

image

我在這里并沒有貼具體代碼, 一則因?yàn)楣俜浇o的代碼確實(shí)適合上手, 更重要是因?yàn)? 理解 rabbitmq 究竟是個(gè)什么玩意 更重要

rabbitmq 究竟是啥

  • 首先是 MQ 最基礎(chǔ)的概念: 生產(chǎn)者producer + 消息隊(duì)列MQ(狹義指存儲消息的隊(duì)列類型的數(shù)據(jù)結(jié)構(gòu)) + 消費(fèi)者consumer
  • consumer 怎么從 MQ 中獲取消息 + consumer獲取消息后確認(rèn)(ack): 可以近似理解 MQ 和 consumer 之間需要一層 LB
  • producer 怎么投遞消息到 MQ 中: exchange + exchange type + routing key + binding key -> 消息路由/主題訂閱
  • 怎么擴(kuò)展 MQ 的性能呢: 集群, 涉及到集群, 又會新增很多概念了

放幾張圖輔助理解:

amqp模型
  • 實(shí)際使用過程中, 還需要 tcp 連接相關(guān)的概念: connection + channel
rabbitmq模型
  • 這張圖可以看到消息msg 的 生命周期
rabbitmq消息流轉(zhuǎn)

寫在最后

正兒八經(jīng)(準(zhǔn)確說, 這叫 專業(yè)) 的消息隊(duì)列, 架構(gòu)設(shè)計(jì)上確實(shí)有一定的復(fù)雜性, 而且為了滿足高性能, 還會有很多性能優(yōu)化的點(diǎn) -- 學(xué)習(xí)消息隊(duì)列, 長路漫漫, 可以好好折騰一番了~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,699評論 19 139
  • 來源 RabbitMQ是用Erlang實(shí)現(xiàn)的一個(gè)高并發(fā)高可靠AMQP消息隊(duì)列服務(wù)器。支持消息的持久化、事務(wù)、擁塞控...
    jiangmo閱讀 10,519評論 2 34
  • 本文大綱 RabbitMQ 歷史 RabbitMQ 應(yīng)用場景 RabbitMQ 系統(tǒng)架構(gòu) RabbitMQ 基本概...
    Java_Explorer閱讀 16,808評論 1 40
  • 1. 歷史 RabbitMQ是一個(gè)由erlang開發(fā)的AMQP(Advanced Message Queue )的...
    高廣超閱讀 6,241評論 3 51
  • 什么叫消息隊(duì)列 消息(Message)是指在應(yīng)用間傳送的數(shù)據(jù)。消息可以非常簡單,比如只包含文本字符串,也可以更復(fù)雜...
    lijun_m閱讀 1,419評論 0 1

友情鏈接更多精彩內(nèi)容