Сценарий: у меня есть здравый веб-сервер, обслуживающий простой веб-сайт. Сайт представляет собой большую таблицу данных в формате html с поддержкой шаблонов vue. Поскольку записи в таблице меняются каждые несколько минут, данные передаются через websocket при изменении. Около 2000 пользователей одновременно. Я попытался реализовать архитектуру pub / sub.
Проблема: мои веб-сокеты закрываются, как только мой обработчик sanic возвращается. Я мог бы иметь петлю внутри, чтобы держать обработчик открытым. Но держать 2000 открытых обработчиков звучит как плохая идея ... Также открытые обработчики ведут себя странно. Один поток или небольшой пул потоков должен делать эту работу. Возможно, я неправильно понял санитарную документацию и нуждаюсь в совете по дизайну.
Вещи, которые я пробовал:
- увеличить время ожидания, чтобы оно было достаточно высоким
- попробовать различные другие настройки веб-сокета в Sanic
- позвольте моей стороне клиента js вернуть ложное сообщение ( Закрытие Javascript сразу после открытия )
- установить для ссылки ws значение null после ее передачи
Индекс Sanic Webserver:
@app.route('/')
async def serve_index(request):
return await file(os.path.join(os.path.dirname(__file__), 'index.html'))
JS Index.html:
var app = new Vue({
el: '#app',
data() {
manydata0: 0,
manydata1: 0,
ws: null,
}
},
methods: {
update: function (json_data) {
json = JSON.parse(json_data);
this.manydata0 = json['data0'];
this.manydata1 = json['data1'];
}
},
created: function () {
this.ws = new WebSocket('ws://' + document.domain + ':' + location.port + '/reload');
messages = document.createElement('ul');
this.ws.onmessage = function (event) {
console.log("new data")
app.update(event.data);
return false;
};
document.body.appendChild(messages);
this.ws.onclose = function (event) {
console.log("closed :(")
};
Обработчик веб-сокета Sanic Webserver (1-я версия, сокеты сразу умирают):
@app.websocket('/reload')
async def feed(request, ws):
#time.sleep(42) # this causes the websocket to be created and closed on client side 42 seconds after my request
await ws.send(Path(json).read_text()) # serve initial data
connected_clients.append(ws) # subscribe to websocket list. another thread will read list entries and serve them updates
Обработчик веб-сокетов Sanic Webservers (2-я версия, Обработчик блокирует другие обработчики запросов)
@app.websocket('/reload')
async def feed(request, ws):
mod_time = 0
while True:
try:
stat = os.stat(json)
if mod_time != stat.st_mtime:
await ws.send(Path(json).read_text())
except Exception as e:
print("Exception while checking file: ", e)
# this stops the server to handle other @app.routes like css, fonts, favicon
Обработчик веб-сокетов Sanic Webservers (3-я версия, ненужный recv ())
@app.websocket('/reload')
async def feed(request, ws):
mod_time = 0
while True:
try:
stat = os.stat(json)
if mod_time != stat.st_mtime:
await ws.send(Path(json).read_text())
await recv() # if the client sends from time to time all is fine
except Exception as e:
print("Exception while checking file: ", e)
Последние два фрагмента кода мало чем отличаются. Я добавляю ws.recv () и отправляю подходящие вещи со стороны клиента (например, с интервалом), тогда все работает. Затем отправляются css, шрифты и favicon. Но это не может быть предназначено, не так ли? Это не должно хорошо масштабироваться, верно?
В целом, это не имеет особого смысла для меня. Что я недопонимаю?