这是《nestjs搭建通用业务框架》系列的第6篇,本篇带领大家升级nestjs中默认的web服务器Express,改成高性能的 fastify。
前言
本篇主要的目的,是搭建一个高性能的web服务器,便于后续开展通用业务(鉴权)的开发。
深入fastify
以下列出的是 Fastify 已经实现的主要功能及原理:
高性能: 据我们所知,Fastify 是这一领域中最快的 web 框架之一,另外,取决于代码的复杂性,Fastify 最多可以处理每秒 3 万次的请求。
可扩展: Fastify 通过其提供的钩子(hook)、插件和装饰器(decorator)提供完整的可扩展性。
基于 Schema: 即使这不是强制性的,我们仍建议使用 JSON Schema 来做路由(route)验证及输出内容的序列化,Fastify 在内部将 schema 编译为高效的函数并执行。
日志: 日志是非常重要且代价高昂的。我们选择了最好的日志记录程序来尽量消除这一成本,这就是 Pino!
对开发人员友好: 框架的使用很友好,帮助开发人员处理日常工作,并且不牺牲性能和安全性。
支持 TypeScript : 我们努力维护一个 TypeScript 类型声明文件,以便支持不断成长的 TypeScript 社区。
改良性能
在阅读与实践本部分的时候,一定要清晰的清楚自己的目标:提升接口的性能。如果,在已经成型的nest(Express)项目中,如果要进行Express -> Fastify的操作,一定要注意Express的中间件与Fastify可能不兼容,会导致切换失败。所以,在最初设计框架的时候就应该考虑到两个框架的优缺点,来进行选择。
框架 | 优点 | 缺点 |
---|---|---|
Express | 文档丰富,生态丰富 | 性能相对较差,笨重 |
Fastify | 性能优,轻量 | 学习与使用成本 |
总结:Fastify对于初学者来说,学习成本与Express一致,所以建立直接上手。Express对于熟悉http模块的同学来说,上手成本低。对于性能有要求的场景,Fastify是大家不二的选择。
在nest中默认会使用Express框架,作为web服务器的底层服务。为了提升性能的需求,nest提供了其他库的兼容性,例如Fastify
Fastify的性能是优于Express的,见下表:
测试环境: EX41S-SSD, Intel Core i7, 4Ghz, 64GB RAM, 4C/8T, SSD.
方法:autocannon -c 100 -d 40 -p 10 localhost:3000
* 2, taking the second average
框架 | 版本 | 是否有路由功能? | 请求/秒 |
---|---|---|---|
Express | 4.17.1 | ✓ | 15,978 |
hapi | 19.1.0 | ✓ | 45,815 |
Restify | 8.5.1 | ✓ | 49,279 |
Koa | 2.13.0 | ✗ | 54,848 |
Fastify | 3.0.0 | ✓ | 78,956 |
- | |||
http.Server | 12.18.2 | ✗ | 70,380 |
数据测试库fastify/benchmarks
集成步骤:
安装依赖
@nestjs/platform-fastify
1
npm i --save @nestjs/platform-fastify
配置适配器
安装 fastify 后,我们可以使用
FastifyAdapter
,修改src/main.ts
文件1 2 3 4 5 6 7 8 9 10 11
import { NestFactory } from '@nestjs/core'; import { FastifyAdapter, NestFastifyApplication } from '@nestjs/platform-fastify'; import { ApplicationModule } from './app.module'; async function bootstrap() { const app = await NestFactory.create<NestFastifyApplication>(ApplicationModule, new FastifyAdapter()); // 默认情况下,`Fastify`仅在 `localhost 127.0.0.1` 接口上监听 // 改成 0.0.0.0 接受其他主机上的连接 await app.listen(3000, '0.0.0.0'); } bootstrap();
运行
npm run start:dev
,打开localhost:3000
验证服务是否OK。
看Hello world
,或者打印出来如下信息:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | [下午8:43:23] File change detected. Starting incremental compilation... [下午8:43:23] Found 0 errors. Watching for file changes. [Nest] 4682 - 2021/03/24 下午8:43:24 [NestFactory] Starting Nest application... [Nest] 4682 - 2021/03/24 下午8:43:24 [InstanceLoader] DatabaseModule dependencies initialized +44ms [Nest] 4682 - 2021/03/24 下午8:43:24 [InstanceLoader] TypeOrmModule dependencies initialized +1ms [Nest] 4682 - 2021/03/24 下午8:43:24 [InstanceLoader] ConfigHostModule dependencies initialized +0ms [Nest] 4682 - 2021/03/24 下午8:43:24 [InstanceLoader] AppModule dependencies initialized +0ms [Nest] 4682 - 2021/03/24 下午8:43:24 [InstanceLoader] ConfigModule dependencies initialized +1ms [Nest] 4682 - 2021/03/24 下午8:43:24 [InstanceLoader] ConfigModule dependencies initialized +0ms [Nest] 4682 - 2021/03/24 下午8:43:24 [InstanceLoader] ConfigModule dependencies initialized +0ms query: START TRANSACTION query: SELECT * FROM `INFORMATION_SCHEMA`.`COLUMNS` WHERE `TABLE_SCHEMA` = 'nest-common' AND `TABLE_NAME` = 'typeorm_metadata' query: COMMIT [Nest] 4682 - 2021/03/24 下午8:43:25 [InstanceLoader] TypeOrmCoreModule dependencies initialized +118ms [Nest] 4682 - 2021/03/24 下午8:43:25 [RoutesResolver] AppController {}: +8ms [Nest] 4682 - 2021/03/24 下午8:43:25 [RouterExplorer] Mapped {, GET} route +3ms [Nest] 4682 - 2021/03/24 下午8:43:25 [NestApplication] Nest application successfully started +3ms |
就OK了。
关于路径别名
我们常见的用法,比如:@
代表src
在nest项目中配置路径别名比较简单,可以在tsconfig.json
中添加paths
属性:
1 2 3 4 5 6 7 8 9 10 11 12 | { "compilerOptions": { // .... // 添加如下内容 "paths": { "@/*": [ "src/*" ], } }, // ... } |
然后,重新使用npm run start:dev
进行测试即可。
后面,项目目录再深,也好写文件路径了,再也不用看到../../../
无穷无尽的关联路径了。