LoginSignup
15
15

More than 3 years have passed since last update.

Node.jsでもUNIXドメインソケットを使いたい

Last updated at Posted at 2019-09-09

はじめに

Node.jsで使うことのできる通信方式としては、TCPソケット、ストリーミングIPCエンドポイント、そしてHTTPインターフェースです。HTTPインターフェースに関しては、実際にはTCPソケットとして動いているので、実質前の2つになります。
では、TCPソケットとストリーミングIPCエンドポイントの違いは何でしょうか?

TCPソケットは、TCP/IPの上でソケットを用いて行う通信方式です。
一方のストリーミングIPCエンドポイントは、IPC(Inter-Process Communication)の下、同一マシーン内でプロセス間通信をストリーミングで行う通信方式です。

このストリーミングIPCエンドポイントをUNIX上で実現されている技術が、『 Unix domain sockets 』です。

UNIXドメインソケットとは?

ローカルで開かれたソケットファイルを通じて、サーバー側とクライアント側とで通信を行う方法です。
Node.jsでは適用されていませんが、一般的には unix:// でURLが始まります。

TCPで行う通信と異なり、ローカルファイルを指定して通信を行うため、ドメインの解決や外部通信をしません。
そのため、TCPに比べ速いです。
その検証に関しては、 Performance Analysis of Various Mechanisms for Inter-process Communication をご覧ください。

『TCPソケット』の接続イメージ
『UNIXドメインソケット』の接続イメージ

使ってみよう!

この記事のサンプルプログラムは unix-domain-socket にあります。

UNIXドメインソケットは、Node.jsのビルドインモジュールの net の中で提供されています。
そのため、この記事では net を主に用いてプログラムを書いていきます。
Net | Node.js

送信側

以下のようなプログラムを作成しました。

import net from 'net';

// UNIXドメインソケットのコネクションを作成する
// net.createConnectionの引数にファイルを指定するとUNIXドメインソケットで繋がる
const client = net.createConnection('/tmp/unix.sock');
client.on('connect', () => {
  console.log('connected.');
});
client.on('data', (data) => {
  console.log(data.toString());
});
client.on('end', () => {
  console.log('disconnected.');
});
client.on('error', (err) => {
  console.error(err.message);
});
client.write('hello');

受信側

以下のようなプログラムを作成しました。

import net from 'net';
import fs from 'fs';

// サーバーを設定
const server = net.createServer((connection) => {
  console.log('connected.');
  connection.on('close', () => {
    console.log('disconnected.');
  });
  connection.on('data', (data) => {
    console.log(data.toString());
  });
  connection.on('error', (err) => {
    console.error(err.message);
  });
  connection.write('unix domain socket');
  connection.end();
});

// ソケットファイルを削除(存在するとlistenできない)
try {
  fs.unlinkSync('/tmp/unix.sock');
} catch (error) {}

// UNIXドメインソケットでlistenする
server.listen('/tmp/unix.sock');

実行してみる

ともに同じ仮想サーバー内で実行しています。
左側は送信側で、右側は受信側です。
UNIXドメインソケットの実行状況

おわりに

このUNIXドメインソケットは、ローカルマシーン内でプロセス間で通信を行う場合に効果を発揮します。
例えば、KubernetesのPod内のコンテナ間で通信を行う場合に使うことができます。

ボリュームを共有してマウントすることで通信ができるので、ドメインの名前解決に縛られることが無くなります。
ポートで通信を行う場合と比べて制限を受けない部分もあるので、一度使ってみてはどうですか?

15
15
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
15