2017-12-08 40 views
0

최근 Flask 앱에서 WebSocket 지원을 구현 중입니다. 프록시 5. uWSGI 2.0.13 +는 Gevent와 웹 소켓입니다 (원숭이로 1. 파이썬 2.7 2. 플라스크 + 플라스크-SocketIo 3. SocketIO (클라이언트 측) 4의 nginx를 :Flask-SocketIO + uWSGI. 뮬 (Mule) 작업자와 함께 내 보냅니다.

설정은 다음과 같습니다 - 패치 됨)

나는 소켓 연결을 사용할 수 있도록 관리했지만 UWSGI Workers, 단일 뮬 (특히 노새) 사이의 동기화에 어려움을 겪고있다.

나는 물건들을 감시하기 위해 UWSGI 노새를 열었고, 30 초마다 상태를보고하고, 연결된 클라이언트들에게 그것을 방송했다. 사용 가능한 작업자 (뮬 전용)에서 내 작업을 실행하도록 허용하는 경우 예전의 서버와 똑같은 프로세스 (예 : )로만 클라이언트에 도달 할 수 있습니다. 클라이언트 요청은 (400 PID) 및 설정된 소켓 연결로 제공됩니다 . 나중에 하나의 노새 작업이 동일한 작업자에 의해 처리되어 클라이언트가 Emit을 수신했습니다.) 다른 작업자가 해당 작업을 처리하면 클라이언트가 방출하지 않습니다.

단일 작업자 모드에서는 모든 것이 정상적으로 작동하지만 분명히 허용할만한 해결책입니다. 여기

일부 기술 정보입니다 : uwsgi.ini

[uwsgi] 
#application's base folder 
base = /home/ubuntu/application_test 

#python module to import 
app = manage 
module = %(app) 

home = %(base)/venv 
virtualenv = %(base)/venv 
pythonpath = %(base) 

#socket file's location 
socket = %(base)/application_test.sock 

#permissions for the socket file 
chmod-socket = 666 

#the variable that holds a flask application inside the module imported at 
line #6 
callable = app 

#location of log files 
logto = /var/log/uwsgi/%n.log 

processes = 10 

#WebSocket 
http-websockets = true 

gevent = 1000 
enable-threads = true 
die-on-therm = true 

vacuum = true 

mule=%(base)/application_test/uwsgi_mules/metrics_mule.py 

플라스크 앱

(...) 
from flask_socketio import SocketIO 
app = Flask(__name__) 
socketio = SocketIO(app,message_queue='redis://') 
(...) 

노동자 방출 코드

socket = SocketIO(message_queue='redis://') 

def broad_cast_server_info(state, health): 
    socket.emit('sys_state', health) 
    socket.emit('system_snapshot', state) 

클라이언트 측

 socket.on('sys_state', function(data){ 
      (...) 
      } 
     }); 

응답 응답으로 클라이언트 측 socket.emit을 사용하면 모든 것이 정상적으로 작동합니다.

노새에서는 단순히 socketio를 가져오고 emit을 호출하면 위에서 설명한 문제가 발생합니다. 그러나 내가 따르는 경우 : https://flask-socketio.readthedocs.io/en/latest/#emitting-from-an-external-process

나는 노새가 그 일을 실행할 때마다 redis 에러를 얻고있다.

File "/home/ubuntu/application_test/venv/local/lib/python2.7/site-packages/flask_socketio/init.py", line 365, in emit skip_sid=skip_sid, callback=callback, **kwargs) File "/home/ubuntu/application_test/venv/local/lib/python2.7/site-packages/socketio/server.py", line 228, in emit **kwargs) File "/home/ubuntu/application_test/venv/local/lib/python2.7/site-packages/socketio/pubsub_manager.py", line 66, in emit 'skip_sid': skip_sid, 'callback': callback}) File "/home/ubuntu/application_test/venv/local/lib/python2.7/site-packages/socketio/redis_manager.py", line 62, in _publish return self.redis.publish(self.channel, pickle.dumps(data)) File "/home/ubuntu/application_test/venv/local/lib/python2.7/site-packages/redis/client.py", line 2034, in publish return self.execute_command('PUBLISH', channel, message) File "/home/ubuntu/application_test/venv/local/lib/python2.7/site-packages/redis/client.py", line 673, in execute_command connection.send_command(*args) File "/home/ubuntu/application_test/venv/local/lib/python2.7/site-packages/redis/connection.py", line 610, in send_command self.send_packed_command(self.pack_command(*args)) File "/home/ubuntu/application_test/venv/local/lib/python2.7/site-packages/redis/connection.py", line 585, in send_packed_command self.connect() File "/home/ubuntu/application_test/venv/local/lib/python2.7/site-packages/redis/connection.py", line 489, in connect raise ConnectionError(self._error_message(e)) redis.exceptions.ConnectionError: Error -2 connecting to redispass:6379. Name or service not known.

PIP의 FREEZE :

alabaster==0.7.9 
amqp==2.1.1 
aniso8601==1.2.0 
appdirs==1.4.3 
astroid==1.4.8 
Babel==2.3.4 
beautifulsoup4==4.5.1 
certifi==2017.11.5 
chardet==3.0.4 
click==6.7 
decorator==4.0.11 
defusedxml==0.5.0 
dict2xml==1.5 
dicttoxml==1.7.4 
docopt==0.6.2 
enum-compat==0.0.2 
enum34==1.1.6 
eventlet==0.21.0 
Flask==0.12 
Flask-Login==0.4.0 
Flask-RESTful==0.3.5 
flask-restful-swagger-2==0.33 
Flask-Script==2.0.5 
Flask-SocketIO==2.9.2 
flask-swagger-ui==0.0.3 
Flask-WTF==0.14.2 
gevent==1.2.2 
greenlet==0.4.12 
html5lib==1.0b8 
hurry.filesize==0.9 
hypchat==0.21 
idna==2.6 
infinity==1.4 
intervals==0.8.0 
itsdangerous==0.24 
Jinja2==2.9.5 
jira==1.0.10 
lazy-object-proxy==1.2.2 
lxml==3.8.0 
MarkupSafe==1.0 
monotonic==1.4 
oauthlib==2.0.2 
olefile==0.44 
ordereddict==1.1 
packaging==16.8 
pbr==3.0.1 
pdfkit==0.6.1 
Pillow==4.0.0 
pql==0.4.3 
psutil==5.4.1 
py==1.4.34 
pymongo==3.4.0 
pyodbc==4.0.15 
pyparsing==2.2.0 
PyPDF2==1.26.0 
pypyodbc==1.3.4 
python-dateutil==2.6.0 
python-engineio==2.0.1 
python-memcached==1.58 
python-socketio==1.8.3 
pytz==2016.10 
reportlab==3.4.0 
requests==2.13.0 
requests-oauthlib==0.8.0 
requests-toolbelt==0.8.0 
six==1.10.0 
SQLAlchemy==1.1.6 
SQLAlchemy-Utils==0.32.14 
suds==0.4 
urllib3==1.22 
validators==0.11.3 
vine==1.1.3 
webencodings==0.5.1 
Werkzeug==0.12 
wrapt==1.10.10 
WTForms==2.1 
xmltodict==0.10.2 
WTForms-Components==0.10.3 

나는 다음과 같은 경우에 대한 빨간색했습니다 : - 원숭이 - 패치 Gevent - uwsgi은 (uWSGI 2.1에서 작동하는 가정)를 통해 초기 원숭이 패치 Gevent - Redis 큐 추가

Flask-SocketIO를 uWSGI 작업자와 동기화하여 작동시키는 다른 방법이 있습니까?

답변

0

에 연결할 수 있습니다.여기에 대한 대답은 다음과 같습니다.

다중 작업자 패턴은 Monkey-patchin과 Redis와 같은 docs에 설명 된 일부 메시지 대기열 메커니즘이 필요합니다. Redis 작업 만들기, 해결 된 문제 설명. 여기에 Redis 부분이 있습니다.

&TL; DN Redis 연결 문자열이 잘못되었습니다. Redis는 URL의 특수 문자를 지원하지 않으며 심지어 인코딩됩니다.

Flask-SocketIO에는 redis에 연결 문자열이 필요합니다 (코드 숨김은 redis.Redis.from_url() 메소드를 사용합니다). 나는 질문을 게시 내 레디 스 암호가 사실 URL은 다음과 같습니다 있도록 보호된다는 사실을 건너 뛰는에서 분명 실수를했습니다

'redis://[:RedIsPass#]@localhost:6379/1'

그러나 오류 메시지로 인해 암호 문자열의 정상화, 그리고로드에 약간 오해의 소지가 호스트로. 특수 문자와 소문자를 모두 제거합니다.

에 내가 연결 문자열을 수정 한

Error -2 connecting to redispass:6379. Name or service not known.

: 내가 또 다른 문제가 발생했습니다

'redis://:RedIsPass#@localhost:6379/1'

,이 때 "잘못된 IPV6"오류를 즉 MSG가 좋아 에러 나에게 제공합니다. #에 암호가 있기 때문에 발생했습니다. 슬프게도 Redis lib에는 URL 디코드가 없으므로 % 23을 # 23으로 바꾸어도 % 23이 일반 텍스트로 전달되고 비밀번호와 일치하지 않으므로 문제가 해결되지 않습니다. 서버에서 암호를 변경해야했습니다. 일반 비밀번호가 작동했습니다.

0

빨간 색으로 문제가있는 것 같습니다 설치하고 시작하셨습니까? 실행 redis-cli -h localhost -p 6379 만들 수 있는지 플라스크-socketIO 나에게 따라야 할 놀라운 우위를 안겨주었습니다 @shalbafzadeh 그것을

+0

c. Redis는 가동되어 있으며 기본 redis-py lib를 통해 완벽하게 액세스 할 수 있습니다. – Silverrose

+0

어떻게 든 redis에 연결하는 대신 : // localhost : 6379 socketio는 redispass에 연결을 시도합니다 : 6379 message_queue = 'redis : //'를 message_queue = 'redis : // localhost : 6379'로 변경하십시오. – shalbafzadeh

+0

따르도록 이끌어 라. 명성 – Silverrose