Appearance
Express 架构分析
高层架构
Express 采用中间件链式的架构,整体可以分为以下几个层次:
┌─────────────────────────────────────────────────┐
│ 应用层 (Application) │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 路由 │ │ 中间件 │ │ 控制器 │ │
│ └──────────┘ └──────────┘ └──────────┘ │
├─────────────────────────────────────────────────┤
│ Express 核心 (Core) │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Router │ │ Layer │ │ Request │ │
│ └──────────┘ └──────────┘ └──────────┘ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Response │ │ App │ │ View │ │
│ └──────────┘ └──────────┘ └──────────┘ │
├─────────────────────────────────────────────────┤
│ Node.js HTTP (底层) │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ http │ │ events │ │ stream │ │
│ └──────────┘ └──────────┘ └──────────┘ │
└─────────────────────────────────────────────────┘核心模块
Application (应用)
Application 是 Express 的核心类,代表一个 Express 应用实例:
javascript
class Application {
constructor() {
this.settings = {};
this.engines = {};
this.defaultConfiguration();
}
// 启动服务器
listen(port, callback) {
const server = http.createServer(this);
return server.listen(port, callback);
}
// 注册中间件
use(fn) {
const layer = new Layer('/', fn);
this.stack.push(layer);
}
// 注册路由
get(path, fn) {
const route = new Route(path);
route.get(fn);
const layer = new Layer(path, route.dispatch.bind(route));
this.stack.push(layer);
}
// 处理请求
handle(req, res, done) {
let index = 0;
const next = (err) => {
if (err) {
return done(err);
}
if (index >= this.stack.length) {
return done();
}
const layer = this.stack[index++];
layer.handle_request(req, res, next);
};
next();
}
}Router (路由器)
Router 负责路由匹配和分发:
javascript
class Router {
constructor() {
this.stack = [];
}
// 添加路由
get(path, fn) {
const layer = new Layer(path, fn);
layer.method = 'GET';
this.stack.push(layer);
}
// 处理请求
handle(req, res, next) {
const method = req.method;
const url = req.url;
for (const layer of this.stack) {
if (layer.match(url) && layer.method === method) {
return layer.handle_request(req, res, next);
}
}
next();
}
}Layer (层)
Layer 代表中间件或路由的一层:
javascript
class Layer {
constructor(path, fn) {
this.path = path;
this.handle = fn;
this.method = null;
this.params = {};
}
// 匹配路径
match(path) {
if (this.path === path) {
return true;
}
// 支持参数路由
const paramNames = [];
const regex = this.pathToRegex(this.path, paramNames);
const match = path.match(regex);
if (match) {
this.params = this.extractParams(match, paramNames);
return true;
}
return false;
}
// 处理请求
handle_request(req, res, next) {
const fn = this.handle;
try {
fn(req, res, next);
} catch (err) {
next(err);
}
}
}Request (请求)
Request 扩展了 Node.js 的 IncomingMessage:
javascript
class Request {
constructor(req) {
this.req = req;
this.url = req.url;
this.method = req.method;
this.headers = req.headers;
this.query = this.parseQuery(req.url);
this.params = {};
this.body = {};
}
// 解析查询字符串
parseQuery(url) {
const queryIndex = url.indexOf('?');
if (queryIndex === -1) {
return {};
}
const queryString = url.slice(queryIndex + 1);
return this.parseQueryString(queryString);
}
// 解析查询字符串
parseQueryString(str) {
const params = {};
const pairs = str.split('&');
for (const pair of pairs) {
const [key, value] = pair.split('=');
params[decodeURIComponent(key)] = decodeURIComponent(value || '');
}
return params;
}
}Response (响应)
Response 扩展了 Node.js 的 ServerResponse:
javascript
class Response {
constructor(res) {
this.res = res;
this.statusCode = 200;
this.headers = {};
this.locals = {};
}
// 设置状态码
status(code) {
this.statusCode = code;
return this;
}
// 发送 JSON
json(obj) {
this.setHeader('Content-Type', 'application/json');
this.send(JSON.stringify(obj));
}
// 发送响应
send(data) {
this.res.writeHead(this.statusCode, this.headers);
this.res.end(data);
}
// 设置响应头
setHeader(name, value) {
this.headers[name] = value;
return this;
}
// 渲染模板
render(view, options, callback) {
// 实现模板渲染
}
}数据流
请求处理流程
HTTP 请求
│
▼
┌─────────────────────────────────────┐
│ HTTP 服务器 │
│ - 接收请求 │
│ - 创建 req/res 对象 │
└───────────────┬───────────────────┘
│
▼
┌─────────────────────────────────────┐
│ Express 应用 │
│ - 创建 Request 对象 │
│ - 创建 Response 对象 │
└───────────────┬───────────────────┘
│
▼
┌─────────────────────────────────────┐
│ 中间件链 │
│ - 执行中间件 1 │
│ - 执行中间件 2 │
│ - 执行中间件 N │
└───────────────┬───────────────────┘
│
▼
┌─────────────────────────────────────┐
│ 路由处理 │
│ - 匹配路由 │
│ - 提取参数 │
│ - 执行路由处理器 │
└───────────────┬───────────────────┘
│
▼
┌─────────────────────────────────────┐
│ 控制器 │
│ - 处理业务逻辑 │
│ - 生成响应数据 │
└───────────────┬───────────────────┘
│
▼
┌─────────────────────────────────────┐
│ 响应生成 │
│ - 设置状态码 │
│ - 设置响应头 │
│ - 发送响应体 │
└───────────────┬───────────────────┘
│
▼
HTTP 响应中间件链流程
请求进入
│
▼
┌─────────────────────────────────────┐
│ 中间件 1 │
│ - 处理请求 │
│ - 调用 next() │
└───────────────┬───────────────────┘
│
▼
┌─────────────────────────────────────┐
│ 中间件 2 │
│ - 处理请求 │
│ - 调用 next() │
└───────────────┬───────────────────┘
│
▼
┌─────────────────────────────────────┐
│ 中间件 N │
│ - 处理请求 │
│ - 调用 next() │
└───────────────┬───────────────────┘
│
▼
┌─────────────────────────────────────┐
│ 路由处理器 │
│ - 执行业务逻辑 │
│ - 发送响应 │
└───────────────┬───────────────────┘
│
▼
响应返回并发模型
单线程模型
Express 基于 Node.js 的单线程模型:
主线程
┌─────────────────────────────────────┐
│ 事件循环 │
│ - 接收请求 │
│ - 执行中间件 │
│ - 处理路由 │
│ - 发送响应 │
└───────────────┬───────────────────┘
│
▼
┌─────────────────────────────────────┐
│ 线程池 (libuv) │
│ - 文件 I/O │
│ - DNS 解析 │
│ - 加密操作 │
└─────────────────────────────────────┘并发处理
Express 可以处理大量并发请求:
请求 1 ──┐
├──► 中间件链 ──► 响应
请求 2 ──┤
│
请求 3 ──┤
│
请求 N ──┘容错策略
错误处理
Express 提供多种错误处理机制:
- 错误中间件:专门处理错误的中间件
- 默认错误处理:Express 内置的错误处理
- 异步错误:使用 next(err) 传递错误
- 错误日志:记录错误信息
错误处理流程
请求进入
│
▼
┌─────────────────────────────────────┐
│ 中间件 1 │
│ - 发生错误 │
│ - 调用 next(err) │
└───────────────┬───────────────────┘
│
▼
┌─────────────────────────────────────┐
│ 错误处理中间件 │
│ - 接收错误对象 │
│ - 处理错误 │
│ - 发送错误响应 │
└───────────────┬───────────────────┘
│
▼
错误响应可扩展性杠杆
水平扩展
Express 支持多种水平扩展方式:
- 负载均衡:使用 Nginx、HAProxy 等负载均衡器
- 集群模式:使用 Node.js cluster 模块
- 微服务:拆分为多个独立的服务
- 容器化:使用 Docker 进行容器化部署
垂直扩展
Express 也支持垂直扩展:
- 增加 CPU 核心:利用多核 CPU
- 增加内存:提高内存限制
- 优化代码:减少 CPU 和内存使用
- 使用缓存:减少重复计算和 I/O 操作
中间件扩展
Express 的中间件机制提供了强大的扩展能力:
- 自定义中间件:编写自己的中间件
- 第三方中间件:使用丰富的第三方中间件
- 中间件组合:组合多个中间件
- 条件中间件:根据条件加载中间件
总结
Express 的架构设计体现了"简单、灵活、可扩展"的理念。通过中间件链、路由系统和扩展的请求/响应对象,Express 提供了一个强大而灵活的 Web 框架。理解 Express 的架构有助于我们更好地使用和扩展 Express 应用。

扫描二维码关注"架构师AI杜"公众号,获取更多技术内容和最新动态
