当前位置: 首页 > article >正文

使用 Docker 和 PM2 构建高并发 Node.js API 网关

在现代 Web 开发中,构建高并发、高可用的 API 网关是一个常见的需求。本文将介绍如何结合 Docker 和 PM2 构建一个高性能的 Node.js API 网关,并深入探讨分布式限流器的原理与实现。


1. 背景与需求

1.1 高并发 API 网关的挑战

在高并发场景下,API 网关需要具备以下能力:

  • 高可用性:服务崩溃时能自动恢复。
  • 高性能:充分利用多核 CPU 处理请求。
  • 限流与防护:防止恶意请求压垮服务。
  • 环境一致性:开发、测试、生产环境行为一致。

1.2 技术选型

  • Node.js:轻量、高效,适合 I/O 密集型任务。
  • PM2:Node.js 进程管理工具,支持集群模式和自动重启。
  • Docker:容器化部署,确保环境一致性。
  • Redis:分布式限流器的共享存储。

2. 实现步骤

2.1 项目结构

api-gateway/
├── src/
│   ├── server.js         # 主入口
│   ├── auth.js           # 鉴权逻辑
│   ├── rate-limiter.js   # 限流逻辑
│   └── routes/           # 路由配置
├── ecosystem.config.js   # PM2 配置文件
├── Dockerfile            # Docker 构建文件
└── package.json

2.2 核心代码实现

2.2.1 高性能服务器 (server.js)
const express = require('express');
const auth = require('./auth');
const rateLimiter = require('./rate-limiter');const app = express();
app.use(express.json());// 全局中间件
app.use(rateLimiter); // 限流
app.use(auth);        // 鉴权// 路由配置
app.use('/user', require('./routes/user'));
app.use('/order', require('./routes/order'));// 健康检查端点
app.get('/health', (req, res) => {res.status(200).json({ status: 'ok', pid: process.pid });
});const PORT = process.env.PORT || 3000;
const server = app.listen(PORT, () => {console.log(`API Gateway running on port ${PORT} (PID: ${process.pid})`);
});// 优雅关闭
process.on('SIGTERM', () => {server.close(() => {console.log('Process terminated');});
});
2.2.2 分布式限流器 (rate-limiter.js)
const rateLimit = require('express-rate-limit');
const RedisStore = require('rate-limit-redis');
const redis = require('redis');// 创建 Redis 客户端
const redisClient = redis.createClient({host: 'localhost', // Redis 地址port: 6379         // Redis 端口
});// 限流配置
const limiter = rateLimit({windowMs: 1000, // 时间窗口:1秒max: 100,       // 每个客户端在窗口内最多允许100次请求message: 'Too many requests, please try again later.', // 超限时的响应消息standardHeaders: true, // 返回标准 HTTP 限流头(X-RateLimit-*)store: new RedisStore({client: redisClient, // 使用 Redis 存储计数expiry: 60,          // 计数器的过期时间(秒)prefix: 'rate-limit:' // Redis 键前缀})
});module.exports = limiter;

2.3 PM2 集群配置 (ecosystem.config.js)

