场景:我有一个服务于一个简单网站的 sanic 网络服务器。该网站基本上是一个带有 vue 模板支持的 html 中的大型数据表。由于表条目每隔几分钟就会更改一次,因此数据在更改时通过 websocket 传递。大约同时有2000个用户。我试图实现一个发布/订阅架构。
问题:一旦我的 sanic 处理程序返回,我的 websocket 就关闭了。我可以在里面有一个循环来保持处理程序打开。但是保持 2000 个处理程序处于打开状态听起来是个坏主意……而且打开的处理程序的行为也很奇怪。一个线程或一个小线程池应该可以完成这项工作。也许我把 sanic 文档弄错了,需要设计建议。
我尝试过的事情: - 将超时设置增加到足够高 - 在 sanic 中尝试各种其他 websocket 设置 - 让我的客户端 js 返回错误的 onmessage(Javascript websockets 在打开后立即关闭) - 在传递它后将 ws 引用设置为 null
Sanic Webserver 的索引:
@app.route('/')
async def serve_index(request):
return await file(os.path.join(os.path.dirname(__file__), 'index.html'))
Index.html 的 JS:
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 的 Websocket 处理程序(第一版,Sockets 立即死亡):
@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 的 Websocket 处理程序(第 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 的 Websocket 处理程序(第 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。但这不可能是故意的,不是吗?这不应该很好地扩展,对吧?
总而言之,这对我来说没有多大意义。我有什么误解?