基于 Nodejs 的网关设计

发布于 1周前 作者 sinazl 来自 nodejs/Nestjs

基于 Nodejs 的网关设计

最近需要设计一个 node.js 的网关.

简单来说就是一个 nodejs 的反向代理.

Spring 全家桶 里面有 Zuul 这个看门口

网上都看了一圈 有这么几个选择

  • express-gateway
  • http-proxy

为了避免造轮子,想跟诸位老哥请教一下.

说一下我们基本的需求:

  • 高性能
  • 可以发送静态页面
  • 可以鉴权认证 初步 准备 JWT + oauth2 (我们 gateway 是有状态的,我们会把 token 给存在 Redis 里面 然后给客户一个 session, 避免用户之间用 token 来调用我们后端)
  • 可以加 CSRF
  • 根据权限来过滤请求

再次 谢过


21 回复

可以参考下 @acheetahk/request 的 fastProxy


有问题可以给我提 issue

这个看到了 不过不是 nodejs 的技术栈 虽然性能厉害

humm 回头我好好看一下 不想造轮子
生产环境用一个开源项目要看下后面的生态的 还有文档等等. 感谢🙏

node.js 没有单独做网关的开源包,有的只是零散的方法,目前来看方案有三种:

1. 使用 http request pipe 重写,代理到目标服务器完成请求转发
2. 使用 websocket 的方式完成请求转发 # https://docs.nestjs.cn/7/websockets # 参考资料来自 nest.js
3. 使用 grpc 自己实现 interface + 协议 + 传输格式 + 异常信息定义 # https://docs.nestjs.cn/7/microservices?id=grpc #参考资料来自 nest.js

我是用的 1 + 3,1 适合常规业务直接调用,3 适合服务间调用(指多个服务调用,或者形成了调用链)

我建议你先吧目前你觉得合适的方案跑成 demo,做一下性能压测和各方面的评估。

感谢你先 现在看了好几套方案 明天跟同事一起聊一下看看要不要自己做一个. express Gateway 里面坑有些多 开源的大多数不够活跃 最后一次提交都在 1 年多了. 加上一些 redis 的库也没法用. 初步考虑可能用 koa2. 毕竟 Gateway 主要是为了性能来的. 您的建议很好👍

∫好了 现在 开始撸轮子了,基于 https://github.com/chimurai/http-proxy-middleware 鉴权用 passport

已经上线了!

回来看看,发现还好自己撸了一个……

给您发了 github 上标的邮件

老哥 有啥设计思路可以借鉴借鉴吗? 刚好想搞一个

希望能咨询下哈哈,TEY5Nzg5NTUwMzM=

我这里是 Gateway 也鉴权了, 等于这里是个有状态的. 根据请求来判断 某些人是否有某些权限. 如果 token 快要过期了 也是 gateway 续签,token 还有十秒 就续签. 这样请求不会出奇怪的问题. 还有个好处 这样客户端没有 token.

是来了一个 http 请求 然后 gateway 在发出去一个 http 请求吗? 然后 gateway 保留状态。

#18 不是,是这样的。gateway 的作用 可以把来的流分给不同的 微服务,每个微服务有不同的权限。正常没有状态的做法是每个微服务会鉴权一下。鉴权的方式是通过 token 鉴权的。 思想是 gateway 处理请求的统一鉴权,因为 gateway 相当于一个反向代理,这里收到的 http 请求 你知道 这个请求有没有鉴权。如果你搞过前端,有的是通过访问 /current/user 这样来确定你是否登录。但是用了 gateway 任何请求都知道你有没有登录。因为 gateway 那边会存一个 session 这个 session 用来记录用户的状态。不知道明白了没有 ?

嗯嗯 我懂你说的, 我是做前端的, 想问下: 可以把来的流分给不同的 “微服务” 这个微服务在这里是指后端的 http 接口是吧

基于Node.js的网关设计通常涉及构建一个能够处理HTTP请求、进行路由转发、执行安全认证、日志记录以及可能的请求修改的中间层。以下是一个简化的设计思路和示例代码:

设计思路

  1. 请求接收:使用Express或Koa等框架接收HTTP请求。
  2. 路由转发:根据请求的路径和方法,将请求转发到相应的后端服务。
  3. 安全认证:实现JWT或其他认证机制,验证请求的合法性。
  4. 日志记录:记录请求的详细信息,包括请求时间、IP地址、请求路径等。
  5. 请求修改:在转发前,可以对请求进行必要的修改,如添加请求头、修改请求体等。

示例代码(使用Express)

const express = require('express');
const axios = require('axios'); // 用于转发请求
const jwt = require('jsonwebtoken'); // 用于JWT认证
const fs = require('fs'); // 用于日志记录

const app = express();

// 中间件:日志记录
app.use((req, res, next) => {
    fs.appendFileSync('gateway.log', `${new Date().toISOString()} ${req.method} ${req.url}\n`);
    next();
});

// 中间件:JWT认证
app.use((req, res, next) => {
    const token = req.headers['authorization'];
    if (!token || !jwt.verify(token, 'your_secret_key')) {
        return res.status(403).send('Forbidden');
    }
    next();
});

// 路由转发
app.use('*', async (req, res) => {
    const response = await axios({
        method: req.method,
        url: 'http://your-backend-service/' + req.url,
        data: req.body
    });
    res.send(response.data);
});

app.listen(3000, () => {
    console.log('Gateway is running on port 3000');
});
回到顶部