topbit 3.1.9 → 3.2.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
@@ -848,8 +848,6 @@ app.run(1234)
848
848
  //最大解析的文件数量
849
849
  maxFiles : 12,
850
850
 
851
- daemon : false, //开启守护进程
852
-
853
851
  /*
854
852
  开启守护进程模式后,如果设置路径不为空字符串,则会把pid写入到此文件,可用于服务管理。
855
853
  */
@@ -972,9 +970,9 @@ app.run(1234)
972
970
  this.config.debug && console.error(errname, err)
973
971
  },
974
972
 
975
- //最大负载率百分比,默认为75表示当CPU使用率超过75%,则会自动创建子进程。
973
+ //最大负载率百分比,默认为0.75表示当CPU使用率超过75%,则会自动创建子进程。
976
974
  //必须通过autoWorker开启自动负载模式才有效。
977
- maxLoadRate: 75,
975
+ maxLoadRate: 0.75,
978
976
 
979
977
  //http2协议的http2Stream超时,若不设置,-1表示和timeout一致。
980
978
  streamTimeout: -1,
package/README.md CHANGED
@@ -812,8 +812,6 @@ Full configuration options for app initialization are as follows. Please read th
812
812
  // Max number of files to parse
813
813
  maxFiles : 12,
814
814
 
815
- daemon : false, // Enable daemon mode
816
-
817
815
  /*
818
816
  After enabling daemon mode, if path is not empty string, pid is written to this file. Used for service management.
819
817
  */
@@ -936,9 +934,9 @@ Full configuration options for app initialization are as follows. Please read th
936
934
  this.config.debug && console.error(errname, err)
937
935
  },
938
936
 
939
- // Max load rate percentage. Default 75 means if CPU usage > 75%, automatically create child process.
937
+ // Max load rate percentage. Default 0.75 means if CPU usage > 75%, automatically create child process.
940
938
  // Must enable auto load mode via autoWorker.
941
- maxLoadRate: 75,
939
+ maxLoadRate: 0.75,
942
940
 
943
941
  // http2 protocol http2Stream timeout. If not set, -1 means consistent with timeout.
944
942
  streamTimeout: -1,
package/demo/loader.js CHANGED
@@ -4,26 +4,50 @@ process.chdir(__dirname)
4
4
 
5
5
  let Topbit = require('../src/topbit.js')
6
6
  let {Loader} = Topbit
7
+ const npargv = Topbit.npargv
8
+
9
+ let {args} = npargv({
10
+ '--loadtype': {
11
+ name: 'loadtype',
12
+ default: 'text',
13
+ limit: ['text', 'json', 'orgjson', 'obj', 'orgobj']
14
+ },
15
+ '--load': {
16
+ name: 'load',
17
+ default: false
18
+ },
19
+ '-w': {
20
+ name: 'worker',
21
+ default: 2,
22
+ min: 1,
23
+ max: 5
24
+ }
25
+ })
7
26
 
8
27
  let app = new Topbit({
9
28
  debug: true,
10
- loadInfoFile: '--mem',
29
+ loadMonitor: true,
30
+ loadInfoType : args.loadtype,
31
+ globalLog : false,
32
+ logType: 'stdio',
33
+ loadInfoFile : args.load ? '' : '/tmp/topbit-loadinfo.log',
34
+ maxLoadRate: 0.6
11
35
  })
12
36
 
13
37
  if (app.isWorker) {
14
38
  app.get('/', async ctx => {
15
39
  ctx.ok('ok')
16
40
  })
17
-
18
- let ld = new Loader()
19
-
20
- ld.init(app)
21
41
  }
22
42
 
23
- app.sched('none')
24
- .autoWorker(12)
25
- .printServInfo(100)
26
- .daemon(1234, 5)
43
+ let ld = new Loader()
44
+
45
+ ld.daemonInit(app, () => {
46
+ app.sched('none')
47
+ .autoWorker(12)
48
+ .printServInfo(100)
49
+ .daemon(1234, args.worker)
50
+ })
27
51
 
28
52
  //console.log(app.midware.midGroup)
29
53
  //console.log({...app.router})
