惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

罗磊的独立博客
Apple Machine Learning Research
Apple Machine Learning Research
The Cloudflare Blog
WordPress大学
WordPress大学
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
博客园 - 叶小钗
博客园 - 聂微东
阮一峰的网络日志
阮一峰的网络日志
腾讯CDC
博客园 - 三生石上(FineUI控件)
V
V2EX
有赞技术团队
有赞技术团队
V
Visual Studio Blog
小众软件
小众软件
Jina AI
Jina AI
酷 壳 – CoolShell
酷 壳 – CoolShell
博客园 - Franky
量子位
T
Tailwind CSS Blog
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
P
Palo Alto Networks Blog
Cisco Talos Blog
Cisco Talos Blog
I
Intezer
Project Zero
Project Zero
A
Arctic Wolf
P
Privacy International News Feed
V
Vulnerabilities – Threatpost
L
Lohrmann on Cybersecurity
S
Securelist
C
Cybersecurity and Infrastructure Security Agency CISA
C
CXSECURITY Database RSS Feed - CXSecurity.com
T
Tor Project blog
Hacker News - Newest:
Hacker News - Newest: "LLM"
S
Security @ Cisco Blogs
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Google DeepMind News
Google DeepMind News
N
News and Events Feed by Topic
TaoSecurity Blog
TaoSecurity Blog
L
LINUX DO - 热门话题
G
GRAHAM CLULEY
Help Net Security
Help Net Security
N
News | PayPal Newsroom
W
WeLiveSecurity
G
Google Developers Blog
Microsoft Security Blog
Microsoft Security Blog
Engineering at Meta
Engineering at Meta
MongoDB | Blog
MongoDB | Blog
C
Check Point Blog

mephisto.cc

修复rime-ice无法弹出候选框的问题 开机滚动字体显示优化 个人网站安全防护 树莓派上部署Vaultwarden 使用goaccess实时分析Caddy日志 个人网站监控 Hugo全站AVIF记 Linux下尝试使用Godot开发小游戏 Arch linux dae 透明代理 Airflow接管galler-dl下载任务 如何使用gallery-dl批量下载图像 Arch核显下如何愉快玩Dota2和CS2 Arch/labwc 环境网络相关设置 Rime添加dota2词库 Arch 重装记录 Supertuxkart iOS版终于发布了 打造自己的流媒体音乐服务 剪切板管理工具clipcat推荐 MangoHud性能监控 微信小程序开发记 Rofi试用 解决Arch下VSCode无法输入中文的问题 独立窗口管理器下无法录屏问题处理 上海市二手房成交数据监控 OpenLDAP监控 Arch linux如何顺畅连接蓝牙设备 使用Git和Ansible管理配置文件 Arch Linux SSL VPN 客户端配置 Arch linux下iNode客户端的安装和使用方法 券商费率调整记 迷你主机组装记 Labwc更换定制皮肤 树莓派跑分流代理 实用自动代理配置示例 九年老鼠标复活记 Openvpn示例 Mac下如何旋转webp图片 如何隐藏Vscode中Markdown PDF插件的头部内容 解决Linux下网络配置无法变更保存的问题 labwc环境启用wlogout Ubuntu下新官方微信尝鲜 简单检测用户是否开启广告屏蔽 Atuin ZFS下卡顿问题解决 Wine安装64位微信 Fish 和 Atuin使用记 Fastapi简单实现临时下载链接 Fastapi微信公众号开发简要 Hugo根据语种展示不同内容 如何修复Waybar微信图标错误 信封加密简要 Linux环境下维护公众号记录 快速隐藏和呼出终端 Wayland环境自动切换壁纸 SuperTuxKart 试玩 简单抓取雪球股票快讯 为什么你的kill命令不能列出信号表 Wine安装微信保姆教程 Hysteria科学上网简要 Ubuntu 23.10 钉钉无法启动解决方法 网站导航栏防止插入Adsense自动广告 Linux环境按键检测 Hugo文末添加最后修改时间 Wayland环境ksnip无法复制问题解决 我眼中的股票市场 Caddy简单图片防盗链 greetd和regreet使用教程 Wayland环境下截图加后期修改 Wayland 环境下gif录屏 Firefox的一些有趣功能 Ubuntu 切换系统语言 Firefox 标题栏高度调整 网站添加回到顶部功能 Hugo自定义字体 Labwc 便捷配置 Wofi使用教程 窗口管理器labwc使用记 文件共享软件Dufs推荐 Hugo静态站点接入Adsense广告 Fcitx5配置详解 Ubuntu安装chrome的方法总结 一种Xterm.js的全屏方案 Google网址收录api Python示例 手机听离线音乐 Snipe it资产导入 应用启动器yofi使用配置 Snipe it资产管理系统安装使用 Ubuntu开机启动加速 Vue3 vite TypeScript跨域等相关设置 Ubuntu手动升级Libreoffice Ubuntu设置alacritty为默认终端 简体文章批量转换为繁体 使用Inkscape调整svg图片大小 实用命令 使用mitmproxy给手机app抓包 Python中rstrip方法细解 Github同主机多仓库部署deploy key问题处理 Linux安装最新版本Python KeePassXC使用教程 Ubuntu 22.10连接蓝牙耳机报错br-connection-profile-unavailable解决方法 Caddy日志配置轮转和格式化
简单获取celery任务实时结果
2024-08-04 · via mephisto.cc

