2

Node + Express 后台开发 —— 上传、下载和发布 - 彭加李

 1 year ago
source link: https://www.cnblogs.com/pengjiali/p/17385971.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

上传、下载和发布

前面我们已经完成了数据库的增删改查,在弄一个上传图片、下载 csv,一个最简单的后台开发就已完成,最后部署即可。

需求:做一个个人简介的表单提交,有昵称简介头像。后端能接收数据并保存到数据库。

接收不到数据

amis-editor(amis 低代码编辑器,更多了解请看这里)绘制一个如下界面:

o_230509104817_node_express-uploaddownloaddeploy-01.png

前端上传文件使用 InputFile 的手动上传。配置如下:

{
    "type": "input-file",
    "name": "file",
    "label": "File",
    "accept": "*",
    "asBlob": true
}

后端定义一个路由:

// 个人简介
// http://localhost:3000/users/upload
router.post('/upload', function(req, res, next) {
  console.log('req', req.body)
  res.send({"status":0,"msg":"","data":{}});
});

输入信息后提交,后端 req.body 是空对象,说明无法接收数据:

req {}
POST /users/upload 200 6.230 ms - 31

前端传输数据如下:

o_230509104825_node_express-uploaddownloaddeploy-02.png

如果前端不传文件,后端 req.body 则能正常接收数据:

req { nickname: 'pjl', introduction: 'i am pjl', file: '' }
POST /users/upload 200 26.287 ms - 31

TipContent-Type 用于指示资源的 MIMIE 类型,请求中,客户端告诉服务器实际发送的数据类型。相应中,告诉客户端发送的内容的内容类型。不传文件请求头的 Content-Type 是 Content-Type: application/json;传了文件,请求头的 Content-Type 是 Content-Type: multipart/form-data; boundary=----。需要在表单中进行文件上传时,就需要使用该格式:multipart/form-data

multer

Multer 是一个 node.js 中间件,用于处理 multipart/form-data 类型的表单数据,它主要用于上传文件。
:Multer 不会处理任何非 multipart/form-data 类型的表单数据

安装 multer

PS E:\pjl-back-end> npm install --save multer

added 17 packages, and audited 119 packages in 18s

3 packages are looking for funding
  run `npm fund` for details

4 vulnerabilities (3 high, 1 critical)

To address all issues (including breaking changes), run:
  npm audit fix --force

Run `npm audit` for details.

使用 multer:

PS E:\pjl-back-end> git diff routes/users.js

+const multer  = require('multer')
+// 启动服务后,自动在 public 下创建 uploads 文件夹
+const upload = multer({ dest: 'public/uploads/' })

+// 一旦请求过来,就会先经过中间件把接收到的图片存入 uploads 文件夹中,然后在到下一步
+// file 是前端文件的 name。由于这里是一张图片,所以用 single 方法。多张图片的使用请看文档
+router.post('/upload', upload.single('file'), function(req, res, next) {
+  // req.body 将具有文本域数据,如果存在的话
+  console.log(req.body)
+  // req.file 是 `file` 文件的信息
+  console.log(req.file)
   res.send({"status":0,"msg":"","data":{}});
 });

启动服务后,会自动在 public 下创建 uploads 文件夹。输入昵称、简介和头像,点击提交。头像文件会重命名并上传到 uploads 中,通过 req.body 可以取得昵称和简介,通过 req.file 可以取得文件信息。后续存入数据库的操作笔者就不在进行,无非就是通过 token 取得用户 id,然后将昵称、简介和头像路径传给 services,通过 model 保存到数据库。

