NGINXおよびNGINX PlusとNode.js、Socket.IOを使用する:WebSocket API

NGINX | 2014年11月19日

この記事では、NGINXおよびNGINX PlusをNode.jsとSocket.IOで使用する方法について説明します。以前公開した「WebSocketとNGINXを使用したリアルタイムWebアプリケーションの構築」の記事が好評だったため、今回はSocket.IOに関するドキュメントとベストプラクティスを引き続きご紹介します。

Node.jsおよびSocket.IOとともにNGINXを使用する理由

Socket.IOは、Node.jsアプリケーションの普及に伴い、広く利用されるようになったWebSocket APIです。オンラインゲームやチャットなどのリアルタイムアプリを簡単に構築できることで知られています。NGINX 1.3.13以降およびすべてのNGINX PlusリリースはWebSocket接続のプロキシをサポートしているため、Socket.IOを利用できます。WebSocketプロトコルでは、単一のTCP接続を介した全二重、つまり双方向の通信が可能です。

本番環境で稼働するアプリケーションは通常、ポート80(HTTP)、ポート443(HTTPS)、またはその両方を使用する必要があります。アプリケーションの複数のコンポーネントがユーザーとやり取りする場合や、ポート80のWebサーバーを使用して他のアセットを配信している場合、これが課題となることがあります。そのため、Socket.IOサーバーへのプロキシが必要となり、その実現にはNGINXが最適です。バックエンドアプリケーションのインスタンスが1つでも数百でも、複数のノードを使用する場合は、NGINXでアップストリームの負荷分散も行えます。

Socket.IOの設定

Node.jsをインストールするには、適切なディストリビューションをダウンロードします(または、パッケージマネージャーを使用してインストールします)。Socket.IOをインストールするには、npm install socket.ioコマンドを実行します。

この例では、リアルタイムアプリのSocket.IOサーバーがポート5000で稼働しているものとします。以下は、server.js Nodeアプリケーションファイルのテンプレートです。サーバーとして機能し、受信リクエストをSocket.IOサーバーが稼働する適切なポートにルーティングする基本的なプログラムです。

var io = require('socket.io').listen(5000); 
io.sockets.on('connection', function (socket) {
  socket.on('set nickname', function (name) {
    socket.set('nickname', name, function () {
      socket.emit('ready');
    });
  });
 
  socket.on('msg', function () {
    socket.get('nickname', function (err, name) {
      console.log('Chat message by ', name);
    });
  });
});

クライアントに配信されるファイル(例:index.html)に、次のようなJavaScriptコードを追加します。この例では、ユーザーのブラウザーとのWebSocketを作成するために、アプリケーションへの接続を要求します。

<script src="/socket.io/socket.io.js"></script>
<script>
     var socket = io(); // your initialization code here.
</script>

NGINXの設定

アップストリームの宣言

アプリケーションに複数のインスタンスがある場合、NGINXおよびNGINX Plusでは、ユーザーセッションの負荷を分散し、複数のノードに振り分けることができます。NGINXまたはNGINX Plusの設定にあるhttpコンテキスト内に、upstreamブロックを追加して、アップストリームグループのノードを定義します。

次の例に示すように、weightパラメーターをserverディレクティブに指定すると、そのサーバーに転送するトラフィックの割合を設定できます。ここでは、srv1.app.comが他のサーバーの5倍のセッションを受信します。NGINX Plusは、高度な負荷分散方式に加え、セッション永続化、ヘルスチェック、拡張ステータスレポート、負荷分散対象サーバーグループの動的な再構成を追加することで、NGINXのリバースプロキシ機能を拡張します。

# in the http{} configuration block
upstream socket_nodes {
    ip_hash;
    server srv1.app.com:5000 weight=5;
    server srv2.app.com:5000;
    server srv3.app.com:5000;
    server srv4.app.com:5000;
}

仮想ホストの設定

サーバーのアップストリームグループを宣言したら、そこにトラフィックを転送するように仮想サーバーを設定する必要があります。少なくとも、proxy_passディレクティブを追加し、アップストリームグループ名を指定します。WebSocketプロトコルでは、HTTP/1.1で導入されたUpgradeヘッダーを使用するため、proxy_http_versionディレクティブも追加します。