在日常web开发工作中,往往有一些需要长时间运行的后台任务,比如说发送邮件、上传文件、编译软件等。当这些任务完成时,前端页面能及时变更。

让有用户能感知到任务已经完成,或者说有变化。

本文列举一个最简单的实现方案:

socket.io前端 + flask-socketio + celery

1. 前端页面

创建一个test.html文件,内容如下。

 1<!DOCTYPE html>
 2<html lang="en">
 3<head>
 4    <title>Socket.IO Test</title>
 5    <script src="https://cdn.socket.io/4.0.1/socket.io.min.js"></script>
 6    <script>
 7        var socket = io.connect('http://127.0.0.1:5000');
 8
 9        socket.on('connect', function() {
10            console.log('Connected:', socket.id);
11        });
12
13        socket.on('disconnect', function() {
14            console.log('Disconnected');
15        });
16
17        socket.on('test event', function(data) {
18            console.log('Received message:', data);
19            // alert(data.message);
20        });
21
22        function sendMessage() {
23            var message = document.getElementById('message').value;
24            socket.emit('my_event', message);
25        }
26    </script>
27</head>
28    <body>
29        <input type="text" id="message">
30        <button onclick="sendMessage()">Send</button>
31    </body>
32</html>

页面很简单,从cdn上导入socket.io.min.js文件,和后端建立ws连接,还有简单的发送消息按钮,收到信息后,会在打印相关信息,对新手十分友好。

如果你还是不理解,可以关注公众号留言,我尽力解答。

2. Flask 后端

创建一愕app.py文件,装好各种依赖包。

 1
 2from flask import Flask
 3from flask_socketio import SocketIO
 4from celery import Celery
 5
 6app = Flask(__name__)
 7app.config['SECRET_KEY'] ='my_secret_key'
 8socketio = SocketIO(app, cors_allowed_origins="*",message_queue='redis://',logger=True, engineio_logger=True)
 9
10# Celery 配置
11app.config['CELERY_BROKER_URL'] ='redis://localhost:6379/0'
12app.config['CELERY_RESULT_BACKEND'] ='redis://localhost:6379/0'
13
14celery = Celery(app.name, broker=app.config['CELERY_BROKER_URL'],backend=app.config['CELERY_RESULT_BACKEND'])
15celery.conf.beat_schedule = {
16    'task_interval': {
17        'task': 'app.long_running_task',
18        'schedule': 10.0, # 时间间隔
19    }
20}
21
22@celery.task
23def long_running_task():
24    # 模拟任务执行
25    import time
26    time.sleep(8)
27    # 任务完成后通过 SocketIO 发送通知
28    socketio.emit('test event', { 'message': 'Job done! time is: {}'.format( time.ctime() ) })
29
30@socketio.on('connect')
31def handle_connect():
32    print('连接成功')
33
34@socketio.on('disconnect')
35def handle_disconnect():
36    print('Client disconnected')
37
38if __name__ == '__main__':
39    socketio.run(app, host='0.0.0.0', port=5000)

