聲明:本文僅限于簡書發(fā)布禁谦,其他第三方網(wǎng)站均為盜版导盅,原文地址: Kombu 源碼解析一
Kombu 源碼解析一
玩 Python 的同學(xué)可能很多都聽說過甚至玩過 Celery,Celery 作為 Python 中最流行的異步消息隊(duì)列可以說是非常得受歡迎。但是梧兼,用得多的同學(xué)相信也是有一個(gè)感觸,那就是時(shí)不時(shí)會(huì)遇到莫名奇妙的坑智听,而且最后都只能通過重啟解決羽杰,因?yàn)橐业皆驅(qū)嵲诓皇且患菀椎氖虑椤?/p>
而我作為這受傷人群中的一個(gè),想了解一下這個(gè)大坑內(nèi)部的原理到推,所以就曾經(jīng)扒過它內(nèi)部的實(shí)現(xiàn)考赛,但是,由于 Celery 確實(shí)有點(diǎn)龐大环肘,而且我認(rèn)為代碼實(shí)現(xiàn)得也不是很多欲虚,所以,只是學(xué)習(xí)到了一部分的知識悔雹,但是复哆,卻是收獲良多。所以腌零,最近因?yàn)楦鞣N情況梯找,我這次深扒一次,所以后續(xù)將會(huì)有一系列的文章是講 Celery 實(shí)現(xiàn)的益涧。
當(dāng)你嘗試查看 Celery 的源碼的時(shí)候锈锤,你會(huì)發(fā)現(xiàn)有一個(gè)你根本繞不過的坑的,那就是 Kombu闲询,Kombu 的定位是一個(gè)兼容 AMQP 協(xié)議的消息隊(duì)列抽象久免,但是,這只是作者的一面說辭扭弧,你看完代碼就知道了阎姥,它是嘗試做異步MQ 的兼容 AMQP 的抽象隊(duì)列。所以鸽捻,我決定先從 Kombu 的代碼寫起呼巴,而這篇文章是第一篇!
我在這個(gè)系列里面講的都是 Kombu 4.1.0 和 Celery 4.1.0 的事御蒲,先提前說一下衣赶,以免后續(xù)的同學(xué)對不上號。
下載 Kombu 代碼
Kombu 的代碼很好找厚满,因?yàn)樗?Celery 是強(qiáng)耦合的府瞄,所以,它的代碼放在 Celery 的代碼組里頭碘箍,可以很簡單得 Github 上找到摘能,所以下載也是很簡單了:
> git clone https://github.com/celery/kombu.git
> cd kombu
> git checkout v4.1.0
這樣续崖,你就得到了我這個(gè)系列文章里面的 Kombu 的源代碼了,而我后面的所有代碼來源以及行數(shù)都是對應(yīng)這個(gè)版本的代碼的团搞!
整體 Review
拿到代碼之后严望,我就先摒棄所有的非代碼部分,直接來整體看看 kombu 這個(gè)目錄下有什么:
可以看到逻恐,在 kombu 這個(gè)目錄里面大部分都是文件像吻,而只有三個(gè)文件夾,分別是:
- async:異步操作的 函數(shù) 和 類
- transport:兼容各種 MQ 的類
- utils: 一些輔助 函數(shù) 和 類
從這個(gè)目錄中复隆,我們就發(fā)現(xiàn)了一些問題拨匆,你說你既然是抽象 MQ 的,你要啥異步操作啊挽拂,這有點(diǎn)越界了呀喂惭每。
簡單添加/獲取消息
OK,概覽完我們看一些實(shí)際的東西亏栈,先嘗試用 Kombu 寫一個(gè)生產(chǎn)/消費(fèi)的代碼吧台腥,這個(gè) DEMO 分為兩部分
- simple_receive.py:一個(gè)簡單的消費(fèi)者
- simple_send.py:一個(gè)簡單的生產(chǎn)者
下面看看這兩段代碼都是怎么寫的:
還是老規(guī)矩,這兩段代碼你都可以在我的 Github 中找到绒北。先看看看消費(fèi)者黎侈,消費(fèi)者的代碼比較簡單,我們先建立和 MQ 的連接闷游,然后再從 MQ 的指定隊(duì)列里面將消息拿出來峻汉,處理掉。
而生產(chǎn)者則相反脐往,前面也是要先和隊(duì)列建立連接休吠,但是,有一點(diǎn)不一樣的是這里創(chuàng)建了一個(gè) exchange业簿,然后再往隊(duì)列里面發(fā)送消息瘤礁,而發(fā)送消息的同時(shí)還是搭配好多參數(shù)。
這里就是 Kombu 有意思的一點(diǎn)了辖源,它意圖對所有的 MQ 進(jìn)行抽象,然后通過接口對外暴露出一致的 API希太,這樣我們就不用關(guān)心底層用的是什么 MQ 了克饶,Redis/RabbitMQ/MongoDB 之類的隨便切換。
Kombu 的 MQ 模型
因?yàn)?Kombu 是對 AMQP 進(jìn)行抽象誊辉,所以它必定有抽象的模型矾湃,事實(shí)上,它大體上和 RabbitMQ 差不多堕澄,但是邀跃,不完全一樣霉咨,有一些差別,下面就介紹一下 Konbu 的抽象模型拍屑。
在 Kombu 中途戒,存在多個(gè)概念,其實(shí)我們在前邊簡單的生產(chǎn)/消費(fèi)者樣例中已經(jīng)看到了了一些僵驰,他們分別是:
- Message:生產(chǎn)消費(fèi)的基本單位喷斋,其實(shí)就是我們所謂的一條條消息
- Connection:對 MQ 連接的抽象,一個(gè) Connection 就對應(yīng)一個(gè) MQ 的連接
- Transport:真實(shí)的 MQ 連接蒜茴,也是真正連接到 MQ(redis/rabbitmq) 的實(shí)例
- Producers: 發(fā)送消息的抽象類
- Consumers:接受消息的抽象類
- Exchange:MQ 路由星爪,這個(gè)和 RabbitMQ 差不多,支持 5 類型
- Queue:對應(yīng)的 queue 抽象粉私,其實(shí)就是一個(gè)字符串的封裝
消息是發(fā)送到那個(gè) Queue 的
假設(shè)我們想要發(fā)送一個(gè)消息到 Redis 中名為 'test' 的 queue 中顽腾,那么 Kombu 是怎么做的,這就設(shè)計(jì)到 Exchange 的概念了诺核。目前 Kombu 對于不同 MQ 的支持是這樣的:
假設(shè)我們用的是 Direct抄肖,那么我們的 Producer 在生產(chǎn)的時(shí)候只需要指定 Queue=test 即可,這樣就會(huì)發(fā)送的 test 這個(gè) queue 中猪瞬。更多關(guān)于 Exchange 的知識可以參考:AMQP 0-9-1 Model Explained
這一篇就先介紹到這里憎瘸,后續(xù)就開始深入到代碼層面,看下這個(gè)模型中的各個(gè)實(shí)體是如何實(shí)現(xiàn)的陈瘦。