module.exports = {apps: [{name: 'api-gateway',script: './src/server.js',instances: 'max',        // 根据 CPU 核心数启动进程exec_mode: 'cluster',    // 集群模式max_memory_restart: '1G',// 内存超限自动重启env: {NODE_ENV: 'production',REDIS_HOST: 'redis-host' // Redis 地址},log_date_format: 'YYYY-MM-DD HH:mm Z',error_file: '/dev/stdout', // 日志输出到标准输出out_file: '/dev/stdout'}]
};

2.4 Docker 容器化配置 (Dockerfile)

FROM node:18-alpine# 安装构建依赖
RUN apk add --no-cache python3 make g++WORKDIR /app
COPY package*.json ./# 生产依赖安装(包含PM2)
RUN npm install --production && \npm install pm2 -gCOPY . .# 使用 PM2 专属容器运行时
CMD ["pm2-runtime", "start", "ecosystem.config.js"]

3. 部署与扩展

3.1 构建并启动容器

# 构建镜像
docker build -t api-gateway .# 运行容器(限制资源)
docker run -d \--name gateway \-p 3000:3000 \--cpus 4 \          # 限制使用4核 CPU--memory 4g \       # 限制4GB内存--network my-network \api-gateway

3.2 水平扩展(Kubernetes 示例)

apiVersion: apps/v1
kind: Deployment
metadata:name: api-gateway
spec:replicas: 8        # 启动8个Podselector:matchLabels:app: gatewaytemplate:metadata:labels:app: gatewayspec:containers:- name: gatewayimage: api-gateway:latestresources:limits:cpu: "2" # 每个Pod限制2核memory: 2Giports:- containerPort: 3000

4. 分布式限流器的原理

4.1 核心原理

分布式限流器通过共享存储(如 Redis)在多个服务实例之间同步请求计数,从而实现对请求的全局限流。其核心思想是:

  1. 共享存储:使用 Redis 记录请求计数。
  2. 全局计数:所有服务实例共享同一个计数器。
  3. 时间窗口:基于时间窗口(如每秒、每分钟)统计请求数。

4.2 工作流程

  1. 客户端发起请求。
  2. 服务端检查 Redis 中该客户端的请求计数:
    • 如果计数未超限,允许请求并通过 Redis 增加计数。
    • 如果计数超限,拒绝请求并返回 429 Too Many Requests
  3. Redis 自动清理过期计数(基于 TTL)。

5. 总结

通过结合 Docker 和 PM2,我们可以构建一个高性能、高可用的 Node.js API 网关,并利用分布式限流器保护服务不被过多请求压垮。这种架构不仅适用于高并发场景,还能显著提升服务的可维护性和可扩展性。

关键优势

  • 高可用性:PM2 自动重启崩溃的进程,Docker 提供容器级恢复。
  • 高性能:PM2 集群模式充分利用多核 CPU。
  • 全局一致性:分布式限流器确保限流策略全局一致。
  • 环境一致性:Docker 镜像保证开发、测试、生产环境行为一致。

相关文章:

使用 Docker 和 PM2 构建高并发 Node.js API 网关

在现代 Web 开发中,构建高并发、高可用的 API 网关是一个常见的需求。本文将介绍如何结合 Docker 和 PM2 构建一个高性能的 Node.js API 网关,并深入探讨分布式限流器的原理与实现。 1. 背景与需求 1.1 高并发 API 网关的挑战 在高并发场景下&#xff…...

现代前端工程化实践:高效构建的秘密

一、前端工程化错误监控 这种监控可以帮助开发人员及时发现和解决问题,提高应用程序的稳定性和可靠性。 1. Sentry:Sentry是一款开源的错误监控平台,可以监控前端、后端以及移动端应用程序中的错误和异常。Sentry提供了实时错误报告、错误分…...

react高级面试题

以下是一些React高级面试题: 一、组件相关 React组件的生命周期有哪些(类组件)?在函数组件中如何实现类似功能? 答案: 类组件生命周期: componentDidMount:组件挂载后调用&#xff…...

html 列动态布局

样式说明: /* 列动态布局,列之间以空格填充 */ li {display: flex;/* flex-direction: column; */justify-content: space-between; }...

C++小等于的所有奇数和=最大奇数除2加1的平方。

缘由 三种思路解题&#xff1a;依据算术推导得到一个规律&#xff1a;小等于的所有奇数和等于最大奇数除以2加1的平方。将在后续发布&#xff0c;总计有十种推导出来的实现代码。 int a 0,aa 1,aaa 0;cin >> a; while (aa<a) aaa aa, aa 2;cout << aaa;i…...

政采云业务网关实践:使用 Higress 统一替代 APISIX/Kong/Istio Ingress

作者&#xff1a;政采云基础架构团队技术专家 朱海峰&#xff08;片风&#xff09; 业务网关项目背景 由于一些历史的背景&#xff0c;政采云平台在网关建设上遇到一些问题&#xff1a; 容器网关配置较多&#xff0c;配置方式多样&#xff0c;运维压力较大&#xff1a; 配置…...

【嵌入式 Linux 音视频+ AI 实战项目】瑞芯微 Rockchip 系列 RK3588-基于深度学习的人脸门禁+ IPC 智能安防监控系统

前言 本文主要介绍我最近开发的一个个人实战项目&#xff0c;“基于深度学习的人脸门禁 IPC 智能安防监控系统”&#xff0c;全程满帧流畅运行。这个项目我目前全网搜了一圈&#xff0c;还没发现有相关类型的开源项目。这个项目只要稍微改进下&#xff0c;就可以变成市面上目前…...

安卓7以上抓包证书安装

安卓7以上抓包证书安装 fiddler 用户可以直接试试这个文件 前提是要root过了&#xff0c;如果是模拟器就很容易开启 前提&#xff1a;要有openssl工具&#xff0c;在linux一个指令就可以下载了&#xff1a;sudo apt-get install openssl,windons则是在https://www.openssl.org/…...

【C#】任务调度的实现原理与组件应用Quartz.Net

Quartz 是一个流行的开源作业调度库&#xff0c;最初由 Terracotta 开发&#xff0c;现在由 Terracotta 的一部分 Oracle 所有。它主要用于在 Java 应用程序中调度作业的执行。Quartz 使用了一种复杂的底层算法来管理任务调度&#xff0c;其中包括任务触发、执行、持久化以及集…...

C语言:深入了解指针4(超级详细)

看之前必须得掌握有一定指针的知识&#xff0c;不然会看不懂&#xff0c;如果有不懂的可以看我博客 指针1&#xff0c;指针2&#xff0c;指针3 这三个讲了指针全部的基础知识超级详细&#xff0c;这篇只要是讲一些指针练习题也是非常详细 1. sizeof和strlen的对⽐ 1. 基本定义…...

C#+Redis接收数据并定时3秒钟频率异步保存到数据库

要在C#中实现从Redis接收数据,并以每3秒的频率异步保存到数据库,你可以使用System.Threading.Tasks.Task.Delay或System.Timers.Timer来创建一个定时任务。不过,对于更复杂的定时和调度需求,System.Threading.Tasks.Timer或Quartz.NET等库可能更合适。 在这个场景中,由于…...

CEF132 编译指南 Windows 篇 - 拉取 CEF 源码 (五)

1. 引言 获取 CEF 132 源码是开始编译工作的前提和关键步骤。在完成 depot_tools 的安装和配置后&#xff0c;我们需要通过正确的方式下载和同步 CEF 的源代码。由于 CEF 项目依赖于 Chromium 的大量组件&#xff0c;因此源码的获取过程需要特别注意同步策略和版本管理&#x…...

【鸿蒙开发】第二十四章 AI - Core Speech Kit(基础语音服务)

目录 1 简介 1.1 场景介绍 1.2 约束与限制 2 文本转语音 2.1 场景介绍 2.2 约束与限制 2.3 开发步骤 2.4 设置播报策略 2.4.1 设置单词播报方式 2.4.2 设置数字播报策略 2.4.3 插入静音停顿 2.4.4 指定汉字发音 2.5 开发实例 3 语音识别 3.1 场景介绍 3.2 约束…...

DeepSeek与llama本地部署(含WebUI)

DeepSeek从2025年1月起开始火爆&#xff0c;成为全球最炙手可热的大模型&#xff0c;各大媒体争相报道。我们可以和文心一言一样去官网进行DeepSeek的使用&#xff0c;那如果有读者希望将大模型部署在本地应该怎么做呢&#xff1f;本篇文章将会教你如何在本地傻瓜式的部署我们的…...

让万物「听说」:AI 对话式智能硬件方案和发展洞察

本文整理自声网 SDK 新业务探索组技术负责人&#xff0c;IoT 行业专家 吴方方 1 月 18 日在 RTE 开发者社区「Voice Agent 硬件分享会」上的分享。本次主要介绍了 AI 对话式智能硬件的发展历程&#xff0c;新一波 AI 浪潮所带来的创新机遇、技术挑战以及未来的展望。 在语音交…...

Day38-【13003】短文,二叉树,完全二叉树,二叉树的顺序存储,和链式存储

文章目录 第二节 二叉树二叉树的定义及重要性质n个结点&#xff0c;能组合成多少个不同的二叉树满二叉树、完全二叉树完全二叉树的性质二叉树的性质二叉树的结点数完全二叉树的高度 二叉树的存储顺序存储方式链式存储方式二叉链表的程序实现二叉链表空指针域计算 第二节 二叉树…...

MyBatis常见知识点

#{} 和 ${} 的区别是什么&#xff1f; 答&#xff1a; ${}是 Properties 文件中的变量占位符&#xff0c;它可以用于标签属性值和 sql 内部&#xff0c;属于原样文本替换&#xff0c;可以替换任意内容&#xff0c;比如${driver}会被原样替换为com.mysql.jdbc. Driver。 一个…...

4. 【.NET 8 实战--孢子记账--从单体到微服务--转向微服务】--什么是微服务--微服务设计原则与最佳实践

相比传统的单体应用&#xff0c;微服务架构通过将大型系统拆分成多个独立的小服务&#xff0c;不仅提升了系统的灵活性和扩展性&#xff0c;也带来了许多设计和运维上的挑战。如何在设计和实现微服务的过程中遵循一系列原则和最佳实践&#xff0c;从而构建一个稳定、高效、易维…...

【AI】在Ubuntu中使用docker对DeepSeek的部署与使用

这篇文章前言是我基于部署好的deepseek-r1:8b模型跑出来的 关于部署DeepSeek的前言与介绍 在当今快速发展的技术环境中&#xff0c;有效地利用机器学习工具来解决问题变得越来越重要。今天&#xff0c;我将引入一个名为DeepSeek 的工具&#xff0c;它作为一种强大的搜索引擎&a…...

Linux后台运行进程

linux 后台运行进程&#xff1a;& , nohup-腾讯云开发者社区-腾讯云 进程 &&#xff0c;后台运行&#xff0c;结束终端退出时结束进程。 nohup 进程 &&#xff0c;后台运行&#xff0c;结束终端后依然保持运行。...

unity视频在场景中的使用

&#xff08;一&#xff09;软件操作在平面上显示视频播放 1.创建渲染器纹理 2.创建平面 3.在平面上添加Video player 4.视频拖拽到Video player 5.渲染模式选择渲染器纹理 6.把纹理拖到目标纹理上 7.把纹理拖到平面上就可以了 然后运行项目 8.结果 &#xff08;二&#…...

vue3+vite+eslint|prettier+elementplus+国际化+axios封装+pinia

文章目录 vue3 vite 创建项目如果创建项目选了 eslint prettier从零教你使用 eslint prettier第一步&#xff0c;下载eslint第二步&#xff0c;创建eslint配置文件&#xff0c;并下载好其他插件第三步&#xff1a;安装 prettier安装后配置 eslint (2025/2/7 补充) 第四步&am…...

【电商系统架构的深度剖析与技术选型】

以下是对电商系统架构的深度剖析与技术选型&#xff1a; 一、电商系统架构剖析 整体架构 前台系统&#xff1a;是用户直接交互的部分&#xff0c;包括用户界面、商品展示、购物车、订单结算等模块。需注重用户体验&#xff0c;确保页面设计美观、商品信息清晰、购物流程简便。…...

【Android】Android开发应用如何开启任务栏消息通知

Android开发应用如何开启任务栏消息通知 1. 获取通知权限2.编写通知工具类3. 进行任务栏消息通知 1. 获取通知权限 在 AndroidManifest.xml 里加上权限配置&#xff0c;如下。 <?xml version"1.0" encoding"utf-8"?> <manifest xmlns:android…...

【Android开发AI实战】基于CNN混合YOLOV实现多车牌颜色区分且针对车牌进行矫正识别(含源码)

文章目录 引言单层卷积神经网络&#xff08;Single-layer CNN&#xff09;&#x1f4cc; 单层 CNN 的基本结构&#x1f4cc; 单层 CNN 计算流程图像 透视变换矫正车牌c实现&#x1fa84;关键代码实现&#xff1a;&#x1fa84;crnn结构图 使用jni实现高级Android开发&#x1f3…...

探索前端框架的未来:Svelte 的崛起

引言 在前端开发的世界里&#xff0c;框架更新换代的速度仿佛光速。从 jQuery 到 Angular&#xff0c;再到如今大热的 React 和 Vue&#xff0c;开发者们不断追逐更轻量、更快、更易于维护的框架。如今&#xff0c;Svelte 正悄然崛起&#xff0c;并引发了关于前端框架未来的热烈…...

【工具篇】深度揭秘 Midjourney:开启 AI 图像创作新时代

家人们,今天咱必须好好唠唠 Midjourney 这个在 AI 图像生成领域超火的工具!现在 AI 技术发展得那叫一个快,各种工具层出不穷,Midjourney 绝对是其中的明星产品。不管你是专业的设计师、插画师,还是像咱这种对艺术创作有点小兴趣的小白,Midjourney 都能给你带来超多惊喜,…...

多光谱成像技术在华为Mate70系列的应用

华为Mate70系列搭载了光谱技术的产物——红枫原色摄像头&#xff0c;这是一款150万像素的多光谱摄像头。 相较于普通摄像头&#xff0c;它具有以下优势&#xff1a; 色彩还原度高&#xff1a;色彩还原准确度提升约 120%&#xff0c;能捕捉更多光谱信息&#xff0c;使拍摄照片色…...

数字人|通过语音和图片来创建高质量的视频

简介 arXiv上的计算机视觉领域论文&#xff1a; AniPortrait: Audio-Driven Synthesis of Photorealistic Portrait Animation AniPortrait&#xff1a;照片级真实感肖像动画的音频驱动合成 核心内容围绕一种新的人像动画合成框架展开。 研究内容 提出 AniPortrait 框架&a…...

Vue通过触发与监听事件进行数据传递: 子组件调用 $emit 方法来将数据传递给父组件。

文章目录 引言I 组件事件事件参数defineEmits 宏声明需要抛出的事件事件校验例子:子组件告诉父组件放大所有博客文章的文字II 【详细说明】 子组件通过触发一个事件,将数据传递给父组件调用内建的 `$emit `方法传入事件名称来触发一个事件子组件通过`this.$emit`来触发一个事…...