使用 Node.js 实现反向代理以分发多后端服务

作者:接口漫谈时间:2026-10-28 12:54:32浏览:235

本文介绍如何利用 Node.js 的 node-http-proxy 模块构建反向代理服务器,解决单一 80 端口下多类型后端服务(如 PHP、ASP、JSP)的共存与分发问题。通过域名路由将请求转发至不同后端端口,实现低成本的多项目托管方案,并提供了具体的代码配置示例及注意事项。

多后端服务端口分发需求

时下不少场景,都是申请一个 VPS 主机来托管运行 Web 项目的,小弟我也不例外,购买了一个小型的 Win 03 VPS 使用着。在使用的过程中,面临一个问题,就是同一类型的服务端环境还好——但如果是一个 PHP、一个 ASP、 一个 JSP 的三种类型的服务端项目并存着,该怎么分配唯一的 80 端口呢?因为商业 WWW 网站的话,往往只能占用 80 端口,——当然,如果只是做服务的话,如接口之类的,使用其他端口就不会与 80 端口冲突了。许多开发者都会面临到 80 端口这个问题,并且实际情况会受到成本的限制。因为单独为一个项目就买一个 VPS,也不太经济、不太合算,管理起来也不方便。于是,我们就应该好好考虑一下,怎么在提供一个 80 端口的情况下,分发到多种服务端那里去,让不同的主机执行各自的 Web 项目。

反向代理技术原理

这一需求可以通过“反向代理(Reverse Proxy)”技术实现。反向代理的核心功能之一便是端口分发。具体做法是以域名为路由依据:例如,将 AA.com 域名的请求分发至 PHP 的 82 端口执行,将 BB.com 域名的请求分发至 ASP 的 83 端口执行。端口号仅为示例,可根据实际需求任意配置。其本质是接收来自 80 端口的请求,经过处理后转发至对应的后端服务,通俗而言即“左手转右手”的过程。

选择 Node.js 作为代理服务器

提及反向代理,Nginx 往往是首选,但本文暂且忽略 Nginx,转而采用 Node.js 来实现。Node.js 同样具备单线程和事件循环的特性,适合此类任务。选择 Node.js 的原因在于:首先,使用 JavaScript 进行服务端编程比 Nginx 的配置或 Lua 脚本更符合个人偏好;其次,对 Node.js 更为熟悉,使得配置过程更加顺手。

实现该功能的关键包是 node-http-proxy。安装该包需执行以下命令:

Node.js 反向代理实现步骤


npm install http-proxy

安装完成后,新建一个名为 proxy.js 的文件,并写入以下代码:


var http = require('http'), httpProxy = require('http-proxy');

// 新建一个代理 Proxy Server 对象
var proxy = httpProxy.createProxyServer({});

// 捕获异常
proxy.on('error', function (err, req, res) {
 res.writeHead(500, {
 'Content-Type': 'text/plain'
 });
 res.end('Something went wrong. And we are reporting a custom error message.');
});

// 另外新建一个 HTTP 80 端口的服务器,也就是常规 Node 创建 HTTP 服务器的方法。
// 在每次请求中,调用 proxy.web(req, res config) 方法进行请求分发Create your custom server and just call `proxy.web()` to proxy
// a web request to the target passed in the options
// also you can use `proxy.ws()` to proxy a websockets request
//
var server = require('http').createServer(function(req, res) {
 // You can define here your custom logic to handle the request
 // and then proxy the request.
 var host = req.url;
 host = url.parse(host); host = host.host;
 
 console.log("host:" + req.headers.host);
 console.log("client ip:" + (req.headers['x-forwarded-for'] || req.connection.remoteAddress));
 
 proxy.web(req, res, { target: 'http://localhost:8080' });
});

console.log("listening on port 80")
server.listen(80);

使用代理服务器的代价主要是资源消耗增加,具体表现为 CPU 运算量的提升。

在使用中可能遇到的问题包括:无法直接指定文件夹路径,例如 proxy.web(req, res, { target: 'http://jb51.net:81/foo/' }); 这种写法可能无法按预期工作。

作者最新文章