topbit 3.1.8 → 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 +6 -7
- package/README.md +7 -8
- package/demo/http2.js +3 -4
- package/demo/loader.js +32 -9
- package/demo/monitor.js +4 -5
- package/docs/en/topbit-loader.md +11 -4
- package/docs/topbit-loader.md +11 -4
- package/package.json +1 -1
- package/src/loader/loader.js +23 -6
- package/src/topbit.js +140 -94
package/README.cn.md
CHANGED
|
@@ -62,7 +62,8 @@ const app = new Topbit({
|
|
|
62
62
|
debug: true
|
|
63
63
|
})
|
|
64
64
|
|
|
65
|
-
|
|
65
|
+
//输出服务信息并运行服务
|
|
66
|
+
app.printServInfo().run(1234)
|
|
66
67
|
|
|
67
68
|
```
|
|
68
69
|
|
|
@@ -112,7 +113,7 @@ app.get('/', async ctx => {
|
|
|
112
113
|
ctx.to('success')
|
|
113
114
|
})
|
|
114
115
|
|
|
115
|
-
app.run(1234)
|
|
116
|
+
app.printServInfo().run(1234)
|
|
116
117
|
|
|
117
118
|
```
|
|
118
119
|
|
|
@@ -159,7 +160,7 @@ app.put('/p', async c => {
|
|
|
159
160
|
})
|
|
160
161
|
|
|
161
162
|
//默认监听0.0.0.0,参数和原生接口listen一致。
|
|
162
|
-
app.run(8080)
|
|
163
|
+
app.printServInfo().run(8080)
|
|
163
164
|
|
|
164
165
|
```
|
|
165
166
|
|
|
@@ -847,8 +848,6 @@ app.run(1234)
|
|
|
847
848
|
//最大解析的文件数量
|
|
848
849
|
maxFiles : 12,
|
|
849
850
|
|
|
850
|
-
daemon : false, //开启守护进程
|
|
851
|
-
|
|
852
851
|
/*
|
|
853
852
|
开启守护进程模式后,如果设置路径不为空字符串,则会把pid写入到此文件,可用于服务管理。
|
|
854
853
|
*/
|
|
@@ -971,9 +970,9 @@ app.run(1234)
|
|
|
971
970
|
this.config.debug && console.error(errname, err)
|
|
972
971
|
},
|
|
973
972
|
|
|
974
|
-
//最大负载率百分比,默认为75表示当CPU使用率超过75%,则会自动创建子进程。
|
|
973
|
+
//最大负载率百分比,默认为0.75表示当CPU使用率超过75%,则会自动创建子进程。
|
|
975
974
|
//必须通过autoWorker开启自动负载模式才有效。
|
|
976
|
-
maxLoadRate: 75,
|
|
975
|
+
maxLoadRate: 0.75,
|
|
977
976
|
|
|
978
977
|
//http2协议的http2Stream超时,若不设置,-1表示和timeout一致。
|
|
979
978
|
streamTimeout: -1,
|
package/README.md
CHANGED
|
@@ -46,7 +46,8 @@ const app = new Topbit({
|
|
|
46
46
|
debug: true
|
|
47
47
|
})
|
|
48
48
|
|
|
49
|
-
|
|
49
|
+
//in debug mode, output service info
|
|
50
|
+
app.printServInfo().run(1234)
|
|
50
51
|
```
|
|
51
52
|
|
|
52
53
|
When no routes are added, Topbit adds a default route:
|
|
@@ -72,7 +73,7 @@ app.get('/', async ctx => {
|
|
|
72
73
|
})
|
|
73
74
|
|
|
74
75
|
// Defaults to listening on 0.0.0.0, parameters are consistent with the native listen interface.
|
|
75
|
-
app.run(1234)
|
|
76
|
+
app.printServInfo().run(1234)
|
|
76
77
|
|
|
77
78
|
```
|
|
78
79
|
|
|
@@ -94,7 +95,7 @@ app.get('/', async ctx => {
|
|
|
94
95
|
ctx.to('success')
|
|
95
96
|
})
|
|
96
97
|
|
|
97
|
-
app.run(1234)
|
|
98
|
+
app.printServInfo().run(1234)
|
|
98
99
|
|
|
99
100
|
```
|
|
100
101
|
|
|
@@ -141,7 +142,7 @@ app.put('/p', async c => {
|
|
|
141
142
|
})
|
|
142
143
|
|
|
143
144
|
// Defaults to listening on 0.0.0.0
|
|
144
|
-
app.run(8080)
|
|
145
|
+
app.printServInfo().run(8080)
|
|
145
146
|
|
|
146
147
|
```
|
|
147
148
|
|
|
@@ -811,8 +812,6 @@ Full configuration options for app initialization are as follows. Please read th
|
|
|
811
812
|
// Max number of files to parse
|
|
812
813
|
maxFiles : 12,
|
|
813
814
|
|
|
814
|
-
daemon : false, // Enable daemon mode
|
|
815
|
-
|
|
816
815
|
/*
|
|
817
816
|
After enabling daemon mode, if path is not empty string, pid is written to this file. Used for service management.
|
|
818
817
|
*/
|
|
@@ -935,9 +934,9 @@ Full configuration options for app initialization are as follows. Please read th
|
|
|
935
934
|
this.config.debug && console.error(errname, err)
|
|
936
935
|
},
|
|
937
936
|
|
|
938
|
-
// 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.
|
|
939
938
|
// Must enable auto load mode via autoWorker.
|
|
940
|
-
maxLoadRate: 75,
|
|
939
|
+
maxLoadRate: 0.75,
|
|
941
940
|
|
|
942
941
|
// http2 protocol http2Stream timeout. If not set, -1 means consistent with timeout.
|
|
943
942
|
streamTimeout: -1,
|
package/demo/http2.js
CHANGED
package/demo/loader.js
CHANGED
|
@@ -4,27 +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
|
-
|
|
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
|
-
|
|
43
|
+
let ld = new Loader()
|
|
24
44
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
45
|
+
ld.daemonInit(app, () => {
|
|
46
|
+
app.sched('none')
|
|
47
|
+
.autoWorker(12)
|
|
48
|
+
.printServInfo(100)
|
|
49
|
+
.daemon(1234, args.worker)
|
|
50
|
+
})
|
|
28
51
|
|
|
29
52
|
//console.log(app.midware.midGroup)
|
|
30
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
|
-
'--
|
|
13
|
-
name: '
|
|
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.
|
|
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)
|
package/docs/en/topbit-loader.md
CHANGED
|
@@ -61,8 +61,11 @@ if (app.isWorker) {
|
|
|
61
61
|
new Loader().init(app)
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
|
|
65
|
-
app.
|
|
64
|
+
// Max elastic workers
|
|
65
|
+
app.autoWorker(16)
|
|
66
|
+
//delay 100ms, output service info
|
|
67
|
+
.printServInfo(100)
|
|
68
|
+
.daemon(443, 4) // 4 base workers
|
|
66
69
|
```
|
|
67
70
|
|
|
68
71
|
Run `node app.js` → full-featured service is up!
|
|
@@ -98,7 +101,9 @@ new Loader({
|
|
|
98
101
|
const UserModel = require('./model/user')
|
|
99
102
|
service.userModel = new UserModel(service)
|
|
100
103
|
}
|
|
101
|
-
}).init(app)
|
|
104
|
+
}).init(app, () => {
|
|
105
|
+
app.run(1234)
|
|
106
|
+
})
|
|
102
107
|
```
|
|
103
108
|
|
|
104
109
|
---
|
|
@@ -233,7 +238,9 @@ new Loader({
|
|
|
233
238
|
service[name + 'Model'] = new Model(service)
|
|
234
239
|
}
|
|
235
240
|
}
|
|
236
|
-
}).
|
|
241
|
+
}).daemonInit(app, () => {
|
|
242
|
+
app.daemon(1234, 2)
|
|
243
|
+
})
|
|
237
244
|
```
|
|
238
245
|
|
|
239
246
|
---
|
package/docs/topbit-loader.md
CHANGED
|
@@ -59,8 +59,11 @@ if (app.isWorker) {
|
|
|
59
59
|
new Loader().init(app)
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
|
|
63
|
-
app.
|
|
62
|
+
// 最大弹性进程数
|
|
63
|
+
app.autoWorker(16)
|
|
64
|
+
//延迟100ms后输出服务运行信息
|
|
65
|
+
.printServInfo(100)
|
|
66
|
+
.daemon(443, 4) // 4 个基础进程
|
|
64
67
|
```
|
|
65
68
|
|
|
66
69
|
只需执行 `node app.js` 即可启动完整服务!
|
|
@@ -96,7 +99,9 @@ new Loader({
|
|
|
96
99
|
const UserModel = require('./model/user')
|
|
97
100
|
service.userModel = new UserModel(service)
|
|
98
101
|
}
|
|
99
|
-
}).init(app)
|
|
102
|
+
}).init(app, () => {
|
|
103
|
+
app.run(1234)
|
|
104
|
+
})
|
|
100
105
|
```
|
|
101
106
|
|
|
102
107
|
---
|
|
@@ -233,7 +238,9 @@ new Loader({
|
|
|
233
238
|
service[name + 'Model'] = new Model(service)
|
|
234
239
|
}
|
|
235
240
|
}
|
|
236
|
-
}).
|
|
241
|
+
}).daemonInit(app, () => {
|
|
242
|
+
app.daemon(1234, 2)
|
|
243
|
+
})
|
|
237
244
|
```
|
|
238
245
|
|
|
239
246
|
---
|
package/package.json
CHANGED
package/src/loader/loader.js
CHANGED
|
@@ -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
|
@@ -39,7 +39,7 @@ const ErrorLog = require('./lib/errorlog.js')
|
|
|
39
39
|
let __instance__ = 0;
|
|
40
40
|
|
|
41
41
|
let _topbit_server_running = `
|
|
42
|
-
|
|
42
|
+
:.:.:.:.:\x1b[34;5m.\x1b[0m:\x1b[36;5m.\x1b[0m topbit in service \x1b[36;5m.\x1b[0m:\x1b[34;5m.\x1b[0m:.:.:.:.:
|
|
43
43
|
`;
|
|
44
44
|
|
|
45
45
|
let _topbit_home_page = `<!DOCTYPE html><html>
|
|
@@ -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,98 +858,64 @@ 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
861
|
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
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
|
-
})
|
|
862
|
+
/**
|
|
863
|
+
*
|
|
864
|
+
* @param {number} timeout - default 0
|
|
865
|
+
* @param {boolean} debug - default true(true表示只有debug模式才会输出)
|
|
866
|
+
* @returns
|
|
867
|
+
*/
|
|
868
|
+
printServInfo(timeout=0, debug=true) {
|
|
869
|
+
if (typeof timeout === 'boolean') {
|
|
870
|
+
debug = timeout
|
|
871
|
+
timeout = 0
|
|
886
872
|
}
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
873
|
+
|
|
874
|
+
if (!debug || (debug && this.config.debug)) {
|
|
875
|
+
if (timeout > 0) {
|
|
876
|
+
setTimeout(() => {
|
|
877
|
+
this._corePrintServ()
|
|
878
|
+
}, timeout)
|
|
879
|
+
} else {
|
|
880
|
+
queueMicrotask(() => {
|
|
881
|
+
this._corePrintServ()
|
|
882
|
+
})
|
|
883
|
+
}
|
|
891
884
|
}
|
|
885
|
+
|
|
886
|
+
return this
|
|
887
|
+
}
|
|
888
|
+
|
|
889
|
+
_corePrintServ() {
|
|
890
|
+
let {port, host} = this.rundata
|
|
892
891
|
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
let m = null;
|
|
900
|
-
while((m = this.__pre_mids__.pop()) !== undefined) {
|
|
901
|
-
this.add(m.callback, m.options);
|
|
892
|
+
/**
|
|
893
|
+
* 输出路由表,如果是启用了cluster,则通过发送消息的方式让master进程输出。
|
|
894
|
+
* */
|
|
895
|
+
if (typeof port === 'string' && port.indexOf('.sock') > 0) {
|
|
896
|
+
host = '';
|
|
902
897
|
}
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
this.
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
898
|
+
|
|
899
|
+
let is_https = this.config.https;
|
|
900
|
+
|
|
901
|
+
let protocol = this.config.http2
|
|
902
|
+
? ('http2' + (is_https ? '[https]' : ''))
|
|
903
|
+
: (is_https ? 'https' : 'http');
|
|
904
|
+
|
|
905
|
+
if (cluster.isMaster) {
|
|
906
|
+
this.router.printTable();
|
|
907
|
+
console.log(`PID: ${process.pid}, Listen ${host}:${port}, Protocol: ${protocol}`);
|
|
908
|
+
console.log(_topbit_server_running);
|
|
909
|
+
} else if (process.send && typeof process.send === 'function') {
|
|
910
|
+
process.send({type:'_route-table',
|
|
911
|
+
route: this.router.getTable(),
|
|
912
|
+
listen: `Listen: ${host}${host.length > 0 ? ':' : ''}${port}, `,
|
|
913
|
+
protocol: `Protocol: ${protocol}`
|
|
917
914
|
});
|
|
918
915
|
}
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
* 输出路由表,如果是启用了cluster,则通过发送消息的方式让master进程输出。
|
|
922
|
-
* */
|
|
923
|
-
if (this.config.debug) {
|
|
924
|
-
if (typeof port === 'string' && port.indexOf('.sock') > 0) {
|
|
925
|
-
host = '';
|
|
926
|
-
}
|
|
927
|
-
|
|
928
|
-
let is_https = this.config.https;
|
|
929
|
-
|
|
930
|
-
let protocol = this.config.http2
|
|
931
|
-
? ('http2' + (is_https ? '[https]' : ''))
|
|
932
|
-
: (is_https ? 'https' : 'http');
|
|
933
|
-
|
|
934
|
-
if (cluster.isMaster) {
|
|
935
|
-
this.router.printTable();
|
|
936
|
-
console.log(`PID: ${process.pid}, Listen ${host}:${port}, Protocol: ${protocol}`);
|
|
937
|
-
console.log(_topbit_server_running);
|
|
938
|
-
} else if (process.send && typeof process.send === 'function') {
|
|
939
|
-
process.send({type:'_route-table',
|
|
940
|
-
route: this.router.getTable(),
|
|
941
|
-
listen: `Listen: ${host}${host.length > 0 ? ':' : ''}${port}, `,
|
|
942
|
-
protocol: `Protocol: ${protocol}`
|
|
943
|
-
});
|
|
944
|
-
}
|
|
945
|
-
}
|
|
946
|
-
|
|
947
|
-
this.server = this.httpServ.run(port, host);
|
|
948
|
-
return this.server;
|
|
916
|
+
|
|
917
|
+
return this
|
|
949
918
|
}
|
|
950
|
-
//run end
|
|
951
919
|
|
|
952
920
|
/**
|
|
953
921
|
* @param {string} evt
|
|
@@ -968,8 +936,9 @@ class Topbit {
|
|
|
968
936
|
count: 0,
|
|
969
937
|
mode: mode,
|
|
970
938
|
callback: callback
|
|
971
|
-
}
|
|
972
|
-
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
return this;
|
|
973
942
|
}
|
|
974
943
|
|
|
975
944
|
getMsgEvent(evt) {
|
|
@@ -1047,11 +1016,13 @@ class Topbit {
|
|
|
1047
1016
|
}
|
|
1048
1017
|
|
|
1049
1018
|
autoWorker(max) {
|
|
1050
|
-
if (typeof max === 'number' && max
|
|
1051
|
-
this.workerCount.max = max;
|
|
1019
|
+
if (!isNaN(max) && typeof max === 'number' && max >= 0) {
|
|
1020
|
+
this.workerCount.max = max > 0 ? max : os.cpus().length;
|
|
1052
1021
|
} else {
|
|
1053
|
-
throw new Error('autoWorker
|
|
1022
|
+
throw new Error('autoWorker参数必须是一个>=0的数字,表示最大允许创建多少个子进程处理请求。');
|
|
1054
1023
|
}
|
|
1024
|
+
|
|
1025
|
+
return this;
|
|
1055
1026
|
}
|
|
1056
1027
|
|
|
1057
1028
|
/**
|
|
@@ -1066,6 +1037,8 @@ class Topbit {
|
|
|
1066
1037
|
} else {
|
|
1067
1038
|
return cluster.schedulingPolicy;
|
|
1068
1039
|
}
|
|
1040
|
+
|
|
1041
|
+
return this;
|
|
1069
1042
|
}
|
|
1070
1043
|
|
|
1071
1044
|
_checkDaemonArgs() {
|
|
@@ -1112,7 +1085,6 @@ class Topbit {
|
|
|
1112
1085
|
cpu: {user:0, system:0},
|
|
1113
1086
|
cputm : 1000000
|
|
1114
1087
|
};
|
|
1115
|
-
|
|
1116
1088
|
});
|
|
1117
1089
|
|
|
1118
1090
|
let exitTip = () => {
|
|
@@ -1182,6 +1154,76 @@ class Topbit {
|
|
|
1182
1154
|
|
|
1183
1155
|
}
|
|
1184
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
|
+
|
|
1185
1227
|
/**
|
|
1186
1228
|
* 这个函数是可以用于运维部署,此函数默认会根据CPU核数创建对应的子进程处理请求。
|
|
1187
1229
|
* @param {number} port 端口号
|
|
@@ -1189,6 +1231,8 @@ class Topbit {
|
|
|
1189
1231
|
* @param {number} num,要创建的子进程数量,0表示自动,这时候根据CPU核心数量创建。
|
|
1190
1232
|
*/
|
|
1191
1233
|
daemon(port=2368, host='0.0.0.0', num=0) {
|
|
1234
|
+
if (this._is_daemon_listening) return this;
|
|
1235
|
+
|
|
1192
1236
|
if (typeof host === 'number') {
|
|
1193
1237
|
num = host;
|
|
1194
1238
|
host = '0.0.0.0';
|
|
@@ -1200,14 +1244,16 @@ class Topbit {
|
|
|
1200
1244
|
if (port.port && typeof port.port === 'number' && port.port > 0 && port.port <= 65535) port = port.port;
|
|
1201
1245
|
}
|
|
1202
1246
|
|
|
1247
|
+
this._is_daemon_listening = true;
|
|
1203
1248
|
//确保自动创建的worker在终止时不会误认为是系统错误。
|
|
1204
1249
|
setTimeout(() => {
|
|
1205
1250
|
this.errorBreakCount += 1;
|
|
1206
1251
|
}, this.workerErrorTime + 120);
|
|
1207
1252
|
|
|
1208
|
-
|
|
1253
|
+
//暂时去掉,并且屏蔽daemon选项。
|
|
1254
|
+
//this._checkDaemonArgs();
|
|
1209
1255
|
|
|
1210
|
-
if (cluster.isMaster) {
|
|
1256
|
+
if (cluster.isPrimary || cluster.isMaster) {
|
|
1211
1257
|
let osCPUS = os.cpus().length;
|
|
1212
1258
|
if (num > (osCPUS * 2) ) {
|
|
1213
1259
|
num = 0;
|