Flask - socketio 출력 지연 문제 해결 방안
Flask - Socketio 는 Flask 의 프레임 워 크 에서 SOcketIO 서 비 스 를 직접 구축 할 수 있 도록 합 니 다. 실현 방식 은 매우 간단 합 니 다. 기본 적 인 메시지 수신 응답 의 예 입 니 다.
from flask import Flask, request, make_response, jsonify, session
from flask_cors import CORS
from flask_socketio import SocketIO
'''=============================='''
'''flask web server config'''
'''=============================='''
app = Flask(__name__, static_url_path='')
app.config['SECRET_KEY'] = 'secret!'
cors = CORS(app,resources={r"/*":{"origins":"*"}}) # Restful CORS CORS
sio = SocketIO(app)
'''websocket '''
@sio.on('message', namespace='/ws')
def ws_message(data):
ask = {'result':'OK'}
sio.emit('message_back', json.dumps(ack), namespace='/ws')
'''restful , json'''
@app.route('/api', methods=['GET'])
def api_message():
resp = make_response(jsonify({'result':'OK'})
return resp
def main():
pass
if __name__ == '__main__':
main()
sio.run(app, port=8092, host='0.0.0.0', use_reloader=False, debug=False)
while True:
time.sleep(10) #
간단 한 응용 프로그램 에서 app 과 websocket 은 동시에 공존 할 수 있 습 니 다.서버 가 병렬 모드 에 있 을 때, 예 를 들 어 서버 가 여러 스 레 드 를 통 해 socketio emit 메 시 지 를 보 낼 때 다음 과 같은 방식 을 간단하게 사용 합 니 다.
import threading
thread_send_msg = threading.Thread(task_send_msg)
thread_send_msg.start()
def task_send_msg():
while True:
time.sleep(1)
msg
sio.emit('message', json.dumps(msg), namespace='/ws')
socketio 의 전송 간격 은 모델 의 지연 이 나타 나 고 간격 도 1 초 에 한 번 씩 보 내 는 것 이 아니 라 는 것 을 알 게 될 것 입 니 다.
그럼 multiprocessing 을 사용 할 수 있 습 니까?
import multiprocessing
proc_send_msg = multiprocessing.Process(task_send_msg)
proc_send_msg.start()
def task_send_msg():
while True:
time.sleep(1)
msg
sio.emit('message', json.dumps(msg), namespace='/ws')
테스트 결 과 는 여전히 문제 가 발생 할 수 있 으 며, 심지어 fllask 서비스 가 전혀 응답 하지 않 을 수도 있다.
그래서 문제 가 뭐 예요?
documentation 과 stackoverflow 프로 그래 밍 을 찾 아 본 결과 socketio 내부 에서 협 정 작업 스케줄 을 사용 하기 때 문 입 니 다. 이렇게 하면 emit 의 행 위 를 스 레 드 나 프로 세 스 내 에 두 었 을 때 동시에 emit 의 충돌 문 제 를 해결 하지 못 했 기 때 문 입 니 다.우 리 는 coroutine 의 스케줄 링 모드 자체 로 돌아 가 야 한다.여기 서 gevent 를 사용 하여 자신의 수요 에 따라 eventlet 또는 다른 모듈 을 사용 할 수 있 습 니 다.gevent 병행 모드 도 간단 합 니 다.
task_1():
gevent.sleep(1)
print 'running task 1'
task_2():
gevent.sleep(1)
print 'running task 2'
gevent.addall([
gevent.spawn(task_1),
gevent.spawn(task_2)
])
상기 작업 은 gevent 에서 부화 (spawn) 두 개의 협 정 을 한 다음 에 각 협 정 은 1 초 에 gevent. sleep () 를 통 해 gvent 를 다른 협 정 에 사용 하도록 하 는 것 이다.이 모드 를 통 해 emit 동시 다발 사건 을 다음 과 같이 수정 합 니 다.
socketio_msg_queue = Queue(maxsize=5000)
def gtask_sockeio_emit():
while True:
gevent.sleep(0.01)
try:
msg = socketio_msg_queue.get_nowait()
except:
continue
print msg
sio.emit(msg['on'], json.dumps(msg['data']), namespace='/ws/rt_market')
gevent.addAll([
gtask_socketio_emit
])
이 코드 에서 우 리 는 각 스 레 드 에서 발생 할 수 있 는 emit 사건 을 하나의 대기 열 로 보 낸 다음 에 통 일 된 협 정 내 에서 보 내 는 대기 열 을 사용 했다.
그럼 문 제 는 해결 되 었 습 니까?아직...
emit 를 협정 에 넣 은 후에 우 리 는 flask 프레임 워 크 가 응답 하지 않 는 것 을 발견 했다.
가장 큰 가능성 은 gevent 자체 가 프로 세 스 의 자원 을 선점 하여 restful 이 응답 하지 못 하 게 하 는 것 입 니 다.
첫 번 째 로 생각 나 는 방법 은 fllask 를 하나의 프로 세 스 에 넣 는 것 입 니 다. 예 를 들 어 다음 과 같 습 니 다.
def task_start_flask():
'start the rest and ws server'
sio.run(app, port=80, host='0.0.0.0', use_reloader=False, debug=False)
proc_flask = multiprocessing.Process(target=task_start_flask)
proc_flask.start()
결국 양쪽 모두 접근 할 수 없 게 되 었 다.
분석 후, socketio 구축 은 웹 을 통 해 요청 해 야 하기 때문에 fllask 가 어디서 시작 되 는 지, 모든 socketio 통신 이 어디 에 쌓 여 있 는 지, 따로 시작 하 는 것 은 문 제 를 해결 할 수 없 을 것 으로 추정 된다.그래서 두 번 째, 우 리 는 모든 내용 을 gevent 에 넣 고 통일 적 으로 스케줄 링 합 니 다.
gevent.joinall([
gevent.spawn(gtask_sockeio_emit),
gevent.spawn(task_start_flask),
])
이로써 문 제 는 해결 된다.
후기: SocketIO 는 프로 토 콜 자체 에서 효율 이 높 지 않 습 니 다. 더 높 은 효율 이 필요 하 다 면 원생 websocket 을 사용 하 는 것 이 좋 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.