topbit 3.0.7 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.cn.md CHANGED
@@ -915,7 +915,7 @@ app.run(1234)
915
915
  //展示负载信息,需要通过daemon接口开启cluster集群模式
916
916
  loadMonitor : true,
917
917
 
918
- //负载信息的类型,text 、json、--null
918
+ //负载信息的类型,text 、null, obj, orgobj
919
919
  //json类型是给程序通信使用的,方便接口开发
920
920
  loadInfoType : 'text',
921
921
 
package/README.md CHANGED
@@ -879,7 +879,7 @@ Full configuration options for app initialization are as follows. Please read th
879
879
  // Display load info, requires enabling cluster mode via daemon interface
880
880
  loadMonitor : true,
881
881
 
882
- // Load info type: text, json, --null
882
+ // Load info type: text, null, obj, orgobj
883
883
  // json type is for program communication, convenient for interface development
884
884
  loadInfoType : 'text',
885
885
 
package/bin/new-ctl.js CHANGED
@@ -4,66 +4,33 @@
4
4
 
5
5
  let simple_mode = false
6
6
 
7
- let type_context = `\n//!!注意:以下注释是为了能够在支持jsdoc的代码编辑器中提示以及方便查阅提供,不需要可以去掉。
7
+ let type_context = `
8
8
  /**
9
- * ---------------------- ctx.ext模块具备的方法 -----------------------------
10
- *
11
- * @typedef {object} ext
12
- * @property {function} extName(filename: string) - 解析文件扩展名。
13
- * @property {function} makeName(filename: string) - 生成唯一文件名,默认为时间字符串+随机数:2021-01-01_12-12-23_27789.jpg,filename主要用于获取扩展名。
14
- * @property {function} nrand(n, m) - 返回两个数之间的随机数。
15
- * @property {function} uuid() - 返回唯一字符串用于唯一ID,支持标准的8-4-4-4-12和短字符串8-2-2-4两种模式(传递参数为true)。
16
- * @property {function} timestr() - 默认返回年-月-日_时-分-秒,没有空格,方便保存和解析。
17
- * @property {function} sha1(text, encoding = 'hex')
18
- * @property {function} sha256(text, encoding = 'hex')
19
- * @property {function} sha512(text, encoding = 'hex')
20
- * @property {function} sm3(text, encoding = 'hex')
21
- * @property {function} hmacsha1(text, key, encoding = 'hex')
22
- * @property {function} pipe(filename: string, reply: object)
23
- *
24
- * 更多参考:{@link https://gitee.com/daoio/titbit/wikis/helper-function}
25
- */
26
- /**
27
- * --------------------------------- 请求上下文 -----------------------------------------
9
+ * ----------------------------- 请求上下文 -----------------------------------
28
10
  *
29
11
  * @typedef {object} context
30
12
  * @property {string} version - 协议版本,字符串类型,为'1.1' 或 '2' 或 '3'。
31
13
  * @property {number} major - 协议主要版本号,1、2、3分别表示HTTP/1.1 HTTP/2 HTTP/3。
32
14
  * @property {string} method - 请求类型,GET POST等HTTP请求类型,大写字母的字符串。
33
15
  * @property {string} path - 具体请求的路径,比如 /x/y。
34
- * @property {string} routepath - 实际执行请求的路由字符串,比如 /x/:id。
35
- * @property {boolean} isUpload - 是否为上传文件请求,此时就是检测消息头content-type是否为multipart/form-data格式。
16
+ * @property {string} routepath - 实际执行请求的路由字符串。
36
17
  * @property {object} box - 默认为空对象,可以添加任何属性值,用来动态传递给下一层组件需要使用的信息。
37
18
  * @property {object} query - url传递的参数。
38
19
  * @property {object} param - 路由参数。
39
- * @property {object} headers - 指向request.headers。
40
- * @property {object} files - 上传文件保存的信息。
41
- * @property {(object|string|buffer|null)} body - body请求体的数据,具体格式需要看content-type,一般为字符串或者对象,也可能是buffer。
42
- * @property {object} request HTTP/1.1 - 就是http模块request事件的参数IncomingMessage对象,HTTP/2 指向stream对象。
43
- * @property {object} reply - HTTP/1.1协议,指向response,HTTP/2 指向stream。
20
+ * @property {object} headers - 指向req.headers。
21
+ * @property {(object|string|buffer)} body - body请求体的数据,具体格式需要看content-type,一般为字符串或者对象,也可能是buffer。
22
+ * @property {object} req HTTP/1.1 - 就是http模块request事件的参数IncomingMessage对象,HTTP/2 指向stream对象。
23
+ * @property {object} res - HTTP/1.1协议,指向response,HTTP/2 指向stream
44
24
  * @property {object} service - 用于依赖注入的对象,指向app.service。
45
- * @property {function} moveFile(file: object) - 用来移动上传的文件到指定路径,file是通过getFile获取的文件对象。
46
- * @property {function} getFile(name: string, index = 0) - 根据上传名获取上传的文件,如果index是-1表示获取整个数组。
47
- * @property {function} sendHeader() - 发送消息头,针对http/2设计,http/1.1只是一个空函数,为了代码保持一致。
25
+ * @property {function} moveFile(file: object) - 用来移动上传的文件到指定路径。
26
+ * @property {function} getFile() - 根据上传名获取上传的文件。
48
27
  * @property {function} setHeader(key: string, value: string|array)
49
- * @property {function} send(body: string|object|buffer) - 设置要返回的body数据。
28
+ * @property {function} to(body: string|object|buffer) - 设置要返回的body数据。
50
29
  * @property {function} status(code: null | number) - 设置状态码,默认为null表示返回状态码。
51
- * @property {ext} ext - 指向ext模块,提供了一些助手函数,具体参考wiki。
52
- *
53
- * 更多参考:{@link https://gitee.com/daoio/titbit/blob/master/README.md#%E8%AF%B7%E6%B1%82%E4%B8%8A%E4%B8%8B%E6%96%87}
54
30
  */
55
31
  `
56
32
 
57
- let head_hint = `/**********************************************************************
58
- 提示:
59
- 表单提交或异步请求,对应于POST或PUT请求,对应函数post和put,提交的请求体数据通过 ctx.body 获取。
60
-
61
- 路由参数通过 ctx.param 获取,示例:let id = ctx.param.id
62
-
63
- url参数(?a=1&b=2)通过 ctx.query 获取,示例:let name = ctx.query.name
64
-
65
- 使用ctx.getFile(name)获取上传的文件,示例:let f = ctx.getFile('image')
66
- **********************************************************************/\n\n`
33
+ let head_hint = ''
67
34
 
68
35
  function fmt_ctx_param(text) {
69
36
  let ctx_param = `
@@ -88,16 +55,14 @@ function makeController(name) {
88
55
  + (simple_mode ? '' : head_hint)
89
56
  + `class ${modname} {\n\n`
90
57
  + ` constructor() {\n`
91
- + ` //param用于指定最后的路由参数,默认就是/:id\n`
92
- + ` //若要改变路由,则可以设置此属性,比如设置为/:name\n`
58
+ + ` //若要改变路由,则设置此属性,比如设置为/:name\n`
93
59
  + ` //this.param = '/:id'\n`
94
60
  + ` }\n\n`
95
- + ` //控制器类初始化后会执行此函数。\n`
96
- + ` //service默认是app.service,此参数通过titbit-loader初始化的initArgs选项进行控制。\n`
61
+ + ` //加载器初始化后会执行此函数。service默认是app.service。\n`
97
62
  + ` async init(service) {\n`
98
63
  + ` \n`
99
64
  + ` }\n\n`
100
- + (simple_mode ? '' : ` //以下方法,若不需要,要去掉,避免无意义的路由。\n`)
65
+ + (simple_mode ? '' : ` // 根据实际需要增加或删除请求方法。\n`)
101
66
  + `${fmt_ctx_param('获取资源具体内容')}`
102
67
  + ` async get(ctx) {\n\n`
103
68
  + ` }\n`
@@ -112,7 +77,7 @@ function makeController(name) {
112
77
  + ` }\n`
113
78
  + `${fmt_ctx_param('删除资源')}`
114
79
  + ` async _delete(ctx) {\n\n`
115
- + ` }\n`
80
+ + ` }\n\n`
116
81
  + `}\n\nmodule.exports = ${modname}\n`
117
82
  + (simple_mode ? '' : `${type_context}`)
118
83
 
package/demo/allow.js CHANGED
@@ -1,8 +1,21 @@
1
1
  'use strict';
2
2
 
3
- const titbit = require('../src/topbit.js');
4
-
5
- const app = new titbit({
3
+ const Topbit = require('../src/topbit.js');
4
+ const npargv = Topbit.npargv
5
+
6
+ let {args} = npargv({
7
+ '--loadtype': {
8
+ name: 'load',
9
+ default: 'text',
10
+ limit: ['text', 'json', 'orgjson']
11
+ },
12
+ '--loadstdio': {
13
+ name: 'loadstdio',
14
+ default: false
15
+ }
16
+ })
17
+
18
+ const app = new Topbit({
6
19
  debug : true,
7
20
  allow : new Set(['127.0.0.1']),
8
21
  maxIPRequest: 2,
@@ -10,11 +23,11 @@ const app = new titbit({
10
23
  useLimit: true,
11
24
  maxConn: 2000,
12
25
  //http2: true,
13
- showLoadInfo: true,
14
- loadInfoType : 'text',
26
+ loadMonitor: true,
27
+ loadInfoType : args.load,
15
28
  globalLog : true,
16
29
  logType: 'stdio',
17
- loadInfoFile : '/tmp/loadinfo.log'
30
+ loadInfoFile : args.loadstdio ? '' : '/tmp/loadinfo.log',
18
31
  });
19
32
 
20
33
  app.use(async (c, next) => {
@@ -65,7 +78,12 @@ app.get('/', async c => {
65
78
  }, 'home');
66
79
 
67
80
  app.get('/test', async c => {
68
- c.to(c.name);
81
+ //await c.ext.delay(10)
82
+ let sum = 0
83
+ for (let i = 0; i < 1000000; i++) {
84
+ sum += Math.random() * i;
85
+ }
86
+ c.to({sum});
69
87
  }, {group: 'test', name : 'test'});
70
88
 
71
89
  app.post('/test', async c => {
@@ -95,4 +113,6 @@ app.use(async (c, next) => {
95
113
  }, {pre: true, method: 'POST', name: 'transmit'});
96
114
 
97
115
 
98
- app.daemon(2034, 2);
116
+ app.autoWorker(3)
117
+
118
+ app.daemon(2034, 1)
@@ -0,0 +1,78 @@
1
+ 'use strict';
2
+
3
+ const Topbit = require('../src/topbit.js');
4
+ const npargv = Topbit.npargv
5
+
6
+ let {args} = npargv({
7
+ '--loadtype': {
8
+ name: 'loadtype',
9
+ default: 'text',
10
+ limit: ['text', 'json', 'orgjson', 'obj', 'orgobj']
11
+ },
12
+ '--loadstdio': {
13
+ name: 'loadstdio',
14
+ default: false
15
+ }
16
+ })
17
+
18
+ console.log(args)
19
+
20
+ const app = new Topbit({
21
+ debug : true,
22
+ allow : new Set(['127.0.0.1']),
23
+ maxIPRequest: 2,
24
+ unitTime: 10,
25
+ useLimit: true,
26
+ maxConn: 2000,
27
+ //http2: true,
28
+ loadMonitor: true,
29
+ loadInfoType : args.loadtype,
30
+ globalLog : false,
31
+ logType: 'stdio',
32
+ loadInfoFile : args.loadstdio ? '' : '/tmp/topbit-loadinfo.log',
33
+ maxLoadRate: 0.56
34
+ });
35
+
36
+ app.get('/', async c => {
37
+ c.to('ok');
38
+ }, 'home');
39
+
40
+ app.get('/test', async c => {
41
+ //await c.ext.delay(10)
42
+ let sum = 0
43
+ for (let i = 0; i < 90000; i++) {
44
+ sum += Math.random() * i;
45
+ }
46
+ c.to({sum});
47
+ }, {group: 'test', name : 'test'});
48
+
49
+ app.post('/test', async c => {
50
+ c.to(c.body);
51
+ }, {group: 'test', name : 'test-post'});
52
+
53
+ app.post('/transmit', async c => {
54
+ c.to('ok');
55
+ }, 'transmit');
56
+
57
+ app.use(async (c, next) => {
58
+ let total = 0;
59
+
60
+ c.box.dataHandle = (data) => {
61
+ total += data.length;
62
+ if (total > 32) {
63
+ c.response.statusCode = 413;
64
+ c.response.end('太多了,限制32字节以内');
65
+ return ;
66
+ }
67
+ };
68
+
69
+ await next(c);
70
+
71
+ console.log(total, 'bytes');
72
+
73
+ }, {pre: true, method: 'POST', name: 'transmit'});
74
+
75
+
76
+ app.autoWorker(4)
77
+
78
+ app.daemon(2034, 1)
@@ -35,8 +35,8 @@ Built entirely on Node.js native `crypto`, supports:
35
35
  ### 3. 30-Second Quick Start
36
36
 
37
37
  ```js
38
- // middleware/@token.js
39
- const TopbitToken = require('topbit-token')
38
+ const Topbit = require('topbit')
39
+ const TopbitToken = Topbit.Token
40
40
 
41
41
  const token = new TopbitToken({
42
42
  key : 'your-very-strong-32-byte-secret!!',
@@ -79,6 +79,9 @@ async post(c) {
79
79
  ### 5. Advanced: Multi-Key + Instant Revocation
80
80
 
81
81
  ```js
82
+ const Topbit = require('topbit')
83
+ const TopbitToken = Topbit.Token
84
+
82
85
  const token = new TopbitToken({ key: 'current-master-key' })
83
86
 
84
87
  // Add multiple key versions
@@ -112,8 +115,8 @@ Frontend just replaces the old one → seamless “never expire” experience.
112
115
  ### 7. Production Recommended Setup
113
116
 
114
117
  ```js
115
- // middleware/@auth.js
116
- const TopbitToken = require('topbit-token')
118
+ const Topbit = require('topbit')
119
+ const TopbitToken = Topbit.Token
117
120
 
118
121
  const token = new TopbitToken({
119
122
  algorithm : 'aes-256-gcm',
@@ -36,8 +36,8 @@ TopbitToken 是专为 Topbit 框架打造的零依赖、极简、高安全的加
36
36
  ### 三、快速上手(30 秒搞定登录认证)
37
37
 
38
38
  ```js
39
- // middleware/@token.js
40
- const TopbitToken = require('topbit-token')
39
+ const Topbit = require('topbit')
40
+ const TopbitToken = Topbit.Token
41
41
 
42
42
  const token = new TopbitToken({
43
43
  key : 'your-32-byte-secret-key-here!!', // 必须 32 字节(AES-256)
@@ -89,6 +89,9 @@ token.mid() 会自动把验证后的用户信息挂到 c.user
89
89
  ### 五、高级功能:多密钥 + 即时失效(防泄漏神器)
90
90
 
91
91
  ```js
92
+ const Topbit = require('topbit')
93
+ const TopbitToken = Topbit.Token
94
+
92
95
  const token = new TopbitToken({
93
96
  key: 'master-key-2025-01-01',
94
97
  expires: 3600 * 24 * 30
@@ -113,6 +116,9 @@ token.tokenIds = []
113
116
  ### 六、自动刷新 Token 机制
114
117
 
115
118
  ```js
119
+ const Topbit = require('topbit')
120
+ const TopbitToken = Topbit.Token
121
+
116
122
  const token = new TopbitToken({
117
123
  expires: 3600 * 24, // 24小时有效
118
124
  refresh: true // 开启自动刷新
@@ -128,8 +134,8 @@ const token = new TopbitToken({
128
134
  ### 七、最佳实践(生产级推荐配置)
129
135
 
130
136
  ```js
131
- // middleware/@auth.js
132
- const TopbitToken = require('topbit-token')
137
+ const Topbit = require('topbit')
138
+ const TopbitToken = Topbit.Token
133
139
 
134
140
  const token = new TopbitToken({
135
141
  algorithm : 'aes-256-gcm',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "topbit",
3
- "version": "3.0.7",
3
+ "version": "3.1.0",
4
4
  "description": "A Server-side web framework support http/1.1 and http/2",
5
5
  "main": "src/topbit.js",
6
6
  "directories": {
package/src/monitor.js CHANGED
@@ -5,6 +5,8 @@ const os = require('node:os');
5
5
  const fs = require('node:fs');
6
6
  const process = require('node:process');
7
7
 
8
+ const hrtime = process.hrtime
9
+
8
10
  class Monitor {
9
11
 
10
12
  constructor(options) {
@@ -15,6 +17,8 @@ class Monitor {
15
17
 
16
18
  this.workerCount = options.workerCount
17
19
 
20
+ this.isLoadObj = ['obj', 'orgobj'].includes(this.config.loadInfoType)
21
+
18
22
  this.rundata.cpus = os.cpus().length
19
23
 
20
24
  this.loadCount = 0
@@ -24,9 +28,9 @@ class Monitor {
24
28
 
25
29
  this.loadCache = null
26
30
 
27
- this.cpuLastTime = Date.now() - 1
31
+ this.cpuLastTime = hrtime.bigint() - 1n
28
32
 
29
- this.cpuNowTime = Date.now()
33
+ this.cpuNowTime = hrtime.bigint()
30
34
 
31
35
  //this.cpuPercentFactor = 10 * this.rundata.cpus;
32
36
  this.cpuHighRatio = 0
@@ -45,10 +49,36 @@ class Monitor {
45
49
 
46
50
  this.life = 20
47
51
 
48
- this.maxRate = parseInt(this.config.maxLoadRate * 10)
52
+ this.maxRate = this.config.maxLoadRate
49
53
 
50
54
  this.loadfd = null
51
55
 
56
+ this.ipcMsgCache = {
57
+ type: '_load',
58
+ pid: 0,
59
+ cpu: null,
60
+ cputm: 0,
61
+ mem: null,
62
+ conn: 0
63
+ }
64
+
65
+ this.loadjson = {
66
+ masterPid : process.pid,
67
+ listen : `${this.rundata.host}:${this.rundata.port}`,
68
+ CPULoadavg : {
69
+ '1m' : '0',
70
+ '5m' : '0',
71
+ '15m' : '0'
72
+ },
73
+ https: this.config.https,
74
+ http2: this.config.http2,
75
+ workers : []
76
+ }
77
+
78
+ queueMicrotask(() => {
79
+ this.loadjson.listen = `${this.rundata.host}:${this.rundata.port}`
80
+ })
81
+
52
82
  }
53
83
 
54
84
  autoWorker() {
@@ -65,20 +95,20 @@ class Monitor {
65
95
  for (let k in this.workers) {
66
96
  cpuratio = (this.workers[k].cpu.user + this.workers[k].cpu.system) / this.workers[k].cputm
67
97
 
68
- if (cpuratio >= this.maxRate) {
69
- this.cpuHighRatio += 1
98
+ if (cpuratio > this.maxRate) {
99
+ this.cpuHighRatio++
70
100
  } else {
71
101
  if (this.cpuHighRatio > 0) {
72
- this.cpuHighRatio -= 1
102
+ this.cpuHighRatio--
73
103
  }
104
+
74
105
  break
75
106
  }
76
107
  }
77
108
  }
78
109
 
79
110
  if (this.cpuHighRatio >= this.workerCount.cur) {
80
-
81
- this.cpuHighRatio -= 1
111
+ this.cpuHighRatio--
82
112
 
83
113
  if (this.workerCount.cur < this.workerCount.max) {
84
114
  if (this.workerCount.canAutoFork) {
@@ -106,7 +136,7 @@ class Monitor {
106
136
 
107
137
  if (this.workerCount.cur > this.workerCount.total) {
108
138
  if (this.cooling > 0) {
109
- this.cooling -= 1
139
+ this.cooling--
110
140
  } else {
111
141
  for (let k in this.workers) {
112
142
  if (this.workers[k].conn === 0) {
@@ -169,12 +199,16 @@ class Monitor {
169
199
  if (will_disconnect) return;
170
200
 
171
201
  this.cpuLastTime = this.cpuNowTime
172
- this.cpuNowTime = Date.now()
202
+ this.cpuNowTime = hrtime.bigint()
203
+ let diffNs = this.cpuNowTime - this.cpuLastTime
204
+ let diffUs = (Number(diffNs) / 1000) + 0.01
173
205
 
206
+ //此处是计算微秒的cpu变化,而计算负载正好按照微秒进行
174
207
  this.rundata.cpuTime = process.cpuUsage(this.rundata.cpuLast)
208
+
175
209
  if (mem_count < MAX_MEM_COUNT) {
176
210
  this.rundata.mem.rss = process.memoryUsage.rss()
177
- mem_count += 1
211
+ mem_count++
178
212
  } else {
179
213
  this.rundata.mem = process.memoryUsage()
180
214
  mem_count = 0
@@ -182,16 +216,17 @@ class Monitor {
182
216
 
183
217
  this.rundata.mem.total = this.rundata.mem.rss + this.rundata.mem.external
184
218
 
185
- process.send({
186
- type : '_load',
187
- pid : process.pid,
188
- cpu : this.rundata.cpuTime,
189
- cputm : this.cpuNowTime - this.cpuLastTime,
190
- mem : this.rundata.mem,
191
- conn : this.rundata.conn
192
- }, err => {
193
- err && this.config.errorHandle(err, '--ERR-WORKER-SEND--')
194
- //if (err.code === 'ERR_IPC_CHANNEL_CLOSED') {}
219
+ const msg = this.ipcMsgCache
220
+ msg.pid = process.pid
221
+ msg.cpu = this.rundata.cpuTime
222
+ msg.cputm = diffUs
223
+ msg.mem = this.rundata.mem
224
+ msg.conn = this.rundata.conn
225
+
226
+ process.send(msg, err => {
227
+ if (err) this.config.errorHandle(err, '--ERR-WORKER-SEND--')
228
+ // 忽略管道关闭错误
229
+ //if (err && err.code !== 'ERR_IPC_CHANNEL_CLOSED') {}
195
230
  })
196
231
 
197
232
  this.rundata.cpuLast = process.cpuUsage()
@@ -201,7 +236,7 @@ class Monitor {
201
236
  }
202
237
 
203
238
  showLoadInfo(w, id) {
204
- if (this.config.loadInfoType == '--null') {
239
+ if (!this.config.loadInfoType || this.config.loadInfoType === 'null') {
205
240
  return
206
241
  }
207
242
 
@@ -225,31 +260,30 @@ class Monitor {
225
260
 
226
261
  this.loadCount += 1;
227
262
  if (this.loadCount < this.workerCount.cur) {
228
- return ;
263
+ return
229
264
  }
230
265
 
231
- let loadText = this.fmtLoadInfo( this.config.loadInfoType );
266
+ let load_info = this.fmtLoadInfo(this.config.loadInfoType);
232
267
 
233
268
  if (this.config.loadInfoFile === '--mem') {
234
- this.loadCache = loadText;
235
- }
236
- else if (this.loadfd !== null) {
237
-
238
- fs.write(this.loadfd, loadText, 0, (err, bytes, data) => {
239
- err && this.config.debug && this.config.errorHandle(err, '--ERR-WRITE-FILE--');
240
- if (!err) {
241
- fs.ftruncate(this.loadfd, bytes, e => {});
242
- }
243
- });
244
-
269
+ this.loadCache = load_info;
270
+ } else if (this.loadfd !== null) {
271
+ fs.write(this.loadfd, this.isLoadObj ? JSON.stringify(load_info) : load_info, 0,
272
+ (err, bytes, data) => {
273
+ if (err && this.config.debug) this.config.errorHandle(err, '--ERR-WRITE-FILE--');
274
+
275
+ if (!err) {
276
+ fs.ftruncate(this.loadfd, bytes, e => {});
277
+ }
278
+ }
279
+ );
245
280
  } else if (process.ppid > 1 && !this.config.daemon && !this.config.loadInfoFile) {
246
281
  console.clear();
247
282
  //只有没有开启守护进程才会输出到屏幕
248
- console.log(loadText);
283
+ console.log(load_info);
249
284
  }
250
285
 
251
286
  this.loadCount = 0;
252
-
253
287
  }
254
288
 
255
289
  checkMem(w, msg) {
@@ -292,26 +326,16 @@ class Monitor {
292
326
  let p = null;
293
327
 
294
328
  for (let id in this.workers) {
295
-
296
329
  p = this.workers[id];
297
-
298
330
  tmp = [(`${p.pid}`).padEnd(9, ' ')];
299
-
300
331
  t = p.cpu.user + p.cpu.system;
301
-
302
- tmp.push((( t/(p.cputm * 10) ).toFixed(2) + '%').padEnd(8, ' '),
303
-
304
- (`${p.conn}`).padEnd(8, ' '),
305
-
306
- (p.mem.rss / 1048576).toFixed(1).padEnd(8, ' '),
307
-
308
- (p.mem.heapTotal / 1048576).toFixed(1).padEnd(8, ' '),
309
-
310
- (p.mem.heapUsed / 1048576).toFixed(1).padEnd(8, ' '),
311
-
312
- (p.mem.external / 1048576).toFixed(1).padEnd(9, ' '),
313
-
314
- (p.mem.total / 1048576).toFixed(1)
332
+ tmp.push((( t * 100 / p.cputm ).toFixed(2) + '%').padEnd(8, ' '),
333
+ (`${p.conn}`).padEnd(8, ' '),
334
+ (p.mem.rss / 1048576).toFixed(1).padEnd(8, ' '),
335
+ (p.mem.heapTotal / 1048576).toFixed(1).padEnd(8, ' '),
336
+ (p.mem.heapUsed / 1048576).toFixed(1).padEnd(8, ' '),
337
+ (p.mem.external / 1048576).toFixed(1).padEnd(9, ' '),
338
+ (p.mem.total / 1048576).toFixed(1)
315
339
  );
316
340
 
317
341
  cols.push(tmp.join(''));
@@ -323,56 +347,44 @@ class Monitor {
323
347
  +`HTTPS: ${this.config.https ? 'true' : 'false'}; HTTP/2: ${this.config.http2 ? 'true' : 'false'}\n`;
324
348
  }
325
349
 
326
- if (type === 'json') {
327
- let loadjson = {
328
- masterPid : process.pid,
329
- listen : `${this.rundata.host}:${this.rundata.port}`,
330
- CPULoadavg : {
331
- '1m' : oavg[0].toFixed(2),
332
- '5m' : oavg[1].toFixed(2),
333
- '15m' : oavg[2].toFixed(2)
334
- },
335
- https: this.config.https,
336
- http2: this.config.http2,
337
- workers : []
338
- };
350
+ if (type === 'obj') {
351
+ let lj = this.loadjson
352
+ lj.CPULoadavg['1m'] = oavg[0].toFixed(2)
353
+ lj.CPULoadavg['5m'] = oavg[1].toFixed(2)
354
+ lj.CPULoadavg['15m'] = oavg[2].toFixed(2)
355
+ lj.workers = []
356
+
339
357
  for (let id in this.workers) {
340
358
  p = this.workers[id];
341
359
 
342
- loadjson.workers.push({
343
- pid : p.pid,
344
- cpu : `${((p.cpu.user + p.cpu.system)/ (p.cputm * 10) ).toFixed(2)}%`,
345
- cputm : p.cputm,
346
- mem : {
360
+ lj.workers.push({
361
+ pid: p.pid,
362
+ cpu: `${((p.cpu.user + p.cpu.system) * 100 / p.cputm).toFixed(2)}%`,
363
+ cputm: p.cputm,
364
+ mem: {
347
365
  rss : (p.mem.rss / 1048576).toFixed(1),
348
366
  heap : (p.mem.heapTotal / 1048576).toFixed(1),
349
367
  heapused : (p.mem.heapUsed / 1048576).toFixed(1),
350
368
  external : (p.mem.external / 1048576).toFixed(1),
351
369
  },
352
370
  conn : p.conn
353
- });
371
+ })
354
372
  }
355
- return JSON.stringify(loadjson);
373
+
374
+ return lj
356
375
  }
357
376
 
358
- if (type === 'orgjson') {
359
- let loadjson = {
360
- masterPid : process.pid,
361
- listen : `${this.rundata.host}:${this.rundata.port}`,
362
- CPULoadavg : {
363
- '1m' : oavg[0].toFixed(2),
364
- '5m' : oavg[1].toFixed(2),
365
- '15m' : oavg[2].toFixed(2)
366
- },
367
- https: this.config.https,
368
- http2: this.config.http2,
369
- workers : this.workers
370
- };
371
-
372
- return JSON.stringify(loadjson);
377
+ if (type === 'orgobj') {
378
+ let lj = this.loadjson
379
+ lj.CPULoadavg['1m'] = oavg[0].toFixed(2)
380
+ lj.CPULoadavg['5m'] = oavg[1].toFixed(2)
381
+ lj.CPULoadavg['15m'] = oavg[2].toFixed(2)
382
+ lj.workers = this.workers
383
+
384
+ return lj
373
385
  }
374
386
 
375
- return '';
387
+ return null
376
388
  }
377
389
 
378
390
  }
package/src/topbit.js CHANGED
@@ -164,7 +164,7 @@ class Topbit {
164
164
  * - maxFormLength 在multipart/form-data类型提交数据时,单个form项的最大值,默认为1000000字节。
165
165
  * - errorHandle 收集错误并处理的函数,默认是输出错误信息,接收参数为两个,第一个是错误信息,第二个是错误的名字描述。
166
166
  * - ignoreSlash 忽略末尾的/,默认为true。
167
- * - maxLoadRate 在自动创建子进程平衡负载模式,最大子进程负载率限制:25 ~ 98表示百分比。
167
+ * - maxLoadRate 在自动创建子进程平衡负载模式,最大子进程负载率限制:0.150.98
168
168
  * - streamTimeout http2Stream超时,若不设置,默认采用timeout的设置。
169
169
  */
170
170
  constructor(options={}) {
@@ -272,7 +272,7 @@ class Topbit {
272
272
 
273
273
  requestTimeout: 65_000,
274
274
 
275
- maxLoadRate: 75
275
+ maxLoadRate: 0.75
276
276
  };
277
277
 
278
278
  this.whoami = 'topbit';
@@ -343,11 +343,11 @@ class Topbit {
343
343
  break;
344
344
 
345
345
  case 'monitorTimeSlice':
346
- optionsCheck(k, options[k], this.config, {type: 'number', min: 5, max: 5000});
346
+ optionsCheck(k, options[k], this.config, {type: 'number', min: 5, max: 10000});
347
347
  break;
348
-
348
+
349
349
  case 'maxLoadRate':
350
- optionsCheck(k, options[k], this.config, {type: 'number', min: 25, max: 98});
350
+ optionsCheck(k, options[k], this.config, {type: 'number', min: 0.15, max: 0.98});
351
351
  break;
352
352
 
353
353
  case 'maxFiles':
@@ -364,13 +364,13 @@ class Topbit {
364
364
  case 'logHistory':
365
365
  optionsCheck(k, options[k], this.config, {type: 'number', min: 1});
366
366
  break;
367
-
367
+
368
368
  case 'logType':
369
369
  optionsCheck(k, options[k], this.config, {list: ['stdio','file', '']});
370
370
  break;
371
371
 
372
372
  case 'loadInfoType':
373
- optionsCheck(k, options[k], this.config, {list: ['--null', 'text', 'json', 'orgjson']});
373
+ optionsCheck(k, options[k], this.config, {list: [null, 'null', 'text', 'obj', 'orgobj']});
374
374
  break;
375
375
 
376
376
  case 'loadMonitor':
@@ -1110,7 +1110,7 @@ class Topbit {
1110
1110
  total: 0
1111
1111
  },
1112
1112
  cpu: {user:0, system:0},
1113
- cputm : 1000
1113
+ cputm : 1000000
1114
1114
  };
1115
1115
 
1116
1116
  });