V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
leimao
V2EX  ›  Web Dev

如何协调 Flask 和其他不间断运行的 Background 程序?

  •  
  •   leimao · 2022-02-03 00:23:34 +08:00 · 2998 次点击
    这是一个创建于 803 天前的主题,其中的信息可能已经有所发展或是发生改变。

    各位好,小白(并不懂 Full Stack 和其他网络相关技术)在用 Flask 写一个很小的 web App 的时候有一些架构和技术上的疑问,请求帮助和解答。

    这个 Web App 很简单,是这样的。

    1. 它有一个数据库,这个数据库会被一个程序 A 24 小时不间断的更新。
    2. 程序 B 24 小时不间断的每隔一定时间对这个总是被更新的数据库进行 query ,然后生成一个 summary 。这个 summary 最好是在内存上的某个数据结构,方便其他程序读取。
    3. 程序 C ,也就是 Flask Web Server ,会根据用户的请求,返回 summary 中的一部分给用户。

    这三个程序 A ,B 和 C ,每一个用 Python 看起来都不难写。但是怎么把这三个东西有机结合起来,并且(用 gunicorn ?)部署,我有些困惑。原本觉得这不就是三个 thread 或者三个 process 么,放到 flask Python app 里,flask run 的时候这三个 thread 同时 asyn 的运行。但是看到 flask 本身在(用 gunicorn ?)部署的时候似乎不是很支持自定义的 async 的东西,似乎也不支持另外单独开一个 thread ,始终运行一个任务,就不是很清楚怎么把这三个东西揉在一起了。

    请有经验的同学给一些建议,谢谢。

    18 条回复    2022-02-03 11:46:18 +08:00
    ipwx
        1
    ipwx  
       2022-02-03 00:30:58 +08:00   ❤️ 1
    1. Python 没有真多线程,所以你这三个程序要多进程。
    2. 不需要愣是结合,单独运行 A 不香嘛?
    3. 至于 B ,你这 summary 丢进 redis 呗。
    zhijiansha
        2
    zhijiansha  
       2022-02-03 00:48:40 +08:00 via iPhone   ❤️ 1
    flask apscheduler 是不是可以实现?
    gstqc
        3
    gstqc  
       2022-02-03 01:22:15 +08:00   ❤️ 1
    3 个线程也可以的,只要性能满足要求
    不过实际应用中最好是分开 3 个进程,一套代码,多个 app 启动不同功能,这样写代码和部署起来都简单多了
    dayeye2006199
        4
    dayeye2006199  
       2022-02-03 02:37:23 +08:00   ❤️ 2
    分成 3 个部分比较好。

    a. 一个数据库 -- 这个负责不同程序之间的数据交换和存储
    b. 一个 celery 应用 -- 负责 1 和 2 这两个定时任务( https://docs.celeryproject.org/en/stable/userguide/periodic-tasks.html )。生成的 summary 写入 a 的数据库,加上一个生成时间戳;做的粗糙一点,甚至不用 celery 这样的任务队列,直接用 crontab 也可以(但需要处理失败重试等问题)
    c. 一个 flask 应用 -- 用户请求来了之后,负责去 a 里面的数据库,查出最新的 summary 返回给用户
    Livid
        5
    Livid  
    MOD
       2022-02-03 04:02:33 +08:00   ❤️ 1
    试试让所有的程序用这个来存储或者读取生成的 summary:

    https://redis.io/
    leimao
        6
    leimao  
    OP
       2022-02-03 04:58:52 +08:00
    @ipwx 感谢。

    1. 至少对程序 A 和 B 而言,他们不怎么吃资源,所以用三个假线程也无尚大雅。
    2. 目前我的确是在单独运行 A 。但是 B 和 C 必须“有机”的结合起来,这样效率可以高一些。不然最蠢的办法就是 B 定期往硬盘写个东西,C 再往硬盘里读。但是这样有点蠢。
    3. 我看看 Redis 这个东西是干什么的。
    leimao
        7
    leimao  
    OP
       2022-02-03 04:59:44 +08:00
    @zhijiansha 谢谢,我看看。
    leimao
        8
    leimao  
    OP
       2022-02-03 05:00:58 +08:00
    @gstqc 感谢。我也是这么想的,但是实际操作起来就不是很会了。
    leimao
        9
    leimao  
    OP
       2022-02-03 05:03:15 +08:00
    @dayeye2006199 感谢。感觉光靠数据库来进行数据交换有点不好。比如说有 1000 个用户同时请求同样的 summary ,这个数据库得被 query 1000 次,这样肯定不如直接从内存里直接读 summary 效率来的高?
    leimao
        10
    leimao  
    OP
       2022-02-03 05:03:43 +08:00
    @Livid 感谢。我看看学习一下 Redis 。
    Livid
        11
    Livid  
    MOD
       2022-02-03 05:10:13 +08:00
    如果涉及下面这些需求和场景的,基本上你都可以放心地用 Redis:

    1. 程序生成的结果,丢了也没关系(可以再由程序生成)
    2. 生成过程很复杂,但是一旦生成结束,可能会被不同的上下文反复使用
    3. 容量超过 1M 的复杂数据结构
    4. 没有必要一直存储的,可以给数据设置自动过期时间
    plko345
        12
    plko345  
       2022-02-03 10:26:39 +08:00 via Android
    我之前也这样需求,用多进程库实现
    plko345
        13
    plko345  
       2022-02-03 10:28:33 +08:00 via Android
    当时也考虑过 redis 什么的,但自己的东西不大,不想引入太多第三方工具,就自己实现了
    way2explore2
        14
    way2explore2  
       2022-02-03 11:29:56 +08:00
    @dayeye2006199 此乃正解。

    其实可以做三个不同 service ,甚至索性就三个 lambda
    ch2
        15
    ch2  
       2022-02-03 11:39:47 +08:00
    守护进程+内存缓存+定时任务
    dayeye2006199
        16
    dayeye2006199  
       2022-02-03 11:40:48 +08:00
    @leimao 1000 Read QPS 对正常的数据库都是毛毛雨;内存读写引入 redis memcache 这样的,也会徒增复杂度。
    leimao
        17
    leimao  
    OP
       2022-02-03 11:45:28 +08:00
    @plko345 程序 B 和 C 的交互,似乎还是需要依赖第三方的东西来实现。除非你像之前的朋友说的,程序 B 把 summary 写到 database 里去,然后程序 C 每次被请求就去 database 里找 summary 。但是我之前也提了一下这么做有点浪费读写和计算。
    leimao
        18
    leimao  
    OP
       2022-02-03 11:46:18 +08:00
    @dayeye2006199 好的,谢谢你的建议。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   5426 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 09:19 · PVG 17:19 · LAX 02:19 · JFK 05:19
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.