配置 Nginx/NChan

配置 Nginx/NChan

在我开发的移动应用中,我使用 WebSockets 订阅/发布一系列不同的信息。在大多数情况下,应用端 WebSocket 只是一个监听器。但是,有时它也会发布消息。

服务器端我使用 Nginx 上的 [NChan][1] 组合来处理这个问题。NChan 的一个非常好的功能是能够“多路复用”websocket - 即在多个渠道上发布/订阅。在创建移动应用程序时,这对提高整洁度和电池友好性大有帮助。

正如 [NChan 文档][2] 中所述,我已经设置了多路复用pubsub通道

location ~ /pubsub/(\w+)/(\w+)/(\w+)/(\w+)/(\w+)$ 
{
 nchan_pubsub;
 nchan_channel_id "$1" "$2" "$3" "$4" "$5" "control";
 nchan_publisher_upstream_request /alter;
}

上面第三行,chan_publisher_upstream...将传入的请求转发pub到另一台服务器

location = /alter 
{
 proxy_pass https://example.com;
 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;
 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
 proxy_set_header Upgrade $http_upgrade;
 proxy_set_header Connection "upgrade";
} 

在另一台服务器上,我已设置 Nginx 来运行 PHP,index.php服务器根文件夹中的内容如下:

<?php
 trigger_error(json_encode(getallheaders()));//a test to see that the proxy pass is actually 
 happening
 
 header("HTTP/1.1 304 Not Modified");
 //if successful should cause the incoming request to be published without changes
 
 //header("HTTP/1.1 204 No Content");
 //when enable will suppress the incoming request (optionally after doing some server-side
 //stuff with the incoming request data

 //header("HTTP/1.1 200 OK"); 
 //echo 'New Content!';
 //when enabled should replace the incoming requestt content with the new one 
 ?>

据我所知,我已经非常认真地遵循了 NChan 的说明。但是,当我尝试使用此配置在现在定义的pubsub频道上发布时,客户端连接意外被关闭。为了执行此测试,我使用了一些简单的 JavaScript

    var socket;

    function connectPubSub()
    {
     socket = new WebSocket("wss://app.server.url/pubsub/personal/cause/beacon/grid/chat");
     socket.onopen = whenOpen;
     socket.onmessage = whenMessage;
     socket.onclose = whenClose;
     socket.onerror = whenError;
    } 

    function whenOpen(e){console.log("[open] Connection established");}

    function whenMessage(event){console.log(`[message]:${event.data}`);}

    function whenClose(event) 
    {
     if (event.wasClean) 
      alert(`[close] Connection closed cleanly, code=${event.code} reason=${event.reason}`);
      else console.log('[close] Connection died');
    }

    function whenError(error){console.log(`[error] ${error.message}`);}

    function sendMessage(msg){socket.send(msg);}

此时,当我尝试发出以下命令时

connectPubSub();
sendMessage('Hello world!');

我得到如下所示的输出

[open] Connection Established
Websocket connection to app.server.url failed:Close received after close

错误事件如下图

bubbles: false
cancelBubble: false
cancelable: false
composed: false
currentTarget: WebSocket {url: "wss://app.server.url/pubsub/personal/cause/beacon/grid/chat", 
readyState: 3, bufferedAmount: 0, onopen: ƒ, onerror: ƒ, …}
defaultPrevented: false
eventPhase: 0
isTrusted: true
path: []
returnValue: true
srcElement: WebSocket {url: "wss://app.server.url/pubsub/personal/cause/beacon/grid/chat", 
readyState: 3, bufferedAmount: 0, onopen: ƒ, onerror: ƒ, …}
target: WebSocket {url: "wss://app.server.url/pubsub/personal/cause/beacon/grid/chat", 
readyState: 3, bufferedAmount: 0, onopen: ƒ, onerror: ƒ, …}
timeStamp: 83208.4250000189

这让我很困惑。我以为我只需按照 NChan 文档并在多路复用pubsub通道上发布消息,然后在代理服务器上检查消息内容(JSON),然后再决定要做什么

  • 让消息通过(发出 HTTP 304)
  • 采取服务器端操作然后隐藏消息(发出 HTTP 204)
  • 修改消息并发送(发出 HTTP 200)

我对 Nginx 配置指令的了解不够全面,这可能会让我失望。我做错了什么?


我现在已经能够确定这里发生了什么。问题的根源似乎是

proxy_pass https://example.com;

指令。如果我将其更改为

proxy_pass https://example.com/index.php;

一切按预期进行。但是,我仍然不清楚为什么会发生这种情况。我的 Nginx 默认配置文件顶部有以下几行

server 
{
 root /path/to/root;
 index index.php;

 server_name example.com;

我认为上面的第三行,index index.php几乎就是我需要告诉 Nginx 在任何文件夹/子文件夹位置执行 index.php 的全部内容。显然不是这样?[1]:https://nchan.io [2]:https://nchan.io/#getting-started

相关内容