nodejs 中间件 反向代理 接口转发

背景

随着后端业务系统的增加,纵向需求不断扩展,一个业务系统已经无法满足需求了,衍生出多个业务系统,对外暴露的ip、端口就可能有多个,此时不方便外部接口调用,有些特殊行业客户出于安全性考虑不发提供多个对外端口,对外只能提供一个IP一个端口。
这时中间件就产生了!

概念

中间件是一种独立的系统软件服务程序,分布式应用软件借助这种软件在不同的技术之间共享资源,中间件位于客户机服务器的操作系统之上,管理计算资源和网络通信。
一个统一过滤请求的中间层,这就是中间件。

用途

中间件常见的用途有:

  • IP过滤
  • 防爬虫
  • 解析请求
  • 合并接口
  • 合并端口
  • cookie处理
  • 参数校验
  • 权限校验
  • 异常处理
  • 负载均衡
  • 反向代理
    这样业务系统就可以关注点集中在业务层,隔离这些基础设施,让开发者专注于业务以提高开发效率。

技术选型

  • 高并发
  • 传输快
  • 非阻塞(NIO)
    常用的有nodejs、netty、go

案例demo

这里以nodejs为例,实现接口反向代理和合并端口功能
功能描述:
有两个业务系统:财务系统(financeSys)、用户系统(userSys),
分别部署到:
财务系统(financeSys):http://192.168.0.2/find
用户系统(userSys):http://192.168.0.3/login
对外暴露的接口分别是:
http://www.xxx.com/financeSys/find
http://www.xxx.com/userSys/login
对外暴露的接口格式为:http://www.xxx.com/系统名/业务URL,中间件系统根据请求地址的系统名来转发到对应的业务系统中
这时在www.xxx.com这个服务器上部署一个中间件,
收到http://www.xxx.com/financeSys/find的请求时转发到财务系统(financeSys)http://192.168.0.2/find
收到http://www.xxx.com/userSys/login的请求时转发到用户系统(userSys)http://192.168.0.3/login

架构图

图片.png

Nodejs项目分析

  • 使用的第三方框架
    koa: 网络框架,用来搭建服务
    koa2-proxy-middleware:反向代理处理框架
    log4js:日志框架
  • 配置转发的关系的映射文件
{
	"RequestLog": true, // 是否打印请求日志
	"ResponseLog": true, // 是否打印响应日志
	"ServerPort": 80, // 中间件服务端口,即对外暴露的接口端口
	"financeSys": "http://192.168.0.2", // 财务系统(financeSys)的转发地址
	"userSys": "http://192.168.0.3" // 用户系统(userSys)的转发地址
}
  • 根据url中的系统名找到映射文件中配置的业务系统
    如:/financeSys/find -> http://192.168.0.2
router: function(req) {
				const path = req.url;
				let pathArray = path.split("/");
				let projectContext = pathArray[1];
				// let suffix = path.substring(projectContext.length + 1, path.length);
				let serverUrl = config[projectContext];
				if (serverUrl != undefined && serverUrl != null) { // 配置文件已经配置转发路由
					let proxyServer = serverUrl;
					return proxyServer;
				} else { // 没有配置路由转发
					if (config.RequestLog) {
						logger.info("No Proxy Server!! path:" + path);
					}
					return {
						protocol: req.protocol,
						host: req.host,
						port: config.ServerPort
					};
				}
			}
  • 重写业务url
    如:/financeSys/find -> /find
			pathRewrite: function(path, req) {
				let pathArray = path.split("/");
				let projectContext = pathArray[1];
				let suffix = path.substring(projectContext.length + 1, path.length);
				return suffix;
			}
  • 打印请求/响应日志
			onProxyReq: async function(proxyReq, req, res) {
				// 禁用缓存
				proxyReq.setHeader('Cache-Control', 'no-cache');
				// 标示接口赖在中间件
				proxyReq.setHeader('Interface-From', 'Middleware');
				if (config.RequestLog) {
					logger.info("---------------------------- Request ----------------------------");
					logger.info('URL:' + req.url);
					logger.info('Method:' + req.method);
					logger.info('Headers:' + JSON.stringify(req.headers));
					const responseBodyStr = await getBody(req)
					logger.info("Body:" + responseBodyStr);
				}
			},
			onProxyRes: async function(proxyRes, req, res) {
				if (config.ResponseLog) {
					logger.info("---------------------------- Response ----------------------------");
					logger.info("URL:" + req.url);
					const responseBodyStr = await getBody(proxyRes)
					logger.info("Body:" + responseBodyStr);
				}
			}
  • 过滤某些请求不转发
app.use(async (ctx, next) => {
	let url = ctx.originalUrl;
	if (url != '/favicon.ico') {
		await next();
	} else {
		let resStr = JSON.stringify({})
		ctx.response.body = resStr;
	}
});

项目运行打包

npm install
  • 本地调试,可以使用Visual Studio/Visual Studio Code/WebStorm等ide打开,运行命令npm run start
npm run start
  • 打包,运行命令npm run build,会在dist文件夹生成一个index.js文件
  • 运行,在安装有nodejs环境的机器上运行打包生成的index.js文件,运行命令node index.js
node index.js

项目源码:https://codechina.csdn.net/it1/project-middleware.git

如果觉得可以就点个👍吧,欢迎粉丝收藏,土豪打赏,您的关注就是我们创作的动力!

读者有什么想看的相关技术篇章,欢迎评论留言!

QQ交流群:908058499

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

狼人残风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值