• Node + Express 后台开发 —— 上传、下载和发布


    上传、下载和发布

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

    上传图片

    需求

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

    接收不到数据

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

    前端上传文件使用 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
    

    前端传输数据如下:

    如果前端不传文件,后端 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 是可以正常使用。

    下载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,效果如下:

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

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

    发布

    pm2

    假如 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
    成功: 已终止 PID12384 的进程。
    

    nodemon app.js 常用于开发环境

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

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

    体验 pm2

    全局安装 pm2

    PS E:\pjl-back-end> npm install pm2 -g
    npm WARN deprecated uuid@3.4.0: 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    │ default0.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    │ default0.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    │ default0.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    │ default0.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 
    
     Code metrics value 
    ┌────────────────────────┬───────────┐
    │ Used Heap Size20.15 MiB │
    │ Heap Usage89 %      │
    │ Heap Size22.64 MiB │
    │ Event Loop Latency p95 │ 2.04 ms   │
    │ Event Loop Latency0.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 MiBApp Name              www                                                                                                                                
    │Heap Usage                                             91.45 %   │Namespace             defaultHeap Size                                            22.89 MiBVersion               0.0.0Event Loop Latency p95                                 9.12 ms   │Restarts              2Event 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    │ default0.0.0   │ fork    │ 002    │ 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    │ default0.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    │ default0.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
    
    > pjl-back-end@0.0.0 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    │ default0.0.0   │ cluster │ 1249601    │ stopped   │ 0%       │ 0b       │ Adm… │ enabled  │
    │ 1  │ spug-back-end    │ default0.0.0   │ cluster │ 1143601    │ 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    │ default0.0.0   │ cluster │ 1396     │ 14s    │ 1    │ online    │ 0%       │ 58.7mb   │ Adm… │ enabled  │
    │ 1  │ spug-back-end    │ default0.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    │ default0.0.0   │ cluster │ 13868    │ 89s    │ 3    │ online    │ 0%       │ 60.5mb   │ Adm… │ enabled  │
    │ 1  │ spug-back-end    │ default0.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: 错误信息
    
  • 相关阅读:
    C语言学习记录(九)之结构体
    Scrapy
    vim 自动添加脚本信息
    javascript: Bubble Sort
    Github 2024-07-11 Go开源项目日报 Top10
    10.12021 CCPC 新疆省赛ABD
    day13_异常
    相交链表~环形链表
    模拟实现list
    五、Jvm调优
  • 原文地址:https://www.cnblogs.com/pengjiali/p/17385971.html