我有一个运行在Heroku上的FastAPI服务器,使用python-socketio(5.3.0)来处理套接字连接。我有一个端点,当一个事件需要发送到某个套接字时,它就会被调用。我面临的问题是,事件并不是每次都会发出。它只会在某些情况下发出。它在本地运行得很好。
使用python-socketio的FastAPI服务器:
import uvicorn
from fastapi import FastAPI
import socketio
from socketio.asyncio_namespace import AsyncNamespace
import json
notification_users = {}
notification_sockets = {}
class NotificationConnector(AsyncNamespace):
async def on_connect(self, sid, *args, **kwargs):
print("User connected: ", sid)
async def on_disconnect(self, sid):
user_id = chat_sockets.get(sid)
print("User unsubscribed to chats: ", user_id)
connection_list = chat_users.get(user_id)
for socket in connection_list:
if(socket==sid):
connection_list.remove(sid)
if connection_list == []:
chat_users.pop(user_id)
else:
chat_users[user_id] = connection_list
chat_sockets.pop(sid)
async def on_subscribe(self, sid, data):
user_id = str(data.get("userID"))
print("User subscribed to notifications: ", user_id)
if user_id in notification_users.keys():
notification_users[user_id].append(sid)
else:
notification_users[user_id] = [sid]
notification_sockets[sid] = user_id
fast_app = FastAPI()
sio = socketio.AsyncServer(
async_mode='asgi',
cors_allowed_origins='*',
logger=True,
engineio_logger=True
)
sio.register_namespace(NotificationConnector("/notifications"))
app = socketio.ASGIApp(
socketio_server=sio,
other_asgi_app=fast_app,
socketio_path='/socket.io/'
)
@fast_app.post("/send")
async def send_notification(item: NotificationData):
user_id = item.userId
notification_content = json.dumps(item.notification)
socket_list = notification_users.get(user_id,[])
print(f"Socket list for {user_id} is {socket_list}")
for socket in socket_list:
print(f"Sending '{notification_content}' to socket Id: {socket}")
await sio.emit('notifications', notification_content, room=socket,
namespace="/notifications")
return {"success":True},200发布于 2021-06-09 21:08:02
这个问题与python-socketio无关。这似乎是由uvicorn处理全局变量的方式造成的。默认情况下,uvicorn会创建多个worker,并且每个worker都有自己的全局变量副本。
因此,当工作线程处理/send POST请求时,它的notification_users副本可能没有事件需要发送到的套接字id的信息。
将工作进程数更改为1已修复此问题。可能会考虑使用Redis而不是使用全局变量。
A better explanation of how uvicorn workers deal with global variables.
https://stackoverflow.com/questions/67903218
复制相似问题