重大技术栈转变
关于目前在学企业级技术栈SpringBoot 生态向 Node.js生态转换的决定
为了统一所学技术栈,终结前后端语言割裂的现象,践行全端(前后、移动、PC)
也便于日后JavaScript向TypeScript转变
Node.js
Express 是 Node.js的一个库,提供了一些扩展:
Express对 Node.js 的 HTTP 模块进行了封装,提供了更加简洁和灵活的 API 来构建 Web 应用和 API。
功能对比
特性 Node.js 原生 Express 路由处理 需手动解析 URL 和方法 提供简洁的路由 API 中间件支持 需自行实现 内置中间件机制 请求处理 需手动解析请求体 提供 body-parser 等工具 响应处理 需手动设置响应头 简化的响应方法 静态文件服务 需手动实现 一行代码搞定 错误处理 需自行处理 统一错误处理机制
现代 Node.js 技术栈
1. 框架生态
- Express: 最流行的轻量级框架
- Koa: Express 的下一代框架
- Fastify: 高性能 Web 框架
- NestJS: 受 Angular 和Spring 启发的企业级框架
- Hapi: 配置驱动的框架
2. 适用实时应用
Node.js 的事件驱动和非阻塞 I/O 特性使其非常适合实时应用
事件驱动:事件驱动是一种编程范式,其中程序的执行流程由外部事件来决定;具体而言是通过:监听、回调来实现程序执行
补充:事件驱动在I/O操作中也可以理解成一种异步的I/O操作。
非阻塞I/O:发起I/O后并不阻塞,而是继续执行余下代码;I/O完成后再通过回调函数进行操作。
困惑解答
问:Node.js 被称为单线程却具有高并发处理能力?
答:
Node.js 确实是单线程的,但这个"单线程"指的是 JavaScript 执行线程 是单线程的,而不是整个运行时环境是单线程的。
比如,读取文件时,读取文件的那段代码是在主线程执行的,实际读取文件的操作是在其它线程完成的,这往往涉及到线程池和系统线程。下面是一个例子
| |
另一个视角是Node.js事件驱动、非阻塞I/O的特点,这使它能够接收、处理多个并发连接,这是因为每个I/O都不阻塞,并且I/O完成后还可通过回调接着处理。
总结
Node.js 的"单线程"和"高并发"并不矛盾:
- 单线程:指的是 JavaScript 代码执行在单个线程中,避免了多线程的复杂性
- 高并发:指的是能够同时处理大量 I/O 操作,通过非阻塞 I/O 和事件驱动实现
Node.js 通过以下机制实现高并发:
- 非阻塞 I/O:I/O 操作不阻塞主线程
- 事件驱动:通过事件循环处理完成的 I/O 操作
- 线程池:对于某些操作使用底层线程池
- 系统级异步 I/O:利用操作系统提供的异步 I/O 能力
这就是为什么 Node.js 特别适合 I/O 密集型应用(如 Web 服务器、API 服务)的原因。
问:Node.js既然有了多线程模型,并且还优于java,那么实际web应用开发中Node.js生态需不需要引入线程池,为什么
答:具体依照任务而定,如连接MySQL时需要引入数据库连接池,理由是:限制并发数据库查询数量,避免连接耗尽,数据库(如 MySQL)可能无法承受太多连接
总结
Node.js 不需要像 Java 那样广泛使用线程池,因为:
事件循环模型已优化高并发 I/O。
Worker Threads 提供了更轻量的 CPU 并行方案。
仅在以下情况考虑线程池:
长时间阻塞事件循环的 CPU 任务。
需要精细控制并发度的场景(如数据库连接池)。
替代方案:
用
cluster扩展进程。用任务队列(如
bull)解耦耗时任务。最终建议:
默认用事件循环(I/O 密集型)。
CPU 密集型任务 → Worker Threads 或专用微服务(如用 Go/Java 实现)。
线程池仅在特定场景下使用
问:和传统服务端技术的区别?
答:传统技术,如Apache + PHP 通过对多个请求创建多个线程,处理这些请求的始终,而Node通过一个主线程处理所有请求的始终,而中间过程的处理则交给其它线程。
传统服务端技术:
Node

开动啦
初始化后端项目

1. 安装依赖说明
(1) 生产依赖(后端必备)
npm install express cors dotenv
express: Node.js 后端框架cors: 处理跨域请求(开发时前端访问后端 API 用)dotenv: 加载.env环境变量
(2) 开发依赖(热更新调试)
npm install -D nodemon
nodemon: 监听文件变化自动重启 Node 服务(开发专用)