上述代码每隔10秒钟,执行long_running_task这个模拟任务,任务完成后,会给前端发消息,告诉工作已完成,并打印下当前时间。

关键点为:

1socketio = SocketIO(app, cors_allowed_origins="*",message_queue='redis://',logger=True, engineio_logger=True)

跨域设置,开启了dbug,方便在后端查看收发信息,message_queue 配置项也很重要,没仔细看文档的人,在生产环境部署时,debug能力差的可能倒腾一天 也不知道为何前端没有收到信息。

3. 测试环境运行

前端运行: firefox test.html, 用浏览器打开test.html文件,再把调试窗口打开。

后端运行:

  • 运行服务端
 1(.venv) ➜  flask-socketio-celery python app.py
 2Server initialized for threading.
 3 * Serving Flask app 'app'
 4 * Debug mode: off
 5WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 6 * Running on all addresses (0.0.0.0)
 7 * Running on http://127.0.0.1:5000
 8 * Running on http://192.168.124.5:5000
 9Press CTRL+C to quit
10OSxZbltBcO8kRT9NAAAA: Sending packet OPEN data {'sid': 'OSxZbltBcO8kRT9NAAAA', 'upgrades': ['websocket'], 'pingTimeout': 20000, 'pingInterval': 25000}
  • 开启redis server
 1➜  ~ redis-server
 221407:C 04 Aug 2024 15:39:58.061 # WARNING Memory overcommit must be enabled! Without it, a background save or replication may fail under low memory condition. Being disabled, it can also cause failures without low memory condition, see https://github.com/jemalloc/jemalloc/issues/1328. To fix this issue add 'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command 'sysctl vm.overcommit_memory=1' for this to take effect.
 321407:C 04 Aug 2024 15:39:58.061 * oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
 421407:C 04 Aug 2024 15:39:58.061 * Redis version=7.2.5, bits=64, commit=00000000, modified=0, pid=21407, just started
 521407:C 04 Aug 2024 15:39:58.061 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
 621407:M 04 Aug 2024 15:39:58.061 * Increased maximum number of open files to 10032 (it was originally set to 1024).
 721407:M 04 Aug 2024 15:39:58.061 * monotonic clock: POSIX clock_gettime
 8                _._
 9           _.-``__ ''-._
10      _.-``    `.  `_.  ''-._           Redis 7.2.5 (00000000/0) 64 bit
11  .-`` .-```.  ```\/    _.,_ ''-._
12 (    '      ,       .-`  | `,    )     Running in standalone mode
13 |`-._`-...-` __...-.``-._|'` _.-'|     Port: 6379
14 |    `-._   `._    /     _.-'    |     PID: 21407
15  `-._    `-._  `-./  _.-'    _.-'
16 |`-._`-._    `-.__.-'    _.-'_.-'|
17 |    `-._`-._        _.-'_.-'    |           https://redis.io
18  `-._    `-._`-.__.-'_.-'    _.-'
19 |`-._`-._    `-.__.-'    _.-'_.-'|
20 |    `-._`-._        _.-'_.-'    |
21  `-._    `-._`-.__.-'_.-'    _.-'
22      `-._    `-.__.-'    _.-'
23          `-._        _.-'
24              `-.__.-'
25
2621407:M 04 Aug 2024 15:39:58.061 * Server initialized
2721407:M 04 Aug 2024 15:39:58.061 * Loading RDB produced by version 7.2.5
  • 运行celery beat
 1(.venv) ➜  flask-socketio-celery celery -A app.celery beat -l info
 2Server initialized for threading.
 3celery beat v5.4.0 (opalescent) is starting.
 4__    -    ... __   -        _
 5LocalTime -> 2024-08-04 15:41:43
 6Configuration ->
 7    . broker -> redis://localhost:6379/0
 8    . loader -> celery.loaders.app.AppLoader
 9    . scheduler -> celery.beat.PersistentScheduler
10    . db -> celerybeat-schedule
11    . logfile -> [stderr]@%INFO
12    . maxinterval -> 5.00 minutes (300s)
13[2024-08-04 15:41:43,989: INFO/MainProcess] beat: Starting...
14[2024-08-04 15:41:50,632: INFO/MainProcess] Scheduler: Sending due task task_interval (app.long_running_task)
  • 运行celery worker
 1(.venv) ➜  flask-socketio-celery celery -A app.celery worker -l info
 2Server initialized for threading.
 3
 4 -------------- celery@minipc v5.4.0 (opalescent)
 5--- ***** -----
 6-- ******* ---- Linux-6.10.2-arch1-1-x86_64-with-glibc2.40 2024-08-04 15:43:05
 7- *** --- * ---
 8- ** ---------- [config]
 9- ** ---------- .> app:         app:0x78e41973b140
10- ** ---------- .> transport:   redis://localhost:6379/0
11- ** ---------- .> results:     redis://localhost:6379/0
12- *** --- * --- .> concurrency: 16 (prefork)
13-- ******* ---- .> task events: OFF (enable -E to monitor tasks in this worker)
14--- ***** -----
15 -------------- [queues]
16                .> celery           exchange=celery(direct) key=celery
17
18
19[tasks]
20  . app.long_running_task
21
22[2024-08-04 15:43:05,949: WARNING/MainProcess] /home/mephisto/github/flask-socketio-celery/.venv/lib/python3.12/site-packages/celery/worker/consumer/consumer.py:508: CPendingDeprecationWarning: The broker_connection_retry configuration setting will no longer determine
23whether broker connection retries are made during startup in Celery 6.0 and above.
24If you wish to retain the existing behavior for retrying connections on startup,
25you should set broker_connection_retry_on_startup to True.
26  warnings.warn(
27
28[2024-08-04 15:43:05,954: INFO/MainProcess] Connected to redis://localhost:6379/0
29[2024-08-04 15:43:05,954: WARNING/MainProcess] /home/mephisto/github/flask-socketio-celery/.venv/lib/python3.12/site-packages/celery/worker/consumer/consumer.py:508: CPendingDeprecationWarning: The broker_connection_retry configuration setting will no longer determine
30whether broker connection retries are made during startup in Celery 6.0 and above.
31If you wish to retain the existing behavior for retrying connections on startup,
32you should set broker_connection_retry_on_startup to True.
33  warnings.warn(
34
35[2024-08-04 15:43:05,957: INFO/MainProcess] mingle: searching for neighbors
36[2024-08-04 15:43:06,962: INFO/MainProcess] mingle: all alone
37[2024-08-04 15:43:06,970: INFO/MainProcess] celery@minipc ready.
38[2024-08-04 15:43:06,971: INFO/MainProcess] Task app.long_running_task[324cef1b-a8e4-43b0-925d-9e28c841e3b5] received

4. 查看结果

懒得打字了,看截图。

socketio-flask

左侧为浏览器打开test.tml文件的调试情况,右侧顺时针转圈,依次为flask、redis、beat、worker。

左侧console里面每隔十秒钟,打印出了预期信息。

最后,每次码文章至少都要耗费2个小时,收益几乎为零,动力日渐消退。

新工作比以前忙, 更新频率只能调低,今天是周末(不信,看上面截图的时间),通常我都在打游戏,民工娱乐时间短,要恰饭的嘛!

还只能放弃娱乐时间来写这个不痛不痒的文章。如果对读者的有帮助或者有疑问,可关注公众号,也算是支持。

另外在生产环境部署的时候,比这个要复杂很多。

比如用vue3,当后端任务完成后,前端要立刻自动刷新页面,要用watch动态监测变化(轮询也是可以,只是比较丑);

后端部署,会设涉及到Nginx代理的配置,还有如果你用的gunicorn,没仔细读官方文档,配置不当可能倒腾很久,前端都收不到信息;

最离谱的是,当地你url写错的时候,socketio会把错误的url的一部分当作协议消息发送给后端,连接都没法建立。

这些细节写起来、解释起来可能又要几十分钟码字截图,个人觉得能用周末闲暇时间来写,已经是极限了,毕竟不赚钱的,付费问答倒是乐意。