Websocket 環境架設 (以 Node JS 為 server)

    我一直是利用 Django 的框架架網站,且有跑其它應用程式的需求,所以一般環境都會建置在 Windows 的平台下。由於 Django 有提供 channel 模組來建立 Websocket 的應用,之前也有成功的搭配 apache 讓 websocket 跑起來,但只能在 Django 自帶的 server 下跑 websocket,一旦正式上線,總有一些搭配的元件問題無法解決。最近我重新整理網站,又再度碰到這個問題,不過這次我直接捨棄效能不彰的而又處處受限的 apache,改採 nginx 作為 web server,經過幾天的摸索,終於把 Websocket 跑起來,讓它可以在 SSL 加密連線的狀態下執行。以下就是本次架設網站的紀錄,作為往後的參考。

 

目前的環境是:

  Windows 10 + NodeJS V18.12.1 + Python 3.6 + Django 2.0 + Nginx 1.22.0

  (SSL 的申請是透過 Certbot 這個工具來申請 SSL,詳見之前文章的描述 https://blog1.jinvent.com.tw/network/)

  由於是搭建在現有的網頁上,如果原本的網頁執行沒有問題,那主要的環境問題就只剩下 NodeJS 跟 Nginx 的設定了。首先先看 Nginx 的設定,裡面關於 websocket 的部分,這裡主要是參考 https://www.nginx.com/blog/websocket-nginx/ 及 https://www.51cto.com/article/704378.html 瞭篇文章中的說明。下面是節錄我部份 nginx.conf 的內容:

 

upstream websocket {     
      server 127.0.0.1:xxxx;

      server 127.0.0.1:xxxx;
      keepalive 1000;
    }

    map $http_upgrade $connection_upgrade {  
        default upgrade;  
        '' close;  
    } 

 

    server {
        listen      80;
        listen [::]:80;
       
        #listen  443 ssl;
        return 301 https://blog1.jinvent.com.tw$request_uri;

        server_name  blog1.jinvent.com.tw;
        root  <path>/;

        ssl_certificate      <path>fullchain.pem;
        ssl_certificate_key  <path>privkey.pem;

        ssl_session_timeout 5m;
        charset utf-8;
       
        location / {
            proxy_pass http://websocket;
            proxy_redirect off;
            proxy_http_version      1.1;
            proxy_set_header        Upgrade                 $http_upgrade;
            proxy_set_header        Connection              "upgrade";
            proxy_set_header        Host                    $host;
            proxy_set_header        X-Real-IP               $remote_addr;
            proxy_set_header        X-Forwarded-For         $proxy_add_x_forwarded_for;
            proxy_set_header X-NginX-Proxy true;
        }
        
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }        

        location /static {
            alias  <static path>
        }      
    }

如果在加入 websocket 機制之前的網站都可以執行,那麼加入 websocket 後,其中主要需注意的就是藍字部分。而 upstream websocket 裡的 127.0.0.1:xxxx; 其實就是從 proxy_pass http://127.0.0.1:xxxx; 搬過去的。這個環節曾困擾我一兩天,所幸最後解決了,接下來關於 NodeJS 部分,待過幾天再來分享。