Tip:虽然文件没有了后缀(.png),通过chrome 直接访问图片路径(http://localhost:3000/uploads/36d8bda3160d8d09e81b167de1969b47)会自动下载,把图片路径给到 image 是可以正常使用。

o_230509104833_node_express-uploaddownloaddeploy-03.png

下载csv

需求:点击导出全部按钮,发起请求,通过后端直接下载 csv 文件,里面是表格数据。

安装 json2csv 包,用于将数据库中查询的 json 转为 csv:

PS E:\pjl-back-end> npm install json2csv

added 4 packages, and audited 123 packages in 4s

3 packages are looking for funding
  run `npm fund` for details

4 vulnerabilities (3 high, 1 critical)

To address all issues (including breaking changes), run:
  npm audit fix --force

Run `npm audit` for details.
PS E:\pjl-back-end>

安装 iconv-lite 用于编码转换:

PS E:\pjl-back-end> npm i iconv-lite

added 2 packages, changed 1 package, and audited 125 packages in 3s

3 packages are looking for funding
  run `npm fund` for details

4 vulnerabilities (3 high, 1 critical)

To address all issues (including breaking changes), run:
  npm audit fix --force

Run `npm audit` for details.

新建 utils.js,导出 downloadResource 方法用于下载 csv:

// E:\pjl-back-end\libs\utils.js

const Parser = require('json2csv').Parser;

const downloadResource = (res, fileName, fields, data) => {
    
    const json2csv = new Parser({ fields });
    const csv = json2csv.parse(data);
    // iconv-lite: Pure JS character encoding conversion 转码,防止中文乱码
    const iconv = require('iconv-lite');
    const newCsv = iconv.encode(csv, 'gbk')
  
    res.header('Content-Type', 'text/csv');
    res.attachment(fileName);
    return res.send(newCsv);
  }

  module.exports = {
    downloadResource,
  }

在任意路由中增加下载的处理请求:

const downloadResource = require('../libs/utils').downloadResource;
router.get('/download', function(req, res, next) {
  // 列名
  const fields = [
    {
      label: '姓名',
      value: 'name'
    },
    {
      label: '年龄',
      value: 'age'
    },
  ];
  // 模拟从数据库查询出的数据
  const data = [
    { "name":"peng 彭", "age": 18}, 
    { "name":"jia 加", "age": 19}, 
    { "name":"li 李", "age": 20}, 
    { "name":"pjl 彭加李", "age": 21}, 
  ];

  return downloadResource(res, 'users.csv', fields, data);
});

重启服务,浏览器输入 localhost:3000/users/download 回车后会自动下载 csv 文件。双击打开 csv,效果如下:

o_230509104840_node_express-uploaddownloaddeploy-04.png

如果不转码处理,这里 csv 中的中文就会乱码。

疑惑:网上说 gbk和utf8都是都能编码中英文。将 gbk 改为 utf8,在 win7 中打开 csv 仍旧乱码,或许是win7 中打开csv是gbk,得保持客户端和服务器编码一致?

假如 node 项目已经开发完毕,得将应用部署到服务器中。

直接使用 node app.js 一旦关闭终端,服务就会中断

虽然也可以使用 node app.js & 后台启动服务,但也有很多不足,比如重新发布代码不会自动生效

Tip: windows 下关闭后台启动的服务,比如端口是 3000

PS E:\pjl-back-end> netstat -ano|findstr 3000
  TCP    0.0.0.0:3000           0.0.0.0:0              LISTENING       12384
  TCP    [::]:3000              [::]:0                 LISTENING       12384
  TCP    [::1]:3000             [::1]:10229            TIME_WAIT       0
  TCP    [::1]:10230            [::1]:3000             TIME_WAIT       0
PS E:\pjl-back-end> taskkill /PID 12384 /F
成功: 已终止 PID 为 12384 的进程。

nodemon app.js 常用于开发环境

笔者这里使用 pm2。有如下好处:

  • 监控服务资源
  • 发布代码、宕机后会自动重启
  • 比如你的是cpu 是4核,也能充分利用
  • 能查看日志

体验 pm2

全局安装 pm2

PS E:\pjl-back-end> npm install pm2 -g
npm WARN deprecated [email protected]: Please upgrade  to version 7 or higher.  Older versions may use Math.random() in certain circumstances, which is known to be problematic.  See https://v8.dev/blog/math-random for details.

added 184 packages, and audited 185 packages in 25s

12 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities
PS E:\pjl-back-end> pm2 list

下面我们使用 pm2 启动服务:

Tip: 笔者由于环境问题,使用 npx 运行 pm2。你们可以省略。

通过 pm2 --version 查看版本,说明安装成功:

PS E:\pjl-back-end> npx pm2 --version
5.3.0

通过 pm2 start 入口文件 启动服务:

PS E:\pjl-back-end> npx pm2 start ./bin/www
[PM2] Starting E:\pjl-back-end\bin\www in fork_mode (1 instance)
[PM2] Done.
┌────┬────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┬──
────────┬──────────┐
│ id │ name   │ namespace   │ version │ mode    │ pid      │ uptime │ ↺    │ status    │ cpu      │ mem      │ user     │ watching │
├────┼────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼──────────┼──
────────┼──────────┤
│ 0  │ www    │ default     │ 0.0.0   │ fork    │ 9904     │ 0s     │ 0    │ online    │ 0%       │ 42.0mb   │ Adm… │ disabled │
└────┴────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴──
────────┴──────────┘

应用的 id 是 0,name 是 www,后续删除、启动和重启应用使用 id 和 name 都可以。

表示重启次数为0。后续重启应用会自动增加。

status 中的 online 表示已上线。

通过 pm2 list 显示应用列表,比如目前有一个服务(www)已启动(online):

PS E:\pjl-back-end> npx pm2 list
┌────┬────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┬──
────────┬──────────┐
│ id │ name   │ namespace   │ version │ mode    │ pid      │ uptime │ ↺    │ status    │ cpu      │ mem      │ user     │ watching │
├────┼────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼──────────┼──
────────┼──────────┤
│ 0  │ www    │ default     │ 0.0.0   │ fork    │ 9904     │ 2m     │ 0    │ online    │ 0%       │ 57.9mb   │ Adm… │ disabled │
└────┴────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴──
────────┴──────────┘

通过 pm2 restart id|name 重启服务:

// 通过 id 重启
PS E:\pjl-back-end> npx pm2 restart 0
Use --update-env to update environment variables
[PM2] Applying action restartProcessId on app [0](ids: [ '0' ])
[PM2] [www](0) ✓
┌────┬────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┬──
────────┬──────────┐
│ id │ name   │ namespace   │ version │ mode    │ pid      │ uptime │ ↺    │ status    │ cpu      │ mem      │ user     │ watching │
├────┼────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼──────────┼──
────────┼──────────┤
│ 0  │ www    │ default     │ 0.0.0   │ fork    │ 12088    │ 0s     │ 1    │ online    │ 0%       │ 41.9mb   │ Adm… │ disabled │
└────┴────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴──
────────┴──────────┘
// 通过 name 重启
PS E:\pjl-back-end> npx pm2 restart www
Use --update-env to update environment variables
[PM2] Applying action restartProcessId on app [www](ids: [ 0 ])
[PM2] [www](0) ✓
┌────┬────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┬──
────────┬──────────┐
│ id │ name   │ namespace   │ version │ mode    │ pid      │ uptime │ ↺    │ status    │ cpu      │ mem      │ user     │ watching │
├────┼────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼──────────┼──
────────┼──────────┤
│ 0  │ www    │ default     │ 0.0.0   │ fork    │ 6648     │ 0s     │ 2    │ online    │ 0%       │ 40.9mb   │ Adm… │ disabled │
└────┴────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴──

Tip: 表示重启过几次了

pm2 info www 查看 www 这个应用的详细信息:

PS E:\pjl-back-end> npx pm2 info www
 Describing process with id 0 - name www 
┌───────────────────┬────────────────────────────────────────────────┐
│ status            │ online                                         │
│ name              │ www                                            │
│ namespace         │ default                                        │
│ version           │ 0.0.0                                          │
│ restarts          │ 2                                              │
│ uptime            │ 62s                                            │
│ script path       │ E:\pjl-back-end\bin\www                      │
│ script args       │ N/A                                            │
│ error log path    │ C:\Users\Administrator\.pm2\logs\www-error.log │
│ out log path      │ C:\Users\Administrator\.pm2\logs\www-out.log   │
│ pid path          │ C:\Users\Administrator\.pm2\pids\www-0.pid     │
│ interpreter       │ node                                           │
│ interpreter args  │ N/A                                            │
│ script id         │ 0                                              │
│ exec cwd          │ E:\pjl-back-end                              │
│ exec mode         │ fork_mode                                      │
│ node.js version   │ 16.20.0                                        │
│ node env          │ N/A                                            │
│ watch & reload    │ ✘                                              │
│ unstable restarts │ 0                                              │
│ created at        │ 2023-05-09T07:28:11.550Z                       │
└───────────────────┴────────────────────────────────────────────────┘
 Revision control metadata 
┌──────────────────┬──────────────────────────────────────────┐
│ revision control │ git                                      │
│ remote url       │ N/A                                      │
│ repository root  │ E:\pjl-back-end                        │
│ last update      │ 2023-05-09T07:28:12.179Z                 │
│ revision         │ a02f7d6427fde5fdce41aff1626d31c19d80fcdf │
│ comment          │ 取消数据库和登录标识                               │
│ branch           │ master                                   │
└──────────────────┴──────────────────────────────────────────┘
 Actions available 
┌────────────────────────┐
│ km:heapdump            │
│ km:cpu:profiling:start │
│ km:cpu:profiling:stop  │
│ km:heap:sampling:start │
│ km:heap:sampling:stop  │
└────────────────────────┘
 Trigger via: pm2 trigger www <action_name>

 Code metrics value 
┌────────────────────────┬───────────┐
│ Used Heap Size         │ 20.15 MiB │
│ Heap Usage             │ 89 %      │
│ Heap Size              │ 22.64 MiB │
│ Event Loop Latency p95 │ 2.04 ms   │
│ Event Loop Latency     │ 0.08 ms   │
│ Active handles         │ 4         │
│ Active requests        │ 0         │
└────────────────────────┴───────────┘
 Divergent env variables from local env 


 Add your own code metrics: http://bit.ly/code-metrics
 Use `pm2 logs www [--lines 1000]` to display logs
 Use `pm2 env 0` to display environment variables
 Use `pm2 monit` to monitor CPU and Memory usage www

通过 pm2 monit id|name 监控应用程序:

PS E:\pjl-back-end> npx pm2 monit www
┌─ Process List ───────────────────────── ─  www Logs   ─────────────────┐┌─ Logs ───────────────────────────────────────────────
 [ 0] www                        Mem:  59 MB    CPU:  0 %  online  │www > 错误信息
│                                                                 │www > GET /users/testlog 304 1.186 ms - -
│                                                                 │www > 信息
│                                                                 │www > 错误信息
│                                                                 │www > GET /users/testlog 304 1.837 ms - -
│                                                                 │www > 信息
│                                                                 │www > GET /users/testlog 304 0.914 ms - -
│                                                                 │www > 错误信息
│                                                                 │www > 信息
│                                                                 │www > 错误信息
│                                                                 │www > GET /users/testlog 304 1.369 ms - -
│                                                                 │www > 信息
│                                                                 │www > 错误信息
│                                                                 │www > GET /users/testlog 304 1.733 ms - -
│                                                                 │www > 信息
│                                                                 │www > 错误信息
│                                                                 │www > GET /users/testlog 304 3.095 ms - -                                                                                                                
└─────────────────────────────────────────────────────────────────┘└────────────────────────────────────────────
┌─ Custom Metrics ────────────────────────────────────────────────┐┌─ Metadata ──────────────────────────────────────────────
│Used Heap Size                                       20.94 MiB   │App Name              www                                                                                                                                
│Heap Usage                                             91.45 %   │Namespace             default
│Heap Size                                            22.89 MiB   │Version               0.0.0
│Event Loop Latency p95                                 9.12 ms   │Restarts              2
│Event Loop Latency                                     0.14 ms   │Uptime                2m
└─────────────────────────────────────────────────────────────────┘└────────────────────────────────────────────
 left/right: switch boards | up/down/mouse: scroll | Ctrl-C: exit                                                                                                                       To go further check out https://pm2.io/

Tip:日志信息也会同步输出,日志就是console.log 或 console.error输出的内容,下文配置 pm2会讲到。

通过 pm2 stop id|name 停止服务:

PS E:\pjl-back-end> npx pm2 stop www
[PM2] Applying action stopProcessId on app [www](ids: [ 0 ])
[PM2] [www](0) ✓
┌────┬────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┬──
────────┬──────────┐
│ id │ name   │ namespace   │ version │ mode    │ pid      │ uptime │ ↺    │ status    │ cpu      │ mem      │ user     │ watching │
├────┼────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼──────────┼──
────────┼──────────┤
│ 0  │ www    │ default     │ 0.0.0   │ fork    │ 0        │ 0      │ 2    │ stopped   │ 0%       │ 0b       │ Adm… │ disabled │
└────┴────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴──
────────┴──────────┘
关闭并删除应用

通过 pm2 delete id|name 关闭并删除应用:

PS E:\pjl-back-end> npx pm2 delete www
[PM2] Applying action deleteProcessId on app [www](ids: [ 0 ])
[PM2] [www](0) ✓
┌────┬───────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────
┬──────────┬──────────┐
│ id │ name      │ namespace   │ version │ mode    │ pid      │ uptime │ ↺    │ status    │ cpu      │ mem      │ user     │ watching │
└────┴───────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────
┴──────────┴──────────┘
稳定的服务

比如笔者写一个如下服务 app2.js:

// app2.js
const http = require('http')
const fs = require('fs')
const server = http.createServer()

const requestListener = (req, res) => {
    const url = req.url
    // 如果url是 '/',则返回主页
    if(url === '/'){
        res.end("home page")
    }else if(url === '/b'){
        res.end("page b")
    }else if(url === '/error'){
        throw new Error('故意报错')
    }
}

server.on('request', requestListener)
server.listen('3000', () => {
    console.log('服务器已启动')
})

通过 node app2.js 启动服务后,访问 localhost:3000/error 故意报错,服务就会死掉,无法在响应其他请求:

PS E:\pjl-back-end> node app2.js
服务器已启动
E:\pjl-back-end\app2.js:13
        throw new Error('故意报错')
        ^

Error: 故意报错
    at Server.requestListener (E:\pjl-back-end\app2.js:13:15)
    at Server.emit (node:events:513:28)
    at parserOnIncoming (node:_http_server:998:12)
    at HTTPParser.parserOnHeadersComplete (node:_http_common:128:17)

如果改用 pm2 启动服务:

PS E:\pjl-back-end> npx pm2 start app2.js
[PM2] Starting E:\pjl-back-end\app2.js in fork_mode (1 instance)
[PM2] Done.
┌────┬─────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┬─
─────────┬──────────┐
│ id │ name    │ namespace   │ version │ mode    │ pid      │ uptime │ ↺    │ status    │ cpu      │ mem      │ user     │ watching │
├────┼─────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼──────────┼─
─────────┼──────────┤
│ 0  │ app2    │ default     │ 0.0.0   │ fork    │ 12248    │ 0s     │ 0    │ online    │ 0%       │ 40.2mb   │ Adm… │ disabled │
└────┴─────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴─
─────────┴──────────┘

再次访问 localhost:3000/error,通过 pm2 list 发现重启()次数从0变成了3,总之是重启了:

PS E:\pjl-back-end> npx pm2 list
┌────┬─────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┬─
─────────┬──────────┐
│ id │ name    │ namespace   │ version │ mode    │ pid      │ uptime │ ↺    │ status    │ cpu      │ mem      │ user     │ watching │
├────┼─────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼──────────┼─
─────────┼──────────┤
│ 0  │ app2    │ default     │ 0.0.0   │ fork    │ 12196    │ 25s    │ 3    │ online    │ 0%       │ 39.7mb   │ Adm… │ disabled │
└────┴─────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴─

访问 http://localhost:3000/ 页面显示 home page,说明服务正常,也较之前更稳定。

配置 pm2

需求:配置应用名称入口文件监控日志实例数

项目根目录新建 pm2 配置文件 pm2.config.json

{
    "apps": {
        // 应用名称
        "name": "spug-back-end",
        // 入口文件
        "script": "./bin/www",
        // 监控。修改代码后自动生效
        "watch": true,
        // 排除某些文件的监控
        "ignore_watch": [
            "node_modules",
            "logs"
        ],
        // 错误日志。通过 console.error() 输出
        "error_file": "logs/error.log",
        // 自定义日志。通过 console.log() 输出
        "out_file": "logs/custom.log",
        // 给日志添加时间。否则你得这么写 console.log('信息...', '2023-05-09 16:25:00')
        // YYYY不要小写
        "log_date_format": "YYYY-MM-DD HH:mm:ss",
        // cpu 核数。不要超过服务器的 cpu 核数
        // 笔者 cpu 核数是 2,这样会启动 2 个服务,能更好的利用服务器资源。
        "instances": 2
    }
}

Tip:windows 查看 CPU 核数 - 在 cmd 命令中输入 wmic,然后在出现的新窗口中输入 cpu get NumberOfCores

PS E:\pjl-back-end> wmic
wmic:root\cli>cpu get NumberOfCores
NumberOfCores
2

修改 package.json(pm2 指定配置文件启动服务):

// package.json
"scripts": {
    "start": "nodemon ./bin/www",
   +"pro": "pm2 start ./pm2.config.json"
  },

增加如下路由,用于测试日志

// localhost:3000/users/testlog
router.get('/testlog', function(req, res, next) {
  // 输出到自定义日志中
  console.log('信息');
  // 输出到错误日志中
  console.error('错误信息');
  res.send({"status":0,"msg":"123","data":{}});
});

通过 npm run pro 启动服务:

PS E:\pjl-back-end> npm run pro

> [email protected] pro
> pm2 start ./pm2.config.json

[PM2][WARN] Applications spug-back-end not running, starting...
[PM2] App [spug-back-end] launched (2 instances)
┌────┬──────────────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬───
───────┬──────────┬──────────┐
│ id │ name             │ namespace   │ version │ mode    │ pid      │ uptime │ ↺    │ status    │ cpu      │ mem      │ user     │ watching │
├────┼──────────────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼───
───────┼──────────┼──────────┤
│ 0  │ spug-back-end    │ default     │ 0.0.0   │ cluster │ 12496    │ 0      │ 1    │ stopped   │ 0%       │ 0b       │ Adm… │ enabled  │
│ 1  │ spug-back-end    │ default     │ 0.0.0   │ cluster │ 11436    │ 0      │ 1    │ stopped   │ 0%       │ 0b       │ Adm… │ enabled  │
└────┴──────────────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴───
───────┴──────────┴──────────┘

// 启动后立刻执行
PS E:\pjl-back-end> npx pm2 list
┌────┬──────────────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬───
───────┬──────────┬──────────┐
│ id │ name             │ namespace   │ version │ mode    │ pid      │ uptime │ ↺    │ status    │ cpu      │ mem      │ user     │ watching │
├────┼──────────────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼───
───────┼──────────┼──────────┤
│ 0  │ spug-back-end    │ default     │ 0.0.0   │ cluster │ 1396     │ 14s    │ 1    │ online    │ 0%       │ 58.7mb   │ Adm… │ enabled  │
│ 1  │ spug-back-end    │ default     │ 0.0.0   │ cluster │ 1704     │ 14s    │ 1    │ online    │ 0%       │ 58.7mb   │ Adm… │ enabled  │
└────┴──────────────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴───
───────┴──────────┴──────────┘
PS E:\pjl-back-end>

应用名是 spug-back-end

启动了两个应用,说明 "instances": 2 已生效。

logs 文件夹中生成了4个日志文件(每个cpu核就是两个),文件名也是我们配置的,目前日志内容都为空:

$ ll logs
total 0
-rw-r--r-- 1 Administrator 197121 0 May  9 16:40 custom-0.log
-rw-r--r-- 1 Administrator 197121 0 May  9 16:40 custom-1.log
-rw-r--r-- 1 Administrator 197121 0 May  9 16:40 error-0.log
-rw-r--r-- 1 Administrator 197121 0 May  9 16:40 error-1.log

访问 http://localhost:3000/ 页面显示正常:

Express
Welcome to Express

再次查看日志发现 custom-1.log 有内容,记录了着请求的详细信息。例如时间、请求的资源(/stylesheets/style.css):

Administrator@3L-WK-10 MINGW64 /e/pjl-back-end (master)
$ ll logs
total 1
-rw-r--r-- 1 Administrator 197121   0 May  9 16:40 custom-0.log
-rw-r--r-- 1 Administrator 197121 144 May  9 16:42 custom-1.log
-rw-r--r-- 1 Administrator 197121   0 May  9 16:40 error-0.log
-rw-r--r-- 1 Administrator 197121   0 May  9 16:40 error-1.log

Administrator@3L-WK-10 MINGW64 /e/pjl-back-end (master)
$ cat logs/custom-1.log
2023-05-09 16:42:35: GET / 304 21.595 ms - -
2023-05-09 16:42:35: GET /stylesheets/style.css 304 3.358 ms - -

修改某请求响应:

$ git diff  routes/index.js

 router.get('/', function(req, res, next) {
-  res.render('index', { title: 'Express' });
+  res.render('index', { title: 'Express2' });
 });

再次访问 http://localhost:3000/ 修改信息自动生效:

Express2
Welcome to Express2

通过 npx pm2 list 发现服务自动重启了(↺ 1 -> 3):

PS E:\pjl-back-end> npx pm2 list
┌────┬──────────────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬───
───────┬──────────┬──────────┐
│ id │ name             │ namespace   │ version │ mode    │ pid      │ uptime │ ↺    │ status    │ cpu      │ mem      │ user     │ watching │
├────┼──────────────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼───
───────┼──────────┼──────────┤
│ 0  │ spug-back-end    │ default     │ 0.0.0   │ cluster │ 13868    │ 89s    │ 3    │ online    │ 0%       │ 60.5mb   │ Adm… │ enabled  │
│ 1  │ spug-back-end    │ default     │ 0.0.0   │ cluster │ 11792    │ 89s    │ 3    │ online    │ 0%       │ 61.1mb   │ Adm… │ enabled  │
└────┴──────────────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴───

再次查看日志,发现 custom-0.log 也有数据了,这里其实间接说明了一个负载均衡的问题,这两个应用都能提供服务。

$ ll logs
total 2
-rw-r--r-- 1 Administrator 197121 228 May  9 16:46 custom-0.log
-rw-r--r-- 1 Administrator 197121 144 May  9 16:42 custom-1.log
-rw-r--r-- 1 Administrator 197121   0 May  9 16:40 error-0.log
-rw-r--r-- 1 Administrator 197121   0 May  9 16:40 error-1.log

接着访问输出日志的请求:http://localhost:3000/users/testlog,发现在同一时刻(16:54:47)往 custom-0.log 输出了 信息,在 error-0.log 中输出了 错误信息:

$ git diff logs
--- a/logs/custom-0.log
+++ b/logs/custom-0.log
 2023-05-09 16:53:56: GET /users/testlog 304 14.507 ms - -
+2023-05-09 16:54:47: 信息
+2023-05-09 16:54:47: GET /users/testlog 304 9.892 ms - -

--- a/logs/error-0.log
+++ b/logs/error-0.log
 2023-05-09 16:53:56: 错误信息
+2023-05-09 16:54:47: 错误信息

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK