從celery rabbitmq with docker-compose 引出對容器、依賴注入、TDD的感悟

用docker配置項目管理系統taiga的時候,不是我一我的遇到這個問題。https://github.com/douglasmiranda/docker-taiga/issues/5html

問題描述:

用docker-compose啓動celery_worker和rabbitmq,可是celery_worker 連不上 rabbitmqgit

celeryworker_1 | [2017-12-06 07:56:36,539: ERROR/MainProcess] consumer: Cannot connect to amqp://guest:**@rabbit1:5672//: [Errno -2] Name or service not known.
celeryworker_1 | Trying again in 4.00 seconds...github

 

建立celery的地方用官網的web

app = Celery(backend='amqp', broker='amqp://')

 

是不行的。docker

改爲正式點的:數據庫

app = Celery(backend='amqp', broker='amqp://guest:guest@localhost:5672/')

 

也是不行的,不論用localhost。docker-compose 裏 給 rabbitmq 設置的  hostname 都是不行的django

 

成功嘗試一:rabbitmq在容器中,celery worker 和 發起異步任務在host

遇到問題1,首先縮小問題。分步嘗試,首先嚐試只用容器啓動rabbitmq。而後和傳統方式同樣,在host手工啓動celery worker。ubuntu

成功。網絡

問題縮小到celery_worker容器化的問題。app

稍微靠譜點的解法是

1先手工建立1個docker bridge

2 用docker命令行分別啓動rabbitmq和celery worker 

3 手工把celery worker 和 rabbitmq 添加進bridge。

聽說可行,可是我就是要用docker-compose的啊,這樣太醜陋了。

但至少說明有可能成功(不是celery自己bug之類)

 

 

 成功嘗試2、rabbitmq 和celeryworker都在容器中,celery用host的ip地址鏈接rabbitmq。

異步發起者能夠在容器中,也能夠在host中

 

docker中只運行rabbitmq,暴露5672 和15672端口,在本地host安裝celery 起celery worker 是沒問題的

可是若是想把celery worker也放進容器裏,就出問題了。老是提示連不上amqp。

 用了各類方法,最終把rabbit5672暴露,而後把HOST主機IP灌進celery,搞定

 HOST_IP = '192.168.239.129' # ip of host(run docker-compose) 
app = Celery(backend = 'rpc://', broker = 'amqp://guest:guest@{0}:5672/'.format(HOST_IP))

額外的小技巧:

ubuntu查看 ip :

ip addr show

 

 成功嘗試3、rabbitmq 和celeryworker都在容器中,celery用docker-compose.yml中的service_name鏈接

異步發起者只能在容器中

20171207隔了一天,終於發現其實不須要HOST_IP,能夠用名字鏈接的!

只不過名字被docker、rabbitmq給來回誤導了

先說答案:celery裏要用docker-compose.yml裏的這個名字,即啓動rabbitmq鏡像的那個service的名字(而不是他的hostname,我把它註釋掉了,太坑人):

這樣搞的話,比用HOST_IP很差的地方在於,無法從host發起異步任務(返回不告終果)。只能從docker-compose啓動容器,在裏面發起異步任務。

好處是5672端口不用暴露出來了。docker-compose內網和外部徹底隔離,外面感受不到rabbitmq存在(固然我保留了暴露15672監控端口,其實也能夠不暴露)

 

 ——其實postgres的問題也是同樣,用Adminer鏈接的時候,Server處填的也是docker-composer.yml裏的service名字。

http://www.cnblogs.com/xuanmanstein/p/7742647.html

 

 

結論

解決方案不細說了,放github上了

https://github.com/xuqinghan/celery-with-docker-compose#celery-with-docker-compose

 

心得:

1 遇到問題,要縮小、後退、分解。

 像鋸木頭鋸不動了,要日後撤,而後稍微換換方向,角度,再用巧力,不要用蠻力:

1從部署taiga的event模塊遇到celery_worker鏈接不上;

2退到用docker-compose運行celery官網的a+b小函數的demo 仍是連不上;

3再繼續後退:只用docker-compose部署rabbitmq。手工啓動celery和發起異步任務,成功。

4在3成功的基礎上小步前進。而此時問題已經縮小、聚焦到足夠小,再嘗試幾種解決方案:localhost   127.0.0.1   hostname     bridge方式docker0網絡

5搞定、總結。成爲本身的技能點,處處複用。

2 不要有潔癖,

不追求rabbitmq不暴露任何端口,只服務於docker-compose的網絡(不是docker0) ,在host裏暴露端口不丟人;

在開發機上,只在調試當前工程時啓動當前的docker-compose。在生產環境仍是1機1個組的。不追求多工程在一個機器上運行。

不追求一次就實現全都容器化,和寫代碼同樣,先寫好單次執行的邏輯,再套外層的for循環。

——注意到了這些點,問題半天不到就搞定了;死鑽牛角尖,可能N天都無解。

 

3 不能有0 or 100分這種想法。

不能急躁,也不能浮躁(想一次就得100分);

也不能由於想太多,把問題當作鐵板1塊,就畏懼困難(直接交白卷得0分)。

——作工程,都是1分、1分地得分,也是1分 1分地扣分的。 這和合同收付款、各類節點是徹底不一樣的!不要被後者的干擾帶亂了本身的工做節奏。

作工程是相似持倉、空倉的長期過程,而不是啪啪啪不斷交易的各類精彩瞬間。(若是永遠處在趕工、保/搶節點的狀態,要麼是本身工做能力不行,要麼就是項目管理SB,沒有輕重緩急)

 

4作工程的人,在工程上作任何事每次出手,都要有章有法:有高度的目的論,且目的又和普通人不一樣:

1 貫徹目的和意圖導向的思考。在乎從需求、系統用例、到組件名、類名、子過程名、直到變量名的命名,名不正則言不順,要強迫本身和別人(Не жалей ни себя, ни врагов.「不要吝惜本身和敵人」——《斯拉夫女人的告別》白俄版)思考目的性、價值和重要性排序。而且在每一天、每一句的開發中不斷加深學習、打磨、養成習慣;

2 能每時每刻聚焦特定問題,能暫時忽略其餘問題和要求,有「置XX之敵於不顧」,「攻其一點,不及其他」的勇氣和能耐。這是創建在對能力的自信心(「打哪一個,哪一個就剩不下」,因此我有資格挑着打)基礎之上的純粹和純淨的心理狀態。

接觸新人、業餘選手、非技術人員的最大感受就是:

在1上,想的太簡單,作的太隨意(用個人話說,像個孩子);

在2上,一次想得太,想得太多(0分VS100分 來回地跳變,仍是像個什麼都想要的孩子)。

——包括以前的本身,也是這樣。仍是由於功力不夠+心浮氣躁=棒槌。

由於和他們視角不一樣(甚至徹底不一樣),因此本身首先不要生氣,配合別人的任務區時能夠忍着點,盡力配合;

但只要進入本身的責任區,就是要火力全開。若是氣着對方也不要在乎(負責這片的人是我,我也沒想故意氣誰,因此也無所謂)。

和戰鬥機同樣,包線上各有優點區,但進入大噴9(Spitfire LF IX)的優點區,就不要怪Hispano 炮狠了。

 

技術方面的感覺:容器和鏡像不是萬能的。不是什麼都適合打包進鏡像。

celery和django都相繼再也不在dockerhub發佈官方鏡像。由於這倆在用的時候,你們都是定製、引用以後才用的。

並非這倆和docker決裂了,只是不適合打包進dockerfile罷了。

對開發人員來講,什麼適合塞進dockerfile呢?配環境的步驟+配出來的一致性,隔離的、純淨的運行環境。塞配置文件的位置。

其實dockerfile有點像測試框架。而源代碼和配置文件,相似mock。

因此,這符合我下意識的作法:我喜歡把源代碼、和各類配置文件,數據庫文件都放在外面, 用-v 或者volumns 在容器啓動時掛進去,而不是寫在dockerfile裏(git clone 源代碼,具體配置參數),直接build成image。

 

這種套路,很是相似於依賴注入,把repository,service塞進component的過程。

此外,這樣好寫測試用例啊(不依賴實際鏈接web和數據庫)!

任何單元測試的運行,都不能依賴真實的web和數據庫訪問。

不然由於耗時間或者環境難配,不得不每次註釋掉一部分用例,如今想一想,那還測試個屁啊!

 

寫程序的精髓在於識別和感覺到  複雜性+變化性   VS  繁瑣+穩定    ,而後不斷分離,隔離,讓不一樣變化速率,膨脹係數的材料,高度地解耦。

——寫程序的門道無非那幾條,可是知道這些道理是一回事,理解認同這些道理是另外一回事, 而實際工做中能在各類場合把這些招給用出來,用活了,又是另外一回事了。

和武術、修行同樣,知易行難。「三歲小兒道得,八十老翁行不得」。

須要勤學苦練,不是蠻幹(grasshopper裏不寫代碼,一片一片地電池)

從各類角度、各類道路、屢次實踐,去領悟相同的道理。

而後就容易全面開竅和處處突破了。

以前瞭解、學TDD半天,可是就是用很差;如今用了一段時間docker,反而容易找到依賴注入的感受。

本身寫的程序,有哪些是框架性的,相似dockefile的;有哪些是頻繁改動的,相似源代碼、配置文件內容的,要井井有條,分離,而後各自得到自由;

這個分離:就是意圖與實現、虛VS實;部隊 VS 分隊,測試用例VS外部接口的mock。

關注點分離了,就各自聚焦了,也自由了。分得開,責任邊界清晰,才聯合得起來。

相關文章
相關標籤/搜索