📖 本文共 3,232 字,阅读需要 11 分钟
杀鸡要不要用牛刀?一个简单API看透Node.js和PHP
先说结论
如果都用框架/成熟方案:
- 代码量:差不多(Express 50行 vs PHP 50行)
- 真正的差异不在代码量,在运维模式
| 对比项 | Node.js + Express | PHP |
|---|---|---|
| 业务代码量 | ~50行 | ~50行 |
| 运行模式 | 常驻进程(24小时待命) | 共享池(随用随走) |
| 更新代码 | 必须重启 | 直接覆盖 |
| 端口占用 | 单独开一个 | 复用现有 |
| 心智负担 | 多一套进程管理 | 上传即用 |
形象的比喻
Node.js = 私家车
- 天天停在楼下(常驻内存)
- 要买车位(单独端口)
- 要保养年检(PM2管理、重启)
- 好处:随时出发,性能好
PHP = 出租车
- 不用车时不存在(不占内存)
- 不用车位(共享端口)
- 随叫随到(改代码就生效)
- 好处:省心,随用随走
问题来了:你每天只出两次门,需要买辆私家车吗?
代码量对比(用框架版)
Node.js + Express(约50行)
const express = require('express');
const app = express();
const PORT = 8787;
const gicsData = {
sectors: [
{ id: 10, name: '能源' },
{ id: 15, name: '原材料' },
{ id: 20, name: '工业' },
{ id: 25, name: '可选消费' },
{ id: 30, name: '日常消费' },
{ id: 35, name: '医疗保健' },
{ id: 40, name: '金融' },
{ id: 45, name: '信息技术' },
{ id: 50, name: '通信服务' },
{ id: 55, name: '公用事业' },
{ id: 60, name: '房地产' }
]
};
// CORS中间件
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
next();
});
// 获取全部分类
app.get('/api/gics', (req, res) => {
res.json({
success: true,
data: gicsData,
total: gicsData.sectors.length
});
});
// 获取单个分类
app.get('/api/gics/:id', (req, res) => {
const sector = gicsData.sectors.find(s => s.id === parseInt(req.params.id));
if (!sector) {
return res.status(404).json({ success: false, message: '未找到' });
}
res.json({ success: true, data: sector });
});
app.listen(PORT, () => console.log(`Server running on port ${PORT}`));
PHP(约50行)
<?php
header('Content-Type: application/json');
header('Access-Control-Allow-Origin: *');
$gicsData = [
'sectors' => [
['id' => 10, 'name' => '能源'],
['id' => 15, 'name' => '原材料'],
['id' => 20, 'name' => '工业'],
['id' => 25, 'name' => '可选消费'],
['id' => 30, 'name' => '日常消费'],
['id' => 35, 'name' => '医疗保健'],
['id' => 40, 'name' => '金融'],
['id' => 45, 'name' => '信息技术'],
['id' => 50, 'name' => '通信服务'],
['id' => 55, 'name' => '公用事业'],
['id' => 60, 'name' => '房地产']
]
];
$path = $_SERVER['PATH_INFO'] ?? '/';
if ($path =<mark style="background-color: #FFFF00;"> '/api/gics' && $_SERVER['REQUEST_METHOD'] </mark>= 'GET') {
echo json_encode(['success' => true, 'data' => $gicsData, 'total' => count($gicsData['sectors'])]);
exit();
}
if (preg_match('/^\/api\/gics\/(\d+)$/', $path, $matches)) {
$id = (int)$matches[1];
foreach ($gicsData['sectors'] as $sector) {
if ($sector['id'] === $id) {
echo json_encode(['success' => true, 'data' => $sector]);
exit();
}
}
http_response_code(404);
echo json_encode(['success' => false, 'message' => '未找到']);
exit();
}
http_response_code(404);
echo json_encode(['success' => false, 'message' => '接口不存在']);
结论:代码量半斤八两,谁也不比谁优雅。
真正的差异:运维
场景一:部署上线
Node.js:
# 1. 服务器要装Node.js环境
# 2. 上传代码
scp app.js user@server:/app/
# 3. 安装依赖
cd /app && npm install
# 4. 启动服务(还要配PM2保活)
pm2 start app.js --name gics-api
pm2 save
pm2 startup # 配开机自启
# 5. Nginx还要配转发
location /api/ {
proxy_pass http://localhost:8787;
}
PHP:
# 1. 上传文件(完事)
scp api.php user@server:/var/www/html/
# 2. Nginx已经有了,不用改
# 3. 不用装依赖、不用配进程、不用管开机
PHP完胜。
场景二:改一行代码
Node.js:
vim app.js # 改代码
pm2 restart gics-api # 重启(有1秒中断)
PHP:
vim api.php # 改代码,完事
# 下个请求自动生效,无中断
PHP完胜。
场景三:服务器资源占用
Node.js(日请求100次):
内存:50MB × 24小时 = 一直占着
CPU:基本空闲
PHP(日请求100次):
内存:请求时5MB × 100次 × 几毫秒 = 几乎为0
CPU:只在请求时用
对于低频API,PHP资源利用率更高。
什么时候Node.js是正确答案?
不是Node.js不好,是场景要匹配。
用Node.js(私家车)✅
- 高并发(1000+ QPS)
- WebSocket长连接
- 需要内存缓存(如实时统计)
- 团队全栈统一JS
- 微服务架构(反正都要容器化)
用PHP(出租车)✅
- 简单CRUD接口
- 低频调用的API
- 个人小项目
- 快速原型验证
- 不想操心运维
- 服务器资源有限
我的真实感受
写这个API的时候我突然意识到:
Node.js没问题,问题是我的场景不配。
就像一个每天只出门两次的人,不需要买辆车。打车就挺好,便宜、省心、随叫随到。
等哪天我每天要出门100次(高并发),或者要拉货(WebSocket),或者要跑长途(实时流处理),我再买辆Node.js也不迟。
但现在?PHP就挺好。
总结
| 你关心什么 | 选谁 |
|---|---|
| 代码少 | 差不多 |
| 性能高 | Node.js |
| 部署省心 | PHP |
| 更新方便 | PHP |
| 资源占用小(低频) | PHP |
| 高并发能力强 | Node.js |
| 统一前后端语言 | Node.js |
没有银弹,只有合不合适。
你的下一个简单API,真的需要Node.js吗?
非引战,实事求是。两种技术我都爱用,只是场景不同。
评论区说说:你遇到过“杀鸡用牛刀”的经历吗?
本文章永久链接: 杀鸡要不要用牛刀?一个简单API看透Node.js和PHP
