Python消息队列之Huey

缘起:

之前在Python中使用最多的就是Celery, 同样的在这次项目中使用了Celery+eventlet的方式,但是由于具体执行的逻辑是使用的异步编写的, 当时就出现了一个问题,当使用httpx的AsyncClient发送一个网络请求的时候, 发生了阻塞, 导致整个程序无法完整执行. 于是就找替代方案, 于是这次就尝试使用了huey,最终可以实现, 但是为何Celery中执行会发生阻塞,Google中也有大佬提到了

 

github: https://github.com/coleifer/huey

特点:

- 简单

- 轻量

- 执行多种类型: redis,sqlite,file,memory

 

安装:

pip install huey

# 将redis作为队列broker
pip install redis

 

使用:

  1. 配置Huey实例。

  2. 使用@huey.task()装饰器来标记要执行的任务。

  3. 在你的应用程序中调用该任务,它将被添加到任务队列中。

  4. 运行一个worker来监听队列并执行任务。

 

task.py

from huey import RedisHuey
from redis import ConnectionPool

redis_pool = ConnectionPool(host='127.0.0.1', port=6379, db=10, password="密码")
huey = RedisHuey('app', connection_pool=redis_pool)


@huey.task()
def count_beans(num):
    for i in range(num):
        print(i)
        time.sleep(3)
    return 'count beans'

启动消费者:

huey_consumer task.huey -k process -w 4

# windows下
huey_consumer.exe task.huey -k process -w 4

# -k: 指定worker类型, thread(默认), greenlet, process(windows下不支持)
# -w: 指定worker的数量, 同时有多少个消费者同时工作

# 还有其他的一些参数, 可以使用--help查看
# -l: 指定日志文件
# -v: 显示日志

 

主业务,将任务投递到队列中main.py

from task import count_beans

if __name__ == '__main__':
    res = count_beans(10)
    print(res)

 

重试任务&定时任务

# tasks.py
from huey import RedisHuey, crontab
import logging
import time

# 配置huey实例
huey = RedisHuey('my_app', host='localhost')

# 设置日志
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

# 一个简单的任务
@huey.task()
def add_numbers(a, b):
    logger.info("Adding numbers: {} + {}".format(a, b))
    return a + b

# 带有失败重试的任务
@huey.task(retries=3, retry_delay=10)
def flaky_task():
    logger.info("Trying to perform a flaky task...")
    if random.choice([True, False]):
        raise ValueError("Oops! Something went wrong.")
    else:
        logger.info("Flaky task succeeded.")

# 定时任务:每天执行
@huey.periodic_task(crontab(minute='0', hour='3'))
def daily_task():
    logger.info("Running daily task.")
    # 执行一些需要每天运行的操作

# 以下代码是模拟的任务使用案例,在实际应用程序中通常不会包含在任务定义的模块中

# 模拟任务队列和执行
if __name__ == '__main__':
    import random
    # 模拟添加任务到队列
    for i in range(10):
        add_numbers(i, i*2)

    # 模拟执行任务队列中的任务
    for _ in range(10):
        flaky_task()

    # 模拟定时任务的调用,实际情况下应该由huey的调度器执行
    daily_task()

    # 这里我们模拟启动worker,实际上应当通过命令行启动
    # 命令:`huey_consumer.py tasks.huey`
    # 以下代码将会启动一个循环,模拟worker的行为
    while True:
        time.sleep(1)
        huey.flush()

 

注意点: 这里的定时任务,会使用自己的一个调度频率, 例如,每分钟执行, 并不是每分钟的0秒开始执行, 而是根据程序执行的时候,并且启动的时候会执行一次

 

 

 

 

整体使用感受,轻量,快速,清爽,还会有终端的时候,优雅处理方式

 

 

当然还有更多工具可以使用

Rq:

https://github.com/rq/rq

Mrq:

https://github.com/pricingassistant/mrq

 

posted @ 2023-12-28 09:15  X-Wolf  阅读(69)  评论(0编辑  收藏  举报