通过http.createServer()
方法创建一个HTTP服务器后,要通过调用创建的server
实例的listen()
方法监听传入的连接。listen()
方法可以监听一个TCP
端口,或一个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
在网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个Socket
。Socket
可以被定义描述为两个应用通信通道的端点,一个Socket
端点可以用Socket
地址(地址IP
、端口
、协议
组成)来描述。Socket
作为一种进程通信机制,操作系统会分配唯一一个Socket
标识,这个标识与通讯协议有关(不仅限于TCP
或UDP
)。
Unix Domain Socket
Unix Domain Socket
并不是一个实际的协议,它只在同客户机和服务器通信时使用的API,且一台主机与在不同主机间通信时使用相同的API。
Unix Domain Socket
有以下特点
Unix Domain Socket
使用的地址通常是一个文件- 在同一主机通讯时,传输速率是不同主机间的两倍
Unix Domain Socket
套接字描述符可以在同一主机不同进程间传递Unix Domain Socket
套接字可以向服务器提供用户认证信息
TCP Socket
与Unix 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; }