Node.js-API 限流与日志优化

server/2024/11/13 1:12:14/

​🌈个人主页:前端青山
🔥系列专栏:node.js
🔖人终将被年少不可得之物困其一生

依旧青山,本期给大家带来node.js篇专栏内容:node.js-API 限流与日志优化

前言

在前几篇文章中,我们已经为 API 添加了身份验证、CORS 配置、缓存机制和性能监控。本文将继续在这个基础上,进一步增强 API 的稳定性和可维护性。我们将添加 API 限流功能,并对日志进行优化,以便更好地跟踪和调试应用。

目录

前言

目录

1. 添加 API 限流

1.1 安装依赖

1.2 创建限流中间件

1.3 应用限流中间件

2. 优化日志记录

2.1 安装依赖

2.2 创建日志配置

2.3 更新日志中间件

3. 项目结构

4. 运行项目

5. 测试与验证

5.1 测试 API 限流

5.2 验证日志记录

6. 总结与展望

1. 添加 API 限流

为了防止 API 被恶意请求或滥用,我们可以添加 API 限流功能。这有助于保护服务器免受 DDoS 攻击,并确保正常用户的请求能够得到及时响应。我们将使用 express-rate-limit 库来实现这一功能。

1.1 安装依赖

首先,我们需要安装 express-rate-limit 库。打开终端,导航到项目根目录,然后运行以下命令:

npm install express-rate-limit
1.2 创建限流中间件

接下来,我们在 middlewares 目录下创建一个名为 rateLimiter.js 的文件,用于定义限流中间件。

javascript">const rateLimit = require('express-rate-limit');const apiLimiter = rateLimit({windowMs: 15 * 60 * 1000, // 15 分钟max: 100, // 每个 IP 允许的最大请求数message: 'Too many requests from this IP, please try again later.',
});module.exports = apiLimiter;

在这个中间件中,我们设置了每个 IP 在 15 分钟内最多只能发送 100 个请求。如果超过这个限制,客户端将收到一条提示消息,告知其请求过多,需要稍后再试。

1.3 应用限流中间件

最后,我们需要在 app.js 文件中应用这个限流中间件。打开 app.js 文件,添加以下代码:

javascript">require('dotenv').config();
const express = require('express');
const helmet = require('helmet');
const compression = require('compression');
const cors = require('cors');
const swaggerUi = require('swagger-ui-express');
const swaggerJSDoc = require('swagger-jsdoc');
const itemsRouter = require('./routes/items');
const authRouter = require('./routes/auth');
const errorHandler = require('./middlewares/error-handler');
const connectDB = require('./config/db');
const logger = require('./middlewares/logger');
const statusMonitor = require('express-status-monitor');
const apiLimiter = require('./middlewares/rateLimiter');const app = express();// 配置 Helmet
app.use(helmet());// 配置 CORS
app.use(cors());// 日志中间件
app.use((req, res, next) => {logger.info(`${req.method} ${req.url}`);next();
});app.use(express.json()); // 解析 JSON 请求体// 压缩响应体
app.use(compression());// 连接 MongoDB
connectDB();// 性能监控
app.use(statusMonitor());// API 限流
app.use(apiLimiter);// 路由
app.use('/items', itemsRouter);
app.use('/auth', authRouter);// Swagger 配置
const options = {definition: {openapi: '3.0.0',info: {title: 'My API',version: '1.0.0',description: 'This is a simple API for managing items.',},servers: [{url: `http://localhost:${process.env.PORT || 3000}`,},],},apis: ['./routes/*.js'], // 指定包含 API 注解的文件
};const specs = swaggerJSDoc(options);
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(specs));// 错误处理中间件
app.use(errorHandler);module.exports = app;

2. 优化日志记录

为了更好地跟踪和调试应用,我们需要优化日志记录。一个好的日志系统可以帮助我们快速定位问题,了解应用的运行状态。我们将使用 winston 库来实现更详细和灵活的日志记录。

2.1 安装依赖

首先,我们需要安装 winston 和 winston-daily-rotate-file 库。打开终端,导航到项目根目录,然后运行以下命令:

npm install winston winston-daily-rotate-file
2.2 创建日志配置

接下来,我们在 config 目录下创建一个名为 logger.js 的文件,用于定义日志配置。

javascript">const winston = require('winston');
const DailyRotateFile = require('winston-daily-rotate-file');const transport = new DailyRotateFile({filename: 'application-%DATE%.log',datePattern: 'YYYY-MM-DD',zippedArchive: true,maxSize: '20m',maxFiles: '14d',dirname: 'logs',
});const logger = winston.createLogger({level: 'info',format: winston.format.combine(winston.format.timestamp(),winston.format.json()),transports: [transport,new winston.transports.Console({format: winston.format.combine(winston.format.colorize(),winston.format.simple()),}),],
});module.exports = logger;

在这个配置中,我们设置了日志文件的命名规则、日期模式、归档方式、最大文件大小和保留天数。同时,我们还配置了控制台输出,以便在开发过程中能够实时查看日志信息。

2.3 更新日志中间件

最后,我们需要更新 middlewares/logger.js 文件,使用新的日志配置。

javascript">const logger = require('../config/logger');const logRequest = (req, res, next) => {logger.info(`${req.method} ${req.url}`);next();
};module.exports = logRequest;

3. 项目结构

确保项目结构如下:

javascript">my-app/
├── node_modules/
├── public/
│   └── index.html
├── routes/
│   ├── items.js
│   └── auth.js
├── models/
│   ├── item.js
│   └── user.js
├── middlewares/
│   ├── error-handler.js
│   ├── logger.js
│   ├── auth.js
│   ├── cache.js
│   └── rateLimiter.js
├── config/
│   ├── db.js
│   ├── redis.js
│   └── logger.js
├── .env
├── app.js
└── index.js

4. 运行项目

确保 MongoDB 和 Redis 服务已启动。在项目根目录下运行以下命令启动应用:

npm install node index.js

访问 http://localhost:3000/api-docs 查看 Swagger 文档,访问 http://localhost:3000/status 查看性能监控页面。

5. 测试与验证

5.1 测试 API 限流

为了验证 API 限流功能是否生效,我们可以使用 Postman 或其他 HTTP 客户端工具发送多个请求。假设我们设置的限流规则是每个 IP 每 15 分钟最多 100 个请求,我们可以尝试发送超过 100 个请求,看看是否会被限流。

  1. 打开 Postman,创建一个新的请求,设置请求方法为 GET,URL 为 http://localhost:3000/items
  2. 快速发送多个请求,直到达到 100 个请求。
  3. 继续发送请求,观察响应是否返回 429 Too Many Requests 状态码,并且包含提示消息 Too many requests from this IP, please try again later.
5.2 验证日志记录

为了验证日志记录是否正确,我们可以检查日志文件和控制台输出。

  1. 在项目根目录下,找到 logs 目录,查看是否有生成的日志文件。
  2. 打开其中一个日志文件,检查其中的内容是否包含了请求的方法、URL 和时间戳。
  3. 同时,检查控制台输出,确保日志信息也显示在控制台上。

6. 总结与展望

通过本文,我们为 API 添加了限流功能,并优化了日志记录,进一步增强了 API 的稳定性和可维护性。API 限流功能可以帮助我们防止恶意请求和 DDoS 攻击,确保正常用户的请求能够得到及时响应。优化后的日志记录系统则可以帮助我们更好地跟踪和调试应用,快速定位问题。

在未来的文章中,我们将继续探索更多高级功能和技术,如 API 版本控制、安全性增强、部署和容器化等。希望这些改进对你有所帮助!如果你有任何问题或建议,请随时留言交流。


http://www.ppmy.cn/server/140850.html

相关文章

【项目开发】Netty等通信框架中异步IO的解决

未经许可,不得转载。 文章目录 前言异步IONettyMINATwisted前言 当某个过程在进行中,不会阻塞主程序的执行,而是允许程序继续执行其他任务,这样的过程称为异步。 在 JavaScript 和 jQuery 的开发中,异步操作被大量使用,尤其是在涉及回调函数的情况下。例如,以下是使用…

数学基础 -- 线性代数之线性无关

线性无关 在线性代数中,线性无关列指的是矩阵中的列向量之间不满足线性组合关系,即无法通过其他列向量的线性组合来表示某一个列向量。简单地说,一组向量是线性无关的,意味着其中任何一个向量不能由其他向量生成。 1. 线性无关的…

HDR视频技术

第一部分-HDR 技术基础 视频与图像, 是人类认识自然, 感受自然, 记录自然的两种最为直观的方式, 因此,自从 1839 年第一台照相机被发明出来之后,人类一直致力于更好地,更完善地,更精…

算法(第一周)

一周周五,总结一下本周的算法学习,从本周开始重新学习许久未见的算法,当然不同于大一时使用的 C 语言以及做过的简单题,现在是每天一题 C 和 JavaScript(还在学,目前只写了一题) 题单是代码随想…

react-copy-to-clipboard: 一个简单的 React 用于复制文本到剪贴板的组件

npm 地址和 git 地址 npm 地址: https://www.npmjs.com/package/react-copy-to-clipboardgit 地址: https://github.com/nkbt/react-copy-to-clipboard 官方说的用法 react-copy-to-clipboard 提供了一个 CopyToClipboard 组件,用于将文本复制到用户的剪贴板。以…

从零开始训练一个大语言模型需要多少天?

一,前言 在AI领域,训练一个大型语言模型(LLM)是一个耗时且复杂的过程。几乎每个做大型语言模型(LLM)训练的人都会被问到:“从零开始,训练大语言模型需要多久和花多少钱?”…

深度学习-神经网络基础-激活函数与参数初始化(weight, bias)

一. 神经网络介绍 神经网络概念 神经元构建 神经网络 人工神经网络是一种模仿生物神经网络结构和功能的计算模型, 由神经元构成 将神经元串联起来 -> 神经网络 输入层: 数据 输出层: 目标(加权和) 隐藏层: 加权和 激活 全连接 第N层的每个神经元和第N-1层的所有神经元…

Python学习从0到1 day27 第三阶段 Spark ③ 数据计算 Ⅱ

目录 一、Filter方法 功能 语法 代码 总结 filter算子 二、distinct方法 功能 语法 代码 总结 distinct算子 三、SortBy方法 功能 语法 代码 总结 sortBy算子 四、数据计算练习 需求: 解答 总结 去重函数: 过滤函数: 转换函数: 排…