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

NestJS 性能优化:从应用到部署的最佳实践

在上一篇文章中,我们介绍了 NestJS 的微服务架构实现。本文将深入探讨 NestJS 应用的性能优化策略,从应用层到部署层面提供全方位的优化指南。

应用层优化

1. 路由优化

// src/modules/users/users.controller.ts
import { Controller, Get, UseInterceptors, CacheInterceptor } from '@nestjs/common';
import { UsersService } from './users.service';@Controller('users')
@UseInterceptors(CacheInterceptor)
export class UsersController {constructor(private readonly usersService: UsersService) {}// 使用路由参数而不是查询参数,提高路由匹配效率@Get(':id')async findOne(@Param('id') id: string) {return this.usersService.findOne(id);}// 避免深层嵌套路由@Get(':id/profile')async getProfile(@Param('id') id: string) {return this.usersService.getProfile(id);}
}

2. 数据序列化优化

// src/interceptors/transform.interceptor.ts
import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { classToPlain } from 'class-transformer';@Injectable()
export class TransformInterceptor implements NestInterceptor {intercept(context: ExecutionContext, next: CallHandler): Observable<any> {return next.handle().pipe(map(data => {// 使用 class-transformer 进行高效的数据序列化return classToPlain(data, { excludeExtraneousValues: true,enableCircularCheck: false });}),);}
}

数据库优化

1. 查询优化

// src/modules/posts/posts.service.ts
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Post } from './post.entity';@Injectable()
export class PostsService {constructor(@InjectRepository(Post)private postsRepository: Repository<Post>,) {}async findAll(page: number, limit: number) {// 使用分页查询const [posts, total] = await this.postsRepository.createQueryBuilder('post').leftJoinAndSelect('post.author', 'author')// 只选择需要的字段.select(['post.id', 'post.title', 'author.name'])// 添加索引字段的排序.orderBy('post.createdAt', 'DESC')// 使用分页.skip((page - 1) * limit).take(limit)// 缓存查询结果.cache(true).getManyAndCount();return { posts, total };}
}

2. 索引优化

// src/entities/user.entity.ts
import { Entity, Column, Index } from 'typeorm';@Entity()
export class User {@Column()@Index() // 为经常查询的字段添加索引email: string;@Column()@Index() // 为经常排序的字段添加索引createdAt: Date;// 复合索引@Index(['firstName', 'lastName'])@Column()firstName: string;@Column()lastName: string;
}

缓存策略

1. Redis 缓存集成

// src/config/cache.config.ts
import { CacheModule } from '@nestjs/common';
import * as redisStore from 'cache-manager-redis-store';export const cacheConfig = {imports: [CacheModule.register({store: redisStore,host: process.env.REDIS_HOST,port: process.env.REDIS_PORT,ttl: 60 * 60, // 1 hourmax: 100, // 最大缓存数}),],
};// src/modules/products/products.service.ts
import { Injectable, Inject, CACHE_MANAGER } from '@nestjs/common';
import { Cache } from 'cache-manager';@Injectable()
export class ProductsService {constructor(@Inject(CACHE_MANAGER) private cacheManager: Cache,) {}async getProduct(id: string) {// 先从缓存获取let product = await this.cacheManager.get(`product:${id}`);if (!product) {// 缓存未命中,从数据库获取product = await this.productRepository.findOne(id);// 设置缓存await this.cacheManager.set(`product:${id}`, product, { ttl: 3600 });}return product;}
}

2. 多级缓存策略

// src/services/cache.service.ts
import { Injectable } from '@nestjs/common';
import { Cache } from 'cache-manager';
import * as NodeCache from 'node-cache';@Injectable()
export class CacheService {private localCache: NodeCache;constructor(@Inject(CACHE_MANAGER) private redisCache: Cache,) {this.localCache = new NodeCache({stdTTL: 60, // 本地缓存 1 分钟checkperiod: 120,});}async get(key: string) {// 1. 检查本地缓存let data = this.localCache.get(key);if (data) return data;// 2. 检查 Redis 缓存data = await this.redisCache.get(key);if (data) {// 将数据放入本地缓存this.localCache.set(key, data);return data;}return null;}async set(key: string, value: any, ttl?: number) {// 同时更新本地缓存和 Redis 缓存this.localCache.set(key, value, ttl);await this.redisCache.set(key, value, { ttl });}
}

内存管理

1. 内存泄漏防护

// src/decorators/memory-safe.decorator.ts
import { applyDecorators, SetMetadata } from '@nestjs/common';export function MemorySafe(options: { timeout?: number } = {}) {return applyDecorators(SetMetadata('memory-safe', true),SetMetadata('timeout', options.timeout || 30000),);
}// src/interceptors/memory-guard.interceptor.ts
import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { Observable } from 'rxjs';
import { timeout } from 'rxjs/operators';@Injectable()
export class MemoryGuardInterceptor implements NestInterceptor {constructor(private reflector: Reflector) {}intercept(context: ExecutionContext, next: CallHandler): Observable<any> {const isMemorySafe = this.reflector.get('memory-safe', context.getHandler());const timeoutValue = this.reflector.get('timeout', context.getHandler());if (isMemorySafe) {return next.handle().pipe(timeout(timeoutValue),);}return next.handle();}
}

2. 垃圾回收优化

// src/main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import * as v8 from 'v8';async function bootstrap() {// 配置垃圾回收v8.setFlagsFromString('--max_old_space_size=4096');const app = await NestFactory.create(AppModule);// 定期强制垃圾回收setInterval(() => {global.gc();}, 30000);await app.listen(3000);
}
bootstrap();

部署优化

1. PM2 集群配置

// ecosystem.config.js
module.exports = {apps: [{name: 'nestjs-app',script: 'dist/main.js',instances: 'max', // 根据 CPU 核心数自动设置实例数exec_mode: 'cluster',autorestart: true,watch: false,max_memory_restart: '1G',env: {NODE_ENV: 'production',},}],
};

2. Nginx 负载均衡

# nginx.conf
upstream nestjs_upstream {least_conn; # 最少连接数负载均衡server 127.0.0.1:3000;server 127.0.0.1:3001;server 127.0.0.1:3002;keepalive 32; # 保持连接数
}server {listen 80;server_name example.com;location / {proxy_pass http://nestjs_upstream;proxy_http_version 1.1;proxy_set_header Upgrade $http_upgrade;proxy_set_header Connection 'upgrade';proxy_set_header Host $host;proxy_cache_bypass $http_upgrade;# 开启 gzip 压缩gzip on;gzip_types text/plain application/json;gzip_min_length 1000;# 客户端缓存设置add_header Cache-Control "public, max-age=3600";}
}

监控与性能分析

1. 性能监控集成

// src/modules/monitoring/monitoring.service.ts
import { Injectable } from '@nestjs/common';
import * as prometheus from 'prom-client';@Injectable()
export class MonitoringService {private readonly requestDuration: prometheus.Histogram;private readonly activeConnections: prometheus.Gauge;constructor() {// 初始化 Prometheus 指标this.requestDuration = new prometheus.Histogram({name: 'http_request_duration_seconds',help: 'Duration of HTTP requests in seconds',labelNames: ['method', 'route', 'status'],buckets: [0.1, 0.5, 1, 2, 5],});this.activeConnections = new prometheus.Gauge({name: 'active_connections',help: 'Number of active connections',});}recordRequestDuration(method: string, route: string, status: number, duration: number) {this.requestDuration.labels(method, route, status.toString()).observe(duration);}incrementConnections() {this.activeConnections.inc();}decrementConnections() {this.activeConnections.dec();}
}

2. 日志优化

// src/modules/logging/winston.config.ts
import { WinstonModule } from 'nest-winston';
import * as winston from 'winston';
import 'winston-daily-rotate-file';export const winstonConfig = {imports: [WinstonModule.forRoot({transports: [// 控制台日志new winston.transports.Console({format: winston.format.combine(winston.format.timestamp(),winston.format.colorize(),winston.format.simple(),),}),// 文件日志(按日期轮转)new winston.transports.DailyRotateFile({filename: 'logs/application-%DATE%.log',datePattern: 'YYYY-MM-DD',zippedArchive: true,maxSize: '20m',maxFiles: '14d',format: winston.format.combine(winston.format.timestamp(),winston.format.json(),),}),],}),],
};

写在最后

本文详细介绍了 NestJS 应用的性能优化策略:

  1. 应用层优化:路由优化、数据序列化
  2. 数据库优化:查询优化、索引设计
  3. 缓存策略:Redis 集成、多级缓存
  4. 内存管理:内存泄漏防护、垃圾回收优化
  5. 部署优化:PM2 集群、Nginx 负载均衡
  6. 监控与性能分析:Prometheus 集成、日志优化

通过实施这些优化策略,我们可以显著提升 NestJS 应用的性能和可靠性。在实际应用中,建议根据具体场景和需求选择合适的优化方案。

如果觉得这篇文章对你有帮助,别忘了点个赞 👍

相关文章:

NestJS 性能优化:从应用到部署的最佳实践

在上一篇文章中&#xff0c;我们介绍了 NestJS 的微服务架构实现。本文将深入探讨 NestJS 应用的性能优化策略&#xff0c;从应用层到部署层面提供全方位的优化指南。 应用层优化 1. 路由优化 // src/modules/users/users.controller.ts import { Controller, Get, UseInter…...

本地快速推断的语言模型比较:Apple MLX、Llama.cpp与Hugging Face Candle Rust

本地快速推断的语言模型比较&#xff1a;Apple MLX、Llama.cpp与Hugging Face Candle Rust 在自然语言处理&#xff08;NLP&#xff09;部署中&#xff0c;推断速度是一个关键因素&#xff0c;尤其是对于支持大型语言模型&#xff08;LLM&#xff09;的应用来说。随着Apple M1…...

您的公司需要小型语言模型

当专用模型超越通用模型时 “越大越好”——这个原则在人工智能领域根深蒂固。每个月都有更大的模型诞生&#xff0c;参数越来越多。各家公司甚至为此建设价值100亿美元的AI数据中心。但这是唯一的方向吗&#xff1f; 在NeurIPS 2024大会上&#xff0c;OpenAI联合创始人伊利亚…...

智能工厂的设计软件 应用场景的一个例子:为AI聊天工具添加一个知识系统 之14 方案再探 之5:知识树三类节点对应的三种网络形式及其网络主机

本文要点 前面讨论过&#xff08;前面有错这里做了修正&#xff09;&#xff0c;三种簿册归档 对应通过不同的网络形式&#xff08;分布式、对等式和去中心式&#xff09;。每种网络主机上分别提供&#xff1a; 分布式控制脚本、 对等式账本 和 备记手本 通过以上讨论&#x…...

JR-RLAA系20路模拟音频多功能编码器

JR-RLAA系20路模拟音频多功能编码器 产品特色 (1)工业级19英寸标准设备&#xff0c;内置双电源 (2)内嵌Web Server&#xff0c;支持远程Web页面登陆后的统一配置操作 (3)支持20路音频输入 (4)支持Dolby Digital(AC-3) &#xff0c;MPEG-2&#xff0c;AAC-LC/HE-AAC&#x…...

LabVIEW冷却风机性能测试系统

开发了基于LabVIEW软件及LabSQL工具包的冷却风机性能测试系统。系统通过高效的数据库访问技术&#xff0c;实现了对冷却风机测试过程中关键性能数据的采集、存储与管理&#xff0c;优化了测试流程并提升了数据处理的效率。 ​ 项目背景 在工业生产和科研测试中&#xff0c;准…...

Python-Pdf转Markdown

使用pdfminer.sixmarkdownify pdfminer.six可以提取Pdf文本内容markdownify可以将文本内容写markdown文件 安装 pip install pdfminer.six pip install markdownify实现 from pdfminer.high_level import extract_text from markdownify import markdownifydef pdf2markdo…...

pyQT + OpenCV相关练习

一、设计思路 1、思路分析与设计 本段代码是一个使用 PyQt6 和 OpenCV 创建的图像处理应用程序。其主要功能是通过一个图形界面让用户对图片进行基本的图像处理操作&#xff0c;如灰度化、翻转、旋转、亮度与对比度调整&#xff0c;以及一些滤镜效果&#xff08;模糊、锐化、边…...

音视频入门基础:MPEG2-PS专题(3)——MPEG2-PS格式简介

一、引言 本文对MPEG2-PS格式进行简介。 进行简介之前&#xff0c;请各位先下载MPEG2-PS的官方文档。ITU-T和ISO/IEC都分别提供MPEG2-PS的官方文档。但是ITU提供的文档是免费的&#xff0c;ISO/IEC是付费的&#xff0c;所以我们主要阅读ITU提供的官方文档&#xff0c;比如较新…...

云计算学习架构篇之HTTP协议、Nginx常用模块与Nginx服务实战

一.HTTP协议讲解 1.1rsync服务重构 bash 部署服务端: 1.安装服务 [rootbackup ~]# yum -y install rsync 2.配置服务 [rootbackup ~]# vim /etc/rsyncd.conf uid rsync gid rsync port 873 fake super yes use chroot no max connections 200 timeout 600 ignore erro…...

Zookeeper模式安装Kafka(含常规、容器两种安装方式)

一、#创作灵感# 公司使用Kafka的软件项目较多&#xff0c;故写技术笔记巩固知识要点 二、软件环境 - Kafka 3.9.0 官方下载地址&#xff1a;Kafka 3.9.0 - ZooKeeper 3.9.3 官方下载地址&#xff1a;ZooKeeper 3.9.3 - Docker Desktop 4.37 容器图形化工具 官方下载地址…...

【游戏设计原理】41 - 游戏的核心

1. 如何理解&#xff1f; 这条原理主要在讲述“游戏核心”这一概念的重要性及其在游戏开发中的作用。游戏的核心是指决定游戏整体玩法和体验的核心元素&#xff0c;它通常是游戏的主要机制、目标或动作方式。理解这一原理时&#xff0c;我们可以从以下几个层面来考虑&#xff…...

机器学习算法基础知识1:决策树

机器学习算法基础知识1&#xff1a;决策树 一、本文内容与前置知识点1. 本文内容2. 前置知识点 二、场景描述三、决策树的训练1. 决策树训练方式&#xff08;1&#xff09;分类原则-Gini&#xff08;2&#xff09;分类原则-entropy&#xff08;3&#xff09;加权系数-样本量&am…...

[Qt] 信号和槽(1) | 本质 | 使用 | 自定义

目录 一、信号和槽概述 二、本质 底层实现 1. 函数间的相互调用 2. 类成员中的特殊角色 三、使用 四. 自定义信号和槽 1. 基本语法 (1) 自定义信号函数书写规范 (2) 自定义槽函数书写规范 (3) 发送信号 (4) 示例 A. 示例一 B. 示例二 —— 老师说“上课了”&…...

33. 简易内存池

1、题目描述 ● 请实现一个简易内存池,根据请求命令完成内存分配和释放。 ● 内存池支持两种操作命令&#xff0c;REQUEST和RELEASE&#xff0c;其格式为&#xff1a; ● REQUEST请求的内存大小 表示请求分配指定大小内存&#xff0c;如果分配成功&#xff0c;返回分配到的内存…...

win32汇编环境,对话框程序模版,含文本框与菜单简单功能

;运行效果 ;win32汇编环境,对话框程序模版&#xff0c;含文本框与菜单简单功能 ;直接抄进RadAsm可编译运行。 ;下面为asm文件 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>&g…...

人工智能与传统编程的主要区别是什么?

传统编程&#xff1a;开发者预先编写软件行为规则&#xff0c;代码基于程序员定义逻辑处理输入并产生确定输出&#xff0c;具有确定性、手动编写规则和结构化逻辑特点&#xff0c;如垃圾邮件分类程序基于预设关键词等规则。AI 编程&#xff1a;从数据中学习而非手动编写规则&am…...

实战交易策略 篇十一:一揽子交易策略

文章目录 系列文章适用条件核心策略小额大量投资行业或主题聚焦同步操作优势系列文章 实战交易策略 篇一:奥利弗瓦莱士短线交易策略 实战交易策略 篇二:杰西利弗莫尔股票大作手操盘术策略 实战交易策略 篇三:333交易策略 实战交易策略 篇四:价值投资交易策略 实战交易策略…...

doris 2.1 -Data Manipulation-Transaction

注意:doris 只能控制读一致性,并不能rollback 1 Explicit and Implicit Transactions 1.1 Explicit Transactions 1.1.1 Explicit transactions require users to actively start, commit transactions. Only insert into values statement is supported in 2.1. BEGIN; …...

多模态融合:阿尔茨海默病检测

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 一、实验介绍 本实验包含 645 名阿尔茨海默病受试者&#xff0c;分为 AD、CN 和 MCI 组&#xff0c;数据集包含 3D MRI 图像与一份CSV数据&#xff0c;MRI数据…...

AI 焦虑别乱投!3 个问题秒懂要不要养「虾」

作者 | 张辉清 责编 | 梦依丹出品 | 程序人生&#xff08;ID&#xff1a;coder_life&#xff09;当下 AI 热度居高不下&#xff0c;企业该如何抉择&#xff1f;是大举投入布局&#xff0c;还是保持观望&#xff1f;我们借以下三个问题来展开思考。AI 当下处在什么阶段&#xf…...

SAP SD实战:用‘品目阶层’给老板打报表,别再手动筛选了(附OVSV配置步骤)

SAP SD实战&#xff1a;用‘品目阶层’高效生成管理层报表的完整指南 每次月底做销售报表时&#xff0c;你是不是还在手动筛选"男装-夏装"这类产品线数据&#xff1f;作为SAP SD顾问&#xff0c;我经历过无数次熬夜整理Excel表格的痛苦。直到真正掌握了品目阶层的报表…...

从JDK21降到17:2025版IDEA搭建苍穹外卖项目,我踩过的那些版本坑

从JDK21降到17&#xff1a;2025版IDEA搭建苍穹外卖项目实战避坑指南 当你用最新版IDEA 2025和JDK 21打开一个要求JDK 17的项目时&#xff0c;就像穿着高跟鞋去爬山——不是不行&#xff0c;但绝对会走得很辛苦。最近在搭建苍穹外卖项目时&#xff0c;我就深刻体会到了这种&quo…...

交付前批量人脸脱敏自动模糊的一点记录

客户给了一批线下沙龙现场图&#xff0c;两百三十张上下&#xff0c;要用于对外案例页&#xff0c;合同里写了人脸需做不可辨认处理。手工框选不现实&#xff0c;我这次用【批量图片面部识别自动模糊工具】走完整交付链&#xff0c;只记和排期、验收相关的点。输入支持拖文件夹…...

基于企业发展过程的改进型元启发式算法IED:一种高效智能优化策略的探索与应用

改进企业发展优化算法IED&#xff0c;(Enterprise Development, ED)是一种新型的元启发式算法&#xff08;智能优化算法&#xff09;&#xff0c;灵感来源于企业的发展过程。 该算法清晰易懂&#xff0c;与我们日常使用的优化算法相近&#xff0c;发表的期刊等级很高&#xff0…...

万象视界灵坛部署案例:边缘设备(Jetson Orin)轻量化CLIP推理部署

万象视界灵坛部署案例&#xff1a;边缘设备&#xff08;Jetson Orin&#xff09;轻量化CLIP推理部署 1. 项目概述 万象视界灵坛&#xff08;Omni-Vision Sanctuary&#xff09;是一款基于OpenAI CLIP模型的高级多模态智能感知平台。该平台通过创新的像素风格界面设计&#xf…...

英特尔I350网卡PXE功能深度配置:从FLASH状态查询到端口精准控制

1. 英特尔I350网卡PXE功能基础认知 第一次接触服务器网卡PXE配置的朋友可能会觉得这是个"黑盒子"。其实简单来说&#xff0c;PXE&#xff08;Preboot eXecution Environment&#xff09;就是让计算机在没装系统的情况下&#xff0c;通过网络启动并安装操作系统的技术…...

如何用3分钟搭建深度学习的漫画翻译流水线?BallonsTranslator深度解析

如何用3分钟搭建深度学习的漫画翻译流水线&#xff1f;BallonsTranslator深度解析 【免费下载链接】BallonsTranslator 深度学习辅助漫画翻译工具, 支持一键机翻和简单的图像/文本编辑 | Yet another computer-aided comic/manga translation tool powered by deeplearning 项…...

从概念到工具:实战构建基于clawhub skill的个人技能管理体系

最近在整理自己的技能树时&#xff0c;发现需要一个能直观管理个人技术栈的工具。尝试用clawhub skill框架搭建了一套解决方案&#xff0c;配合InsCode(快马)平台的快速部署能力&#xff0c;三天就做出了可实际使用的技能看板。记录下关键实现思路&#xff0c;或许对同样想系统…...

泉盛UV-K5/K6固件自定义:解锁专业对讲机功能的终极指南

泉盛UV-K5/K6固件自定义&#xff1a;解锁专业对讲机功能的终极指南 【免费下载链接】uv-k5-firmware-custom 全功能泉盛UV-K5/K6固件 Quansheng UV-K5/K6 Firmware 项目地址: https://gitcode.com/gh_mirrors/uvk5f/uv-k5-firmware-custom 你是否曾想过&#xff0c;一台…...