設定 Nginx/Nchan

設定 Nginx/Nchan

在我開發的行動應用程式中,我使用 WebSocket 來訂閱/發布一系列不同的資訊。在大多數情況下,應用程式端 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

相關內容