Nginx/NChan 구성

Nginx/NChan 구성

제가 개발 중인 모바일 앱에서는 WebSocket을 사용하여 다양한 정보를 구독/게시합니다. 대부분의 경우 앱 측 웹소켓은 단순히 리스너입니다. 그러나 메시지를 게시하는 경우도 있습니다.

서버 측 Nginx 위에서 작동하는 [NChan][1] 조합을 사용하여 이 문제를 처리하고 있습니다. NChan의 정말 멋진 기능 중 하나는 웹소켓을 "다중화"하는 기능입니다. 즉, 여러 채널에서 게시/구독 기능을 사용할 수 있습니다. 모바일 앱을 만들 때 이는 깔끔함과 배터리 친화성을 향상시키는 데 큰 도움이 됩니다.

pubsub[NChan 문서][2]에 설명된 대로 다중화 채널을 설정했습니다.

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";
} 

index.php다른 서버에서는 서버 루트 폴더 읽기에서 PHP를 실행하도록 Nginx를 설정했습니다.

<?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

관련 정보