我试图用django,apache和socket.iobuild立一个网站。 感谢一些教程和其他stackoverflow的问题,我设法让一切工作,除了一个严重的滞后,发生在短时间内发送多个socket.io消息。
我在Apache中configuration的代理后面运行一个node.js socket.io服务器。 消息从socket.io客户端发送到socket.io服务器,也将转发到django,我要注册事件处理程序。 例如,我想触发一个事件,每次客户端join某个房间,通过socket.io发送一些初始数据。
Django也可以将请求发送到socket.io服务器,以触发socket.io事件(如emit),将消息发送到所有或某些socket.io客户端。
要发送和接收socket.io消息,我使用http长轮询。
这个消息转发到Django,似乎减慢了socket.io通信相当多。 例如,我实现了一个简单的echo工具,像这样工作:
客户端— send message – > apache代理 – > socket.io服务器— http POST —> django – >事件处理程序(将消息发送回客户端)— http POST —> socket.io服务器 – > apache代理 – >客户端
这工作正常,如果我只发送一条消息。 但是如果我在很短的时间内发出大量的信息,就会有越来越大的滞后。 如果我只连续发送10条消息,总共有5秒的延迟,直到最后一条回显消息返回给客户端。 如果我发送更多的消息,我会得到连续收到3-4个回显消息的效果。 之后,下一个徽章到达之前,停顿约2秒钟。
这不会发生,如果我不转发消息到Django,但直接发送回来的socket.io服务器内。
当然可以预料,这个额外的组件会使事情稍微放慢一些,但是这个延迟似乎相当严重。
那么我做错了什么? 也许我的方法转发消息到Django本质上是错误的? 还是有一些configuration,我可以调整,以加快速度? 这个滞后来自哪里呢?
Apache 2.4.7
虚拟主机:
<VirtualHost *:80> ServerName www.example.com ProxyRequests off ProxyPass /socket.io http://localhost:8080/socket.io retry=0 ProxyPassReverse /socket.io http://localhost:8080/socket.io WSGIDaemonProcess www.example.com processes=1 threads=1 display-name=%{GROUP} WSGIProcessGroup www.example.com WSGIScriptAlias / /path/to/wsgi.py DocumentRoot /var/www/example.com/ </VirtualHost>
Node.js服务器
server.js
app = express(); server = http.Server(app); io = require("socket.io")(server); server.listen(8080); app.use(express.bodyParser()); // incoming emit from django will emit a message over socket.io app.post("/emit/", function (req, res) { var body = req.body, message = body.message; io.emit("message", message); res.send("everything is ok"); }); // forwarding incoming socket.io message to django function forward(type, data, sessionId) { var options, req; data.sessionid = sessionId; data = JSON.stringify(data); console.log(data); options = { rejectUnauthorized: false, host: "www.example.com", port: 80, path: "/socket/" + type + "/", method: "POST", headers: { "Content-Type": "application/json", "Content-Length": data.length } }; req = http.request(options, function(res){ res.setEncoding("utf8"); }); req.write(data); req.end(); } io.sockets.on("connection", function (socket) { var sessionId = socket.id; forward("connect", {}, sessionId); socket.on("disconnect", function () { forward("disconnect", {}, sessionId); }); socket.on("message", function(message) { forward("message", { message: message }, sessionId); }); socket.on("join", function (room) { socket.join(room); forward("join", { room: room }, sessionId); }); socket.on("leave", function (room) { socket.leave(room); forward("leave", { room: room }, sessionId); }); });
Django的
转发消息到socket.io
def emit(message): payload = {"message": message} headers = {"content-type": "application/json"} requests.post("http://127.0.0.1:8080/emit/", data=json.dumps(payload, cls=DjangoJSONEncoder), headers=headers, verify=False)
视图来处理socket.io消息:
class MessageView(View): def post(self, request, *args, **kwargs): data = json.loads(request.body) try: sessionid = data["sessionid"] message = data["message"] //fire function will trigger event handler fire("message", sessionid, {"message": message}) return HttpResponse("Everything worked :)") except Exception, e: return HttpResponseServerError(str(e)) @csrf_exempt def dispatch(self, *args, **kwargs): return super(MessageView, self).dispatch(*args, **kwargs)
注册消息事件处理程序:
@on_message def message_received(sessionid, data): //emit to all socket.io clients emit("someone has sent a message")
客户
io.js
socket = io.connect( "http://www.example.com:80", { "multiplex": false, "transports": ["polling", "xhr-polling", "jsonp-polling"] } );
下面的graphics还应该说明我是如何使单个组件相互通信的。
