最近在使用 Flask-SocketIO 想实现实时跟踪 celery
的任务日志(每个任务一个日志文件)的功能。 在本地运行,开了两个窗口,第二个窗口会输出自己的日志,第一个窗口会输入自己的加后一个窗口的日志。类似后续每开的一个窗口,前面的窗口都会 append
此窗口的日志。
client
import sys import socketio client = socketio.Client(recOnnection=False) @client.on('log', namespace='/cdc') def on_log(args): print(args['data']) def send(log_path): try: client.connect('http://127.0.0.1:5000', namespaces='/cdc') client.emit('log', {'log_path': log_path}, namespace='/cdc') except KeyboardInterrupt: try: sys.exit(0) except SystemExit: sys.exit(1)
server
sio = flask_socketio.SocketIO(async_mode=async_mode) @sio.on('log', namespace='/cdc') def log(data): thread = sio.start_background_task(scan_log, data['log_path'], None, flask.request.sid) def scan_log(log_path, app=None, client_id=None): counter = 0 with open(log_path, 'r') as f: while True: line = f.readline() if not line: sio.sleep(0.1) continue counter += 1 sio.emit('log', {'data': line.strip()}, namespace='/cdc', to=client_id)
各位有没有遇到类似的情况?或者有什么大概的思路?
之前启动 server 的方式是默认的 flask run
后续尝试了用 gunicorn + eventlet 的方式启动 gunicorn --worker-class eventlet -w 2 "app:create_app()"
然后两个 client 的 log 输出就正常了。
![]() | 1 dassh 2021-04-14 11:18:09 +08:00 每个日志应该有一个独立的标识,然后 on_log 里对标识进行判断,如果是对应的才 print |
![]() | 2 Alexf4 OP @dassh 这里每一个日志都是独立的(每个任务都生成对应的日志) 所以 client on log 会接受 server 多个线程分别 emit 的数据? 我这个 scan log 不是用多个线程进行的么,另外 emit 的时候用 to 这个参数也区别了 client 的发送的呀 |
![]() | 3 dassh 2021-04-14 11:47:37 +08:00 sio.on('log', ...)就表示你订阅了所有 server emit 的'log'的事件,所以你需要进行过滤判断,to 参数我没用过哈,给你一种解决方案 ``` @client.on('log', namespace='/cdc') def on_log(args): if args['log_path'] == sys.argv[1] #这里的 sys.argv[1]就是你传入 log_path 的地址 print(args['data']) def scan_log(log_path, app=None, client_id=None): ... sio.emit('log', {'data': line.strip(), 'log_path': log_path}, namespace='/cdc', to=client_id) ``` |
![]() | 4 Latin 2021-04-14 12:55:08 +08:00 同一楼加 uuid 过滤 |