nchan
nchan copied to clipboard
nchan_publisher_upstream_request seems not to work fine with websocket
nginx version: nginx/1.13.8
server {
listen 8402 default_server;
access_log /var/log/nginx/pubsub.access.log;
error_log /var/log/nginx/pubsub.error.log debug;
location = /sub {
nchan_subscriber;
nchan_channel_id $arg_id;
}
location = /pubsub {
nchan_pubsub;
nchan_channel_id $arg_id;
nchan_publisher_upstream_request /upstream_pub;
}
location = /upstream_pub {
proxy_pass http://127.0.0.1:8402/test;
proxy_set_header X-Publisher-Type $nchan_publisher_type;
proxy_set_header X-Prev-Message-Id $nchan_prev_message_id;
proxy_set_header X-Channel-Id $nchan_channel_id;
proxy_set_header X-Original-URI $request_uri;
}
location /test {
default_type text/html;
return 200 "test........";
}
}
client side:
ws = new WebSocket("ws://192.168.0.200:8402/pubsub?id=1");
ws.onmessage = function(evt){console.log(evt.data);};
curl --request POST --data "http 1" http://192.168.0.200:8402/pub?id=1
output:
test........
curl --request POST --data "http 2" http://192.168.0.200:8402/pub?id=1
output:
test........
ws.send("aaa") // it seems that nginx don't work fine whenever
send
data,then i should reloadoutput:
test........
curl --request POST --data "http 3" http://192.168.0.200:8402/pub?id=1
request hangs
receive nothing
or
ws.send("aaa")
receive nothing
This should be fixed in Nchan version 1.2.0
Currently I'm facing something quite similar in nchan version: 1.2.7
. I'm using django+gunicorn(wsgi) as the backend. I'm making a simple chat app, with "box" as a container with multiple "channels" that can be accessed by users (aka "personalities")
upstream redis_server { nchan_redis_server redis://127.0.0.1/0; }
nchan_redis_pass redis_server;
server {
location ~ ^/box/(\w+)$ {
proxy_pass http://gunicorn_wsgi/api/box_connect/$1; //Uses accel-redirect to authenticate and connect to an internal pubsub
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
nchan_channel_group_accounting on;
location ~ ^/pubsub/b/(\d+)/c/(\d+)/p/(\d+)$ { # box_id / channel_id / personality_id
internal;
nchan_pubsub;
nchan_channel_group $1; #Group Boxes together
nchan_websocket_client_heartbeat PING PONG;
nchan_websocket_ping_interval 30;
nchan_publisher_upstream_request /upstream_pub; //If I comment this line, everything will be stable! (I just won't get new messages )
nchan_publisher_channel_id C$2P$3O; #Personal Publisher, Upstream should discard!
nchan_subscriber_channel_id C$2 C$2P$3; #Subscribe to public and Private Channel
}
location = /upstream_pub {
internal;
proxy_pass http://gunicorn_wsgi/api/new_message;
proxy_set_header Host $host;
proxy_set_header X-Publisher-Type $nchan_publisher_type;
proxy_set_header X-Prev-Message-Id $nchan_prev_message_id;
proxy_set_header X-Channel-Id $nchan_channel_id;
proxy_set_header X-Original-URI $request_uri;
}
}
server {
listen 127.0.0.1:8080;
location ~ ^/pub/b/(\d+)/c/(\d+)/p/(\d+)$ {
nchan_message_buffer_length 0;
nchan_message_timeout 1s;
nchan_publisher;
nchan_channel_id C$2P$3;
nchan_channel_group $1;
}
location ~ ^/pub/b/(\d+)/c/(\d+)$ {
nchan_message_buffer_length 1;
nchan_message_timeout 5s;
nchan_publisher;
nchan_channel_id C$2;
nchan_channel_group $1;
}
}
And this is the relevant part of django:
def box_connect( request, box_uid ):
... #Authentication takes place here...
response = HttpResponse()
response['X-Accel-Redirect'] = f'/pubsub/b/{channel.box_id}/c/{channel.id}/p/{personality.id}'
response['X-Accel-Buffering'] = 'no'
return response
And what happens, is that after like the first couple of successful publishes, no more messages can be published and the POST request will get stuck!
curl --request POST --data 'A Publish Message to all channel members' -H "Accept: text/json" "http://127.0.0.1:8080/pub/b/2/c/3"
a nginx reload / restart will fix the issue for about 2 seconds! my current "workaround" is to use a single channel for all users to publish to, and somehow identify them from their message.