package/demo/monitor.js CHANGED
@@ -9,8 +9,8 @@ let {args} = npargv({
9
9
  default: 'text',
10
10
  limit: ['text', 'json', 'orgjson', 'obj', 'orgobj']
11
11
  },
12
- '--loadstdio': {
13
- name: 'loadstdio',
12
+ '--load': {
13
+ name: 'load',
14
14
  default: false
15
15
  },
16
16
 
@@ -32,7 +32,7 @@ const app = new Topbit({
32
32
  loadInfoType : args.loadtype,
33
33
  globalLog : false,
34
34
  logType: 'stdio',
35
- loadInfoFile : args.loadstdio ? '' : '/tmp/topbit-loadinfo.log',
35
+ loadInfoFile : args.load ? '' : '/tmp/topbit-loadinfo.log',
36
36
  maxLoadRate: 0.56
37
37
  });
38
38
 
@@ -75,7 +75,6 @@ app.use(async (c, next) => {
75
75
 
76
76
  }, {pre: true, method: 'POST', name: 'transmit'});
77
77
 
78
-
79
78
  app.autoWorker(4)
80
79
 
81
- app.daemon(2034, 1)
80
+ app.printServInfo().daemon(2034, 1)
@@ -101,7 +101,9 @@ new Loader({
101
101
  const UserModel = require('./model/user')
102
102
  service.userModel = new UserModel(service)
103
103
  }
104
- }).init(app)
104
+ }).init(app, () => {
105
+ app.run(1234)
106
+ })
105
107
  ```
106
108
 
107
109
  ---
@@ -236,7 +238,9 @@ new Loader({
236
238
  service[name + 'Model'] = new Model(service)
237
239
  }
238
240
  }
239
- }).init(app)
241
+ }).daemonInit(app, () => {
242
+ app.daemon(1234, 2)
243
+ })
240
244
  ```
241
245
 
242
246
  ---
@@ -99,7 +99,9 @@ new Loader({
99
99
  const UserModel = require('./model/user')
100
100
  service.userModel = new UserModel(service)
101
101
  }
102
- }).init(app)
102
+ }).init(app, () => {
103
+ app.run(1234)
104
+ })
103
105
  ```
104
106
 
105
107
  ---
@@ -236,7 +238,9 @@ new Loader({
236
238
  service[name + 'Model'] = new Model(service)
237
239
  }
238
240
  }
239
- }).init(app)
241
+ }).daemonInit(app, () => {
242
+ app.daemon(1234, 2)
243
+ })
240
244
  ```
241
245
 
