Node.js HTTP Server监听Unix Socket套接字

 2016年04月16日    118     声明


通过http.createServer()方法创建一个HTTP服务器后,要通过调用创建的server实例的listen()方法监听传入的连接。listen()方法可以监听一个TCP端口,或一个Unix Socket套接字。


  1. server.listen()方法的几种形式
  2. UNIX Socket套接字
  3. Nignx对UNIX Socket的支持

1. server.listen()方法的几种形式

Node.js用非常简单的方式实现了HTTP服务器的创建。我们可以使用http.createServer()方法创建一个HTTP服务器:

const http = require('http');

// 创建一个 HTTP 服务器
var server = http.createServer( (req, res) => {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('hello world');
});

创建一个HTTP服务器,就创建一个http.Server类实例。HTTP服务器创建后,还需要调用server.listen()来启动服务器。启动服务器,有以下几种形式:

  • server.listen(port[, hostname][, backlog][, callback]):从一个TCP端口启动监听
  • server.listen(path, [callback]):从一个UNIX Socket套接字启动监听
  • server.listen(handle[, callback]):从一个包含socket套接字或文件描述符的handle对象启动监听

服务器创建后,我们可以像下面这样启动服务器:

// 从'127.0.0.1'和3000端口开始接收连接
server.listen(3000, '127.0.0.1', () => {
   console.log('在端口3000启动了服务器');
});
// 从 UNIX 套接字所在路径 path 上监听连接
server.listen('path/to/socket', () => {
    console.log('从socket路径启动了服务器');
})


2. UNIX Socket套接字

在上面示例中,使用port端口形式的监听,本质是监听TCP Socket端口。而使用path文件路径的方式,本质上是Unix Domain Socket(Unix域套接字)文件。

什么是Socket

在网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个SocketSocket可以被定义描述为两个应用通信通道的端点,一个Socket 端点可以用Socket地址(地址IP端口协议组成)来描述。Socket作为一种进程通信机制,操作系统会分配唯一一个Socket标识,这个标识与通讯协议有关(不仅限于TCPUDP)。


Unix Domain Socket

Unix Domain Socket并不是一个实际的协议,它只在同客户机和服务器通信时使用的API,且一台主机与在不同主机间通信时使用相同的API。

Unix Domain Socket有以下特点

  • Unix Domain Socket使用的地址通常是一个文件
  • 在同一主机通讯时,传输速率是不同主机间的两倍
  • Unix Domain Socket套接字描述符可以在同一主机不同进程间传递
  • Unix Domain Socket套接字可以向服务器提供用户认证信息


TCP SocketUnix Domain Socket

无论时TCP Socket套接字还是Unix Domain Socket套接字,每个套接字都是唯一的。TCP Socket通过IP端口描述,而Unix Domain Socket描述。

TCP属于传输层的协议,使用TCP Socket进行通讯时,需要经过传输层TCP/IP协议的解析。

Unix Domain Socket可用于不同进程间的通讯和传递,使用Unix Domain Socket进行通讯时不需要经过传输层,也不需要使用TCP/IP协议。所以,理论上讲Unix Domain Socket具有更好的传输效率。


3. Nignx对UNIX Socket的支持

经过以上介绍,我们可以了解到使用UNIX Socket方式效率更为优秀。在生产环境中,无论使用哪种方式一般都需要通过Nginx将来自指定域名的用户请求,定向到Node.js HTTP服务器中。

当使用TCP端口时,可以像下面这样配置:

server {
    listen       80;
    server_name  itbilu.com;
	
    location /
    {
        proxy_pass http://127.0.0.1:3000;  //要代理的实际端口(Node.js服务器端口),请求将被定向到此端口
        proxy_set_header   X-Real-IP            $remote_addr;
        proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
        proxy_set_header   Host                   $http_host;
        proxy_set_header   X-NginX-Proxy    true;
        proxy_set_header   Connection "";
        proxy_http_version 1.1;  
    }
    access_log  /var/log/nginx/access/itbilu.log;	
}
server {
    server_name www.itbilu.com;
    rewrite ^(.*) http://itbilu.com$1 permanent;
}

而使用UNIX Socket套接字文件时,可以像下面这样配置:

server {
    listen       80;
    server_name  itbilu.com;
	
    location /
    {
        proxy_pass /var/3w/itbilu.sock;  //要代理的实际Unix套接字文件(Node.js服务器监听的文件),请求将被定向到此路径
        proxy_set_header   X-Real-IP            $remote_addr;
        proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
        proxy_set_header   Host                   $http_host;
        proxy_set_header   X-NginX-Proxy    true;
        proxy_set_header   Connection "";
        proxy_http_version 1.1;  
    }
    access_log  /var/log/nginx/access/itbilu.log;	
}
server {
    server_name www.itbilu.com;
    rewrite ^(.*) http://itbilu.com$1 permanent;
}