V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
akmonde
V2EX  ›  Python

celery 多节点是否适合代替多线程(线程池)

  •  
  •   akmonde · 2018-08-22 10:16:18 +08:00 · 3663 次点击
    这是一个创建于 2318 天前的主题,其中的信息可能已经有所发展或是发生改变。

    大家好,现在有个需求,我一个 fuzz 项目里有多个 module,每个 module 里会带上多个不同的脚本( fuzz 脚本)。

    原来是采用的是主入口通过 celery 调用多个 module,每个 module 采用线程池进行脚本调用,最后将线程池聚合的结果存入数据库(如 mysql )。


    但是后来遇到了瓶颈,某些脚本容易卡住比较长时间,拉高线程数速度也上不去。

    所以我在想,有没有可能主控入口通过 celery 节点调用多个 module,然后每个 module 用 celery 节点调用多个脚本,这样能提高可扩展性,我只要增加节点,无论是加机器还是提高单个机器的配置,理论上就能加快整体速度。


    本来线程池聚合数据还是蛮容易的,如果用多个 celery 节点调用多个脚本,我想到的只能用 redis push,最后再想法子把每一坨结果做数据聚合。

    但是这又带来了新的问题,每一坨数据不知道啥时候完,如果某个 module 脚本比较多,我总不能监控每个脚本任务都监控吧,最后需要的是每个 module 跑完了的聚合结果,才能入库(如 mysql )。

    求大佬们指教,有没有啥办法,如果能解决 v 币感谢~

    在线等,很急!

    8 条回复    2018-08-27 09:14:30 +08:00
    pekingzcc
        1
    pekingzcc  
       2018-08-22 13:21:46 +08:00   ❤️ 1
    celery 的 workflow 有一个 chord,支持一系列异步任务完成后 执行一个同步任务,lz 可以了解下,不知道可不可以解决你的后一个问题
    monsterxx03
        2
    monsterxx03  
       2018-08-22 13:36:27 +08:00   ❤️ 1
    配置下 result backend, 然后入口处脚本同步等待结果, 这样计算是在 celery worker 节点, 你能在入口处得到所有的结果.

    ret = task.delay()
    ret.get()

    每个任务在单独的线程中分发, 最后就和你写单机多线程一样用了.
    akmonde
        3
    akmonde  
    OP
       2018-08-22 13:38:27 +08:00
    @pekingzcc 最后玩计数嘛?嗯嗯,我想想怎么解决获得整个 module 都完成的信号问题。
    akmonde
        4
    akmonde  
    OP
       2018-08-22 13:48:33 +08:00
    @monsterxx03 大佬的意思是用多线程分发 module,然后 celery worker 节点去实现多脚本任务?然后用标识去定位 get 每个 module 的所有结果?不知道我理解是否有误?
    monsterxx03
        5
    monsterxx03  
       2018-08-22 13:58:16 +08:00   ❤️ 1
    不是很明白你的 module 指什么, 一个 python 的 module(带__init__.py)?

    celery 调度的单位是 task, 我的理解你应该把每个 fuzz 脚本的入口处封装成一个 celery task, 所有的 worker 节点上预先放好所有的代码. 入口处只负责分发 task, 同步等待 task 执行结果,就能在入口处汇总所有数据了.

    如果脚本之间没有顺序依赖,只是想最后得到所有结果的话, 我说的应该就够了, 有依赖关系可以看看上面说的 chord.
    akmonde
        6
    akmonde  
    OP
       2018-08-22 16:20:04 +08:00
    @monsterxx03 大概了解了,我那边 module 的意思是,主程入口有多个函数,每个函数算是一个 module,会分别对一批脚本进行调用,也就是您说的 task 分发入口吧,以前做的都是只 task 分发这里的 module,然后每个 task 里面多线程跑脚本。
    不过这样的话,节点不够多的话 效果不一定比多线程强,因为多线程 20-30 稀松平常,如果两三台机器每个跑五六个节点好像还算正常?这样算下来,估计机器少的话,效果估计一般。
    PS:忘了每个节点是不是可以跑同时多个 task,我记得貌似可以。
    akmonde
        7
    akmonde  
    OP
       2018-08-27 08:53:28 +08:00
    @monsterxx03 前两天没看到您最后的回复,我自己看了下还是有点迷糊。您的意思是每个 task 里面是单独包含一个脚本么,然后再在配置好的 result backend 里面,通过异步标记然后最后通过标记汇总结果么,查了下好像没有合适的参考资料。

    参考了下几篇文章,比如这篇,就是通过 id 查询的:
    ```
    https://www.cnblogs.com/piperck/p/5391128.html
    ```

    至于您此前说的,```入口处只负责分发 task,就能在入口处汇总所有数据```,我不太清楚您是否指的是每个 task 只运行一个脚本,然后再在入口处聚合。如果是这样的话,难道是拿到结果后手工聚合?
    因为我看了下您这里举的例子,似乎只是 get 单个任务的结果,:
    ```
    ret = task.delay()
    ret.get()

    ```
    因为我执行完这一批 task 需要有个信号,如果不是的话,您原本的意思是每个 task 会有多个脚本,然后还要用到多线程聚合后再返回该 task 以结果么?

    鄙人比较笨,再次 v 币感谢下,希望能最后给予下解答,谢谢!
    akmonde
        8
    akmonde  
    OP
       2018-08-27 09:14:30 +08:00
    @pekingzcc @monsterxx03
    非常感谢两位,此前没有去仔细看 chord,光在这上面纠结了,很惭愧,现在应该能解决原来的问题了。
    另外,参考了这篇文章:
    ```
    https://blog.csdn.net/preyta/article/details/54313047
    ```
    ----------------
    我想问问两位:
    ----------------
    如果仍延续原来每个 task 里面,多线程跑多个脚本(或者循环之类的)。在每个 task 里面,再使用这篇文章里讲的 chunks - 将大量任务分解为小块任务,会不会加快速速度。
    我知道每个 worker 可以同时跑多个 task,这个以前试过,只是有点好奇这样是否也可行。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1184 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 23:20 · PVG 07:20 · LAX 15:20 · JFK 18:20
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.