Python websockets keepalive ping timeout; close frame не получен
У меня есть 20-50 пользователей, от которых мне нужна информация в реальном времени о том, подключены ли они к Интернету или имеют слабый Интернет
Я написал скрипт на Python, который проверяет соединение и отправляет информацию на веб-сервер в Django django-channels скрипт запускается в планировщике Windows с 9 утра до 6 вечера
Сценарий
async def main():
username = get_username()
url = "{}{}/".format(LOG_SERVER, username)
async with websockets.connect(url) as websocket:
# send info to server
while True:
try:
loop = asyncio.get_event_loop()
data = await loop.run_in_executor(None,
lambda:get_data(username))
await websocket.send(json.dumps(data))
await asyncio.sleep(30)
except websockets.ConnectionClosed as e:
print(f'Terminated', e)
continue
except Exception as e:
logging.error(e)
if __name__ == "__main__":
asyncio.run(main())
Пакет WebSockets: https://websockets.readthedocs.io/
Отправляйте информацию ping min, max, avg каждые 30 секунд. И убедитесь, что клиент подключен до тех пор, пока он подключен к серверу
Django Consumer
async def connect(self):
try:
self.username = self.scope['url_route']['kwargs']['username']
await database_sync_to_async(self.update_user_incr)(self.username)
except KeyError as e:
pass
......
async def disconnect(self, close_code):
try:
if(self.username):
await database_sync_to_async(self.update_user_decr)(self.username)
except:
pass
.......
Проблема в том, что скрипт python иногда блокируется с сообщением
sent 1011 (unexpected error) keepalive ping timeout; no close frame received
no close frame received or sent
и я не могу перезвонить автоматически
Как я могу держать соединение открытым или если оно закрывается, то снова открывается через небольшой процент времени, чтобы фронт-энд не мог изменять индикатор онлайн или офлайн
В итоге я воссоединился с чем-то подобным
async for websocket in websockets.connect(url):
try:
loop = asyncio.get_event_loop()
data = await loop.run_in_executor(None, lambda: get_data(username))
await websocket.send(json.dumps(data))
await asyncio.sleep(30)
except websockets.ConnectionClosed as e:
print(f'Terminated', e)
Но у меня была одна проблема, которая заключалась в корректировке состояния пользователя при каждом подключении. В этом случае вы можете использовать этот blog и этот answer для облегчения нагрузки на базу данных