242
246
  ---
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "topbit",
3
- "version": "3.1.9",
3
+ "version": "3.2.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": {
@@ -17,8 +17,8 @@ class TopbitLoader {
17
17
  let appDir = '.';
18
18
 
19
19
  this.globalMidTable = [];
20
- this.groupMidTable = {};
21
- this.fileMidTable = {};
20
+ this.groupMidTable = Object.create(null);
21
+ this.fileMidTable = Object.create(null);
22
22
 
23
23
  if (typeof options !== 'object') {
24
24
  options = {};
@@ -159,10 +159,7 @@ class TopbitLoader {
159
159
  }
160
160
  }
161
161
 
162
- /**
163
- * 初始化入口 (Async)
164
- */
165
- async init(app) {
162
+ async _coreinit(app) {
166
163
  // 注入应用基础信息到 service,供 Controller 或 Model 使用
167
164
  Object.defineProperties(app.service, {
168
165
  __prepath__: {
@@ -189,6 +186,26 @@ class TopbitLoader {
189
186
  app.service.__topbit_loader__ = true;
190
187
  }
191
188
 
189
+ /**
190
+ * 初始化入口 (Async),提供回调函数在完成后执行
191
+ */
192
+ async init(app, cb) {
193
+ await this._coreinit(app);
194
+ if (cb && typeof cb === 'function') {
195
+ cb(app);
196
+ }
197
+ }
198
+
199
+ async daemonInit(app, cb) {
200
+ if (app.isWorker) {
201
+ await this._coreinit(app);
202
+ }
203
+
204
+ if (cb && typeof cb === 'function') {
205
+ cb(app);
206
+ }
207
+ }
208
+
192
209
  loadController(app) {
193
210
  if (app.service.__topbit_loader__ && !this.config.multi) {
194
211
  outWarning('您已经使用topbit-loader加载过路由,多次加载容易导致路由冲突,重复操作将会被终止。');
package/src/topbit.js CHANGED
@@ -140,7 +140,6 @@ class Topbit {
140
140
  * - globalLog {bool} 启用全局日志。
141
141
  * - maxBody {number} 表示POST/PUT提交表单的最大字节数,包括上传文件。
142
142
  * - maxFiles {number} 最大上传文件数量,超过则不处理。
143
- * - daemon {bool} 启用守护进程模式。
144
143
  * - pidFile {string} 保存Master进程PID的文件路径。
145
144
  * - logFile {string} 日志文件。
146
145
  * - errorLogFile {string} 错误日志文件。
@@ -172,6 +171,9 @@ class Topbit {
172
171
  throw new Error('topbit遵循单例模式,不能构造多次。你可以在多进程或多线程中构造新的实例。');
173
172
 
174
173
  __instance__ += 1;
174
+
175
+ this._is_listening = false;
176
+ this._is_daemon_listening = false;
175
177
 
176
178
  this.config = {
177
179
  //此配置表示POST/PUT提交表单的最大字节数,也是上传文件的最大限制,
@@ -856,71 +858,6 @@ class Topbit {
856
858
  clearService() {
857
859
  for (let k in this.service) delete this.service[k];
858
860
  }
859
-
860
- /**
861
- * 根据配置情况确定运行HTTP/1.1还是HTTP/2
862
- * @param {number} port 端口号
863
- * @param {string} host IP地址,可以是IPv4或IPv6
864
- * 0.0.0.0 对应使用IPv6则是::
865
- */
866
- run(port=2368, host='0.0.0.0') {
867
- if (typeof port === 'object') {
868
- if (port.host && typeof port.host === 'string') host = port.host;
869
- if (port.port && typeof port.port === 'number' && port.port > 0 && port.port <= 65535) port = port.port;
870
- }
871
-
872
- if (this.config.server.SNICallback && typeof this.config.server.SNICallback === 'function' && !this.config.https) {
873
- this.config.https = true;
874
- }
875
-
876
- this.router.argsRouteSort();
877
-
878
- this.rundata.host = (typeof port == 'number' ? host : '');
879
- this.rundata.port = port;
880
-
881
- //如果没有添加路由则添加默认路由
882
- if (this.router.count === 0) {
883
- this.router.get('/*', async c => {
884
- c.setHeader('content-type', 'text/html; charset=utf-8').to(_topbit_home_page)
885
- })
886
- }
887
-
888
- //如果发现更改了service指向,则让this.httpServ.service重新指向this.service。
889
- if (this.service !== this.httpServ.service) {
890
- this.httpServ.service = this.service;
891
- }
892
-
893
- this.midware.addFromCache();
894
-
895
- this.config.parseBody && this.add(this.bodyparser);
896
-
897
- this.add(this.httpServ);
898
-
899
- let m = null;
900
- while((m = this.__pre_mids__.pop()) !== undefined) {
901
- this.add(m.callback, m.options);
902
- }
903
-
904
- //必须放在最后,用于返回最终数据。
905
- this.midware.addFinal();
906
-
907
- if (this.config.useLimit) {
908
- let connlimit = new this.connfilter(this.limit, this.rundata);
909
- this.on('connection', connlimit.callback);
910
- } else {
911
- this.on('connection', (sock) => {
912
- this.rundata.conn++;
913
- sock.on('close', () => {
914
- this.rundata.conn--;
915
- });
916
-
917
- });
918
- }
919
-
920
- this.server = this.httpServ.run(port, host);
921
- return this.server;
922
- }
923
- //run end
924
861
 
925
862
  /**
926
863
  *
@@ -1148,7 +1085,6 @@ class Topbit {
1148
1085
  cpu: {user:0, system:0},
1149
1086
  cputm : 1000000
1150
1087
  };
1151
-
1152
1088
  });
1153
1089
 
1154
1090
  let exitTip = () => {
@@ -1218,6 +1154,76 @@ class Topbit {
1218
1154
 
1219
1155
  }
1220
1156
 
1157
+ /**
1158
+ * 根据配置情况确定运行HTTP/1.1还是HTTP/2
1159
+ * @param {number} port 端口号
1160
+ * @param {string} host IP地址,可以是IPv4或IPv6
1161
+ * 0.0.0.0 对应使用IPv6则是::
1162
+ */
1163
+ run(port=2368, host='0.0.0.0') {
1164
+ if (this._is_listening) return this.server;
1165
+
1166
+ if (typeof port === 'object') {
1167
+ if (port.host && typeof port.host === 'string') host = port.host;
1168
+ if (port.port && typeof port.port === 'number' && port.port > 0 && port.port <= 65535) port = port.port;
1169
+ }
1170
+
1171
+ if (this.config.server.SNICallback && typeof this.config.server.SNICallback === 'function' && !this.config.https) {
1172
+ this.config.https = true;
1173
+ }
1174
+
1175
+ this._is_listening = true;
1176
+
1177
+ this.router.argsRouteSort();
1178
+
1179
+ this.rundata.host = (typeof port == 'number' ? host : '');
1180
+ this.rundata.port = port;
1181
+
1182
+ //如果没有添加路由则添加默认路由
1183
+ if (this.router.count === 0) {
1184
+ this.router.get('/*', async c => {
1185
+ c.setHeader('content-type', 'text/html; charset=utf-8').to(_topbit_home_page)
1186
+ })
1187
+ }
1188
+
1189
+ //如果发现更改了service指向,则让this.httpServ.service重新指向this.service。
1190
+ if (this.service !== this.httpServ.service) {
1191
+ this.httpServ.service = this.service;
1192
+ }
1193
+
1194
+ //必须要坚持先加载再listen的原则。
1195
+ this.midware.addFromCache();
1196
+
1197
+ this.config.parseBody && this.add(this.bodyparser);
1198
+
1199
+ this.add(this.httpServ);
1200
+
1201
+ let m = null;
1202
+ while((m = this.__pre_mids__.pop()) !== undefined) {
1203
+ this.add(m.callback, m.options);
1204
+ }
1205
+
1206
+ //必须放在最后,用于返回最终数据。
1207
+ this.midware.addFinal();
1208
+
1209
+ if (this.config.useLimit) {
1210
+ let connlimit = new this.connfilter(this.limit, this.rundata);
1211
+ this.on('connection', connlimit.callback);
1212
+ } else {
1213
+ this.on('connection', (sock) => {
1214
+ this.rundata.conn++;
1215
+ sock.on('close', () => {
1216
+ this.rundata.conn--;
1217
+ });
1218
+
1219
+ });
1220
+ }
1221
+
1222
+ this.server = this.httpServ.run(port, host);
1223
+ return this.server;
1224
+ }
1225
+ //run end
1226
+
1221
1227
  /**
1222
1228
  * 这个函数是可以用于运维部署,此函数默认会根据CPU核数创建对应的子进程处理请求。
1223
1229
  * @param {number} port 端口号
@@ -1225,6 +1231,8 @@ class Topbit {
1225
1231
  * @param {number} num,要创建的子进程数量,0表示自动,这时候根据CPU核心数量创建。
1226
1232
  */
1227
1233
  daemon(port=2368, host='0.0.0.0', num=0) {
1234
+ if (this._is_daemon_listening) return this;
1235
+
1228
1236
  if (typeof host === 'number') {
1229
1237
  num = host;
1230
1238
  host = '0.0.0.0';
@@ -1236,14 +1244,16 @@ class Topbit {
1236
1244
  if (port.port && typeof port.port === 'number' && port.port > 0 && port.port <= 65535) port = port.port;
1237
1245
  }
1238
1246
 
1247
+ this._is_daemon_listening = true;
1239
1248
  //确保自动创建的worker在终止时不会误认为是系统错误。
1240
1249
  setTimeout(() => {
1241
1250
  this.errorBreakCount += 1;
1242
1251
  }, this.workerErrorTime + 120);
1243
1252
 
1244
- this._checkDaemonArgs();
1253
+ //暂时去掉,并且屏蔽daemon选项。
1254
+ //this._checkDaemonArgs();
1245
1255
 
1246
- if (cluster.isMaster) {
1256
+ if (cluster.isPrimary || cluster.isMaster) {
1247
1257
  let osCPUS = os.cpus().length;
1248
1258
  if (num > (osCPUS * 2) ) {
1249
1259
  num = 0;