从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。

关注点分离了,就各自聚焦了,也自由了。分得开,责任边界清晰,才联合得起来。

相关文章
相关标签/搜索