server {
    server_name app.domain.com;
    location / {
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_http_version 1.1;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
        proxy_pass http://socket_nodes;
    }
}

静的ファイルの場合は?

静的アセットを配信するには、NGINXでリクエストをアップストリームのNode.jsインスタンスにプロキシできますが、ほとんどの場合、NGINXから直接配信する方が効率的です。

上記のserver_nameディレクティブとserverブロックを組み合わせることで、次のlocationブロックは、http://app.domain.com/assets/内のコンテンツに対するクライアントリクエストに、ローカルの/path/to/assetsディレクトリからコンテンツを配信して応答するようNGINXに指示します。さらに、静的ファイルの処理を最適化したり、ニーズに合ったキャッシュの有効期限を設定したりできます。

location /assets {
    alias /path/to/assets;
    access_log off;
    expires max;
}

トラブルシューティング

次のエラーが表示される場合は、NGINX 1.3より前のバージョンを実行している可能性があります。WebSocketはNGINX 1.3.13以降でサポートされています。

WebSocket connection to '...' failed: Error during WebSocket handshake: 'Connection' header value is not 'Upgrade': keep-alive socket.io.js:2371

関連情報

NGINX Plusをお試しいただくには、今すぐ30日間の無料トライアルを開始するか、ユースケースについてお問い合わせください。


共有
タグ: API, Node.js, 2014, Tech, F5 NGINX

関連するブログ記事

チュートリアル:NGINXを使用してアプリケーション向けにOpenTelemetryを構成する
NGINX | 2024/01/18

チュートリアル:NGINXを使用してアプリケーション向けにOpenTelemetryを構成する

OpenTelemetryを使用してNGINXサーバーの状態と健全性をより明確に把握することで、問題のトラブルシューティングを行い、Webアプリケーションのパフォーマンスを向上できます。

AkitaのNGINX Plus認定モジュールでAPIエンドポイントの問題を特定・修正
NGINX | 2023/05/31

AkitaのNGINX Plus認定モジュールでAPIエンドポイントの問題を特定・修正

Akita SoftwareのAPIオブザーバビリティ向け新しいNGINX Plus Certified Moduleを活用して、APIエンドポイントの問題をより迅速に特定し、修正できます。

JavaプロジェクトをスキャフォールディングしてKubernetesネイティブアプリを構築する方法
NGINX | 2023/02/09

JavaプロジェクトをスキャフォールディングしてKubernetesネイティブアプリを構築する方法

Red HatのシニアプリンシパルデベロッパーアドボケイトであるDaniel Oh氏が、Javaプロジェクトをゼロから構築するためのひな形を作成し、Kubernetesネイティブアプリケーションとしてビルドする方法を解説します。

F5 NGINXaaS for Azureのご紹介:Microsoft Azureでネイティブに利用できるSaaS型ロードバランシング
NGINX | 2022/05/24

F5 NGINXaaS for Azureのご紹介:Microsoft Azureでネイティブに利用できるSaaS型ロードバランシング

NGINXaaS for Azureは、NGINX PlusをAzureネイティブのSaaSとして利用できるサービスです。NGINXの設定を容易にリフト&シフトできるため、クラウド導入とモダンアプリの展開を加速できます。

SELinuxでNGINXおよびNGINX Plusを使用する
NGINX | 2018/08/17

SELinuxでNGINXおよびNGINX Plusを使用する

Red Hat Enterprise Linux(RHEL)および関連ディストリビューションでSecurity-Enhanced Linux(SELinux)を有効にすると、デフォルト設定によりNGINXとNGINX Plusの一部の操作が制限されます。この記事では、すべての機能を利用できるようにSELinuxの設定を変更する方法について説明します。

NGINX PlusによるAWS Auto Scalingグループの負荷分散
NGINX | 2017/03/06

NGINX PlusによるAWS Auto Scalingグループの負荷分散

新しいnginx-asg-sync統合ソフトウェアにより、NGINX PlusはAWS Auto Scalingグループの負荷を直接分散できるため、クラウドでの負荷分散がさらに柔軟になります