2023-05-23-【服务开发】nestjs

一、前言背景

1.1 什么是nestjs

NestJS 是一个用于构建高效、可扩展的 Node.js 服务器端应用程序的开发框架。它利用 JavaScript 的渐进增强的能力,结合了 OOP(面向对象编程)、FP(函数式编程)和 FRP(函数响应式编程)等编程范式。NestJS 建立在强大的 HTTP 服务器框架上,例如 Express,并提供了更高层次的抽象,同时仍然向开发者直接暴露了底层框架的 API。

1.2 什么是nodejs

Node.js是一个基于Chrome V8引擎的JavaScript运行环境。它使得开发者能够高效地在服务器端运行JavaScript代码。Node.js提供了一个非阻塞I/O模型,使得开发者能够轻松地编写服务器端应用程序。Node.js还提供了一系列丰富的模块,使得开发者能够轻松地扩展应用程序的功能。

1.3 javascript运行环境

安装yapi

1.4 前端框架比较

框架 特点 缺点 适用场景
NestJS 高效;轻量级;基于装饰器;依赖注入;管道;中间件;拦截器等机制 学习成本较高;对开发者编程素养和面向对象开发思想的要求较高 中大型企业级 Web 应用;需要高效、可扩展的框架
Next.js 基于 React 和 React Router;服务器端渲染;生态圈繁荣 性能相对较低;需要使用 React 的知识 中大型企业级 Web 应用;需要高效、可扩展的框架
Nuxt.js 基于Vue.js 的轻量级应用框架;服务器端渲染;生态圈繁荣 性能相对较低;需要使用 Vue 的知识 中大型企业级 Web 应用;需要高效、可扩展的框架
Egg.js Egg.js 的企业级规范和强大的功能;多线程支持;类型检查良好;基于 Koa2 开发 学习成本较高;对开发者编程素养和面向对象开发思想的要求较高 中大型企业级 Web 应用;需要高效、可扩展的框架
Koa2 轻量级;异步中间件模型;生成器;上下文对象 学习曲线较陡峭;对异步编程的认知要求较高 中小型企业级 Web 应用;需要高效、可扩展的框架
Express 广泛的使用和生态圈;中间件模型;简单易学;主要用于构建RESTful API服务器 大而全,不够轻量级;性能相对较低 小型企业和个人项目;对性能要求不高的应用场景

1.5 nestjs与spring boot对比

| | nestjs | spring boot | |———–|———————–|————-| | 开发语言 | TypeScript或JavaScript | Java或Kotlin | | 发布时间 | 2017 | 2014 | | 学习曲线 | 易上手 | 成本高 | | 扩展性 | 高 | 高 | | 文档和社区 | 较新,不全面 | 完善且丰富 | | 维护成本 | 人力成本高 | 适中 | | 轻量级 | 是 | 否 | | 处理I/O任务 | 高效 | 一般 | | 单线程 | 是 | 否 | | 内存使用率 | 低 | 一般 | | 多线程支持 | 否 | 是 | | 执行计算量大的任务 | 一般 | 高效 | | 严格的类型检测 | 一般 | 是 | | 测试工具 | jest | Junit | | 应用场景 | 轻量级高性能中大型应用 | 大型复杂应用 |

二、nestjs基本概念及用法

Nest的目标是成为一个与平台无关的框架,目前支持两个框架:Express和Fastify,默认使用Express。NestJS对于这两个框架进行了一定的封装,也支持直接使用它们的API,因此给开发者带来了很大的自由度。

NestJS提供了一个开箱即用的框架,能够创建可测试、可扩展、低耦合和易于维护的应用程序。它的设计思想受到Angular的启发,同时也借鉴了其他MVC框架的概念和最佳实践。可使用nest-cli脚手架创建新的NestJS项目。

2.1 主要组件

2.1.1 控制器 Controller

  • 处理传入的请求并向客户端返回响应
  • 被 @Controller 装饰的类 就是 一个 Controller
  • 参数获取 @Body(), @Query(), @Res(); 返回 @Res()
  • nest g resource test

Controllers

2.1.2 提供者 Providers

  • 提供者是 Nest 中的一个基本概念。许多基本的 Nest 类都可以被视为提供者——服务、存储库、工厂、助手等。提供者的主要思想是它可以注入依赖项;这意味着对象之间可以创建各种关系,并且“连接”对象实例的功能可以在很大程度上委托给 Nest 运行时系统。
  • 被 @Injectable 装饰的类 都是Providers
  • 创建服务 nest g service cats Controllers

2.1.3 模块 Modules

  • 模块是用@Module()装饰器注释的类。装饰@Module()器提供Nest用来组织应用程序结构的元数据。
  • 每个应用程序至少有一个模块 - 根模块。根模块是 Nest 用来构建应用程序图的起点。

Controllers

2.1.4 中间件 Middleware

  • 中间件是在路由处理程序之前调用的函数,可以访问请求和响应对象。
  • 在函数中或在带有@Injectable()装饰器的类中实现自定义 Nest 中间件。类应该实现NestMiddleware接口,而函数没有任何特殊要求
    @Injectable()
    export class LoggerMiddleware implements NestMiddleware {
    

Controllers

2.1.5 管道 Pipes

  • 管道是用@Injectable()装饰器注释的类。管道应该实现PipeTransform接口。
  • 用途:1. 转换:将输入数据转换为所需的形式;2. 校验:评估输入数据,如果有效,则简单地通过它;否则,当数据不正确时抛出异常
  • 管道都在arguments由控制器路由处理程序处理的对象上运行。
  • 示例
    @Get(':id')
    async findOne(@Param('id', ParseIntPipe) id: number) {
    return this.catsService.findOne(id);
    }
    

2.1.6 守卫 Guards

  • 守卫是用@Injectable()装饰器注释的类。实现CanActivate接口。 用途:单一职责授权操作。使用@UseGuards() 绑定。
  • 与管道和异常过滤器一样,守卫可以是控制器范围的、方法范围的或全局范围的。
@Injectable()
export class AuthGuard implements CanActivate {

Controllers

2.1.7 拦截器

  • 使用@Injectable()装饰器注解的类,实现NestInterceptor接口,位于请求和响应之间的一段代码。
  • 用途:在函数执行前/后绑定额外的逻辑,如:权限验证,日志记录,性能监控。
  • 拦截器获取请求信息并仅在发送响应时执行阻塞操作。这样一来,传入的请求就不会因 Node.js 进程繁忙而受到限制,并且应用程序可以在后台进行异步处理(与 i/o 相关)。

Controllers

2.2 请求生命周期

  • 收到请求
  • 中间件
    1. 全局绑定的中间件
    1. 路径中指定的 Module 绑定的中间件
  • 守卫
    1. 全局守卫
    1. Controller 守卫
    1. Route 守卫
  • 拦截器(Controller 之前)
    1. 全局
    1. Controller 拦截器
    1. Route 拦截器
  • 管道
    1. 全局管道
    1. Controller 管道
    1. Route 管道
    1. Route 参数管道
  • Controller(方法处理器)
  • 服务
  • 拦截器(Controller 之后)
    1. Route 拦截器
    1. Controller 拦截器
    1. 全局拦截器
  • 异常过滤器
    1. Route
    1. 控制器
    1. 全局
  • 服务器响应

  • 注: Route 代表 Controller 下的method。

2.3 项目搭建

2.4 数据库操作 typeorm

TypeORM 是一个对象关系映射(ORM)库,可用于 Node.js 和各种浏览器中的不同数据库,如 MySQL、PostgreSQL、Oracle、MSSQL 和 SQLite。它支持 Active Record 和 Data Mapper 模式,具有类型安全、易于使用和可扩展的优点。TypeORM 旨在支持最新的 JavaScript 特性,并提供额外的功能以帮助开发人员快速构建健壮的数据库应用程序。

  1. 安装依赖
    npm install @nestjs/typeorm typeorm mysql
    
  2. 配置 ``` import { TypeOrmModule, TypeOrmModuleOptions } from ‘@nestjs/typeorm’; …

@Module({ imports: [ TypeOrmModule.forRoot({ type: ‘mysql’, host: ‘x.x.x.x’, port: 3306, username: ‘root’, password: ‘xxxx’, database: ‘xxxx’, entities: [__dirname + ‘/*/.entity{.ts,.js}’], synchronize: true, }), ], controllers: [AppController], providers: [AppService], }) export class AppModule { }


# 2.5 构建,区分环境
1. 安装依赖包

npm install @nestjs/config cross-env

2. 根目录创建 .env.dev 及 .env.prod 文件
3. 配置

import { Module } from ‘@nestjs/common’; import { AppController } from ‘./app.controller’; import { AppService } from ‘./app.service’; import { TypeOrmModule, TypeOrmModuleOptions } from ‘@nestjs/typeorm’; import { ScheduleModule } from ‘@nestjs/schedule’; import { ConfigModule, ConfigService } from ‘@nestjs/config’;

const envFilePath = .env.${process.env.NODE_ENV || 'dev'};

@Module({ imports: [ ConfigModule.forRoot({ isGlobal: true, envFilePath, }), //配置数据库链接 TypeOrmModule.forRootAsync({ imports: [ConfigModule], inject: [ConfigService], useFactory: (config: ConfigService) => { return { type: ‘mysql’, host: config.get(‘DATABASE_HOST’), port: config.get(‘DATABASE_PORT’), username: config.get(‘DATABASE_USER’), password: config.get(‘DATABASE_PASSWORD’), database: config.get(‘DATABASE_DATABASE’), entities: [__dirname + ‘/*/.entity{.ts,.js}’], synchronize: true, } as TypeOrmModuleOptions; }, }), ScheduleModule.forRoot() ], controllers: [AppController], providers: [AppService], }) export class AppModule { }

4. 修改 package.json 启动及打包指令

“start”: cross-env NODE_ENV=dev nest start –watch


# 2.6 定时任务 

import { ScheduleModule } from ‘@nestjs/schedule’;


[Nestjs开发环境和生产环境的配置](https://juejin.cn/post/7131724757019394079)

# 三、部署
### PM2
1. pm2 是开源的基于Nodejs的进程管理器,包括守护进程、监控、日志的一整套完整的功能;
2. pm2 带有负载均衡功能(使用 Node cluster 集群模块),可以保持node应用进程永远运行在后台
3. 0 秒停机重载,维护升级时不需要停机;
4. 安装pm2 ```pnpm install pm2 -g```

- PM2命令
1. pm2 start app.js:启动nodeJs应用,进程的默认名称为文件名app
2. pm2 start app.js --name mynode:启动node,并指定进程名称为mynode
3. pm2 start app.js -i max:根据有效CPU数目启动最大进程数目
4. pm2 start app.js --watch:实时监控的方式启动,app.js文件有变动时,pm2会自动reload

- 查看与监视进程
1. pm2 list:显示所有进程;
2. pm2 show 0,pm2 info 0:查看进程id为 0 的详细信息;
3. pm2 monit:进入监视页面,监视每个node进程的CPU和内存的使用情况。

- 停止、删除进程
1. pm2 stop/delete 0:停止/删除id为 0 的进程;
2. pm2 stop/delete all:停止/删除所有进程。

- 重启、重载
1. pm2 restart 0:重启id为 0 的进程;
2. pm2 restart all:重启所有进程;
3. pm2 reload 0:0秒停机重载id为 0 进程(用于 NETWORKED 进程);
4. pm2 reload all:重载所有进程。

- 日志操作
1. pm2 logs:显示所有进程的日志;
2. pm2 logs 0:显示进程id为 0 的日志;
3. pm2 flush:清空所有日志文件;
4. pm2 reloadLogs:重载所有日志。
5. pm2 startup:产生 init 脚本,保持进程活着。

## 2. docker容器化部署
- dockerfile


# 其他
mysql 自动备份
https://blog.51cto.com/u_15906694/6007052


1. 宿主机创建 backUp文件夹
2. 执行备份指令

docker exec -it mysql(容器名) /bin/bash -c ‘mysqldump -uroot -p123456 –databases 需要备份的数据库’ > /usr/local/mysql/backup/user_date +%F.sql(宿主机的文件路径);


docker exec -i mysql /bin/bash -c ‘mysqldump -uroot -pjueduianquan996 –databases blowsysun’ > /usr/local/mysql/backup/funds_data_date +\%F.sql

3. 创建定时任务
- linux上最常用的计划任务软件叫crontab,该软件的命令同时也叫crontab。

常用指令

crontab -l:查看当前定时任务 crontab -e:编辑、新建定时任务 0 0 19 * * 1-5 /usr/local/mysql/backup/timerTask.sh


4. 恢复数据

source /usr/local/mysql/backup/emp_2023-01-13.sql ```