鎻愪氦 327fa174 缂栧啓浜 浣滆: F fengmk2 鎻愪氦鑰咃細 Yiyu He

fix: allow request timeout bigger than agent timeout (#3146)

涓婄骇 86093c03
......@@ -27,3 +27,4 @@ yarn.lock
.editorconfig
*clinic-flame*
*clinic-doctor*
.nyc_output/
MIT License
Copyright (c) 2017 Alibaba Group Holding Limited and other contributors.
Copyright (c) 2017-present Alibaba Group Holding Limited and other contributors.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
......
......@@ -238,12 +238,12 @@ module.exports = appInfo => {
* @property {Number} request.timeout - httpclient request default timeout, default is 5000 ms.
*
* @property {Boolean} httpAgent.keepAlive - Enable http agent keepalive or not, default is true
* @property {Number} httpAgent.freeSocketKeepAliveTimeout - http agent socket keepalive max free time, default is 4000 ms.
* @property {Number} httpAgent.freeSocketTimeout - http agent socket keepalive max free time, default is 4000 ms.
* @property {Number} httpAgent.maxSockets - http agent max socket number of one host, default is `Number.MAX_SAFE_INTEGER` @ses https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER
* @property {Number} httpAgent.maxFreeSockets - http agent max free socket number of one host, default is 256.
*
* @property {Boolean} httpsAgent.keepAlive - Enable https agent keepalive or not, default is true
* @property {Number} httpsAgent.freeSocketKeepAliveTimeout - httpss agent socket keepalive max free time, default is 4000 ms.
* @property {Number} httpsAgent.freeSocketTimeout - httpss agent socket keepalive max free time, default is 4000 ms.
* @property {Number} httpsAgent.maxSockets - https agent max socket number of one host, default is `Number.MAX_SAFE_INTEGER` @ses https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER
* @property {Number} httpsAgent.maxFreeSockets - https agent max free socket number of one host, default is 256.
*/
......@@ -257,13 +257,13 @@ module.exports = appInfo => {
},
httpAgent: {
keepAlive: true,
freeSocketKeepAliveTimeout: 4000,
freeSocketTimeout: 4000,
maxSockets: Number.MAX_SAFE_INTEGER,
maxFreeSockets: 256,
},
httpsAgent: {
keepAlive: true,
freeSocketKeepAliveTimeout: 4000,
freeSocketTimeout: 4000,
maxSockets: Number.MAX_SAFE_INTEGER,
maxFreeSockets: 256,
},
......
......@@ -295,7 +295,7 @@ exports.httpclient = {
// default enable http KeepAlive
keepAlive: true,
// idle KeepAlive socket can survive for 4 seconds
freeSocketKeepAliveTimeout: 4000,
freeSocketTimeout: 4000,
// when sockets have no activity for more than 30s, it will be processed as timeout
timeout: 30000,
// maximum number of sockets allow to be created
......@@ -308,7 +308,7 @@ exports.httpclient = {
// default enable https KeepAlive
keepAlive: true,
// idle KeepAlive socket can survive for 4 seconds
freeSocketKeepAliveTimeout: 4000,
freeSocketTimeout: 4000,
// when sockets have no activity for more than 30s, it will be processed as timeout
timeout: 30000,
// maximum number of sockets allow to be created
......
......@@ -301,7 +301,7 @@ exports.httpclient = {
// 榛樿寮鍚 http KeepAlive 鍔熻兘
keepAlive: true,
// 绌洪棽鐨 KeepAlive socket 鏈闀垮彲浠ュ瓨娲 4 绉
freeSocketKeepAliveTimeout: 4000,
freeSocketTimeout: 4000,
// 褰 socket 瓒呰繃 30 绉掗兘娌℃湁浠讳綍娲诲姩锛屽氨浼氳褰撲綔瓒呮椂澶勭悊鎺
timeout: 30000,
// 鍏佽鍒涘缓鐨勬渶澶 socket 鏁
......@@ -314,7 +314,7 @@ exports.httpclient = {
// 榛樿寮鍚 https KeepAlive 鍔熻兘
keepAlive: true,
// 绌洪棽鐨 KeepAlive socket 鏈闀垮彲浠ュ瓨娲 4 绉
freeSocketKeepAliveTimeout: 4000,
freeSocketTimeout: 4000,
// 褰 socket 瓒呰繃 30 绉掗兘娌℃湁浠讳綍娲诲姩锛屽氨浼氳褰撲綔瓒呮椂澶勭悊鎺
timeout: 30000,
// 鍏佽鍒涘缓鐨勬渶澶 socket 鏁
......
......@@ -291,7 +291,8 @@ declare module 'egg' {
httpclient: {
keepAlive: boolean;
freeSocketKeepAliveTimeout: number;
freeSocketKeepAliveTimeout?: number;
freeSocketTimeout: number;
timeout: number;
maxSockets: number;
maxFreeSockets: number;
......
......@@ -5,11 +5,10 @@ const HttpsAgent = require('agentkeepalive').HttpsAgent;
const urllib = require('urllib');
const ms = require('humanize-ms');
class HttpClient extends urllib.HttpClient {
constructor(app) {
const config = app.config.httpclient;
normalizeConfig(app);
const config = app.config.httpclient;
super({
app,
defaultArgs: config.request,
......@@ -50,11 +49,27 @@ function normalizeConfig(app) {
config.httpAgent.timeout = config.timeout;
config.httpsAgent.timeout = config.timeout;
}
if (config.freeSocketKeepAliveTimeout) {
config.freeSocketKeepAliveTimeout = ms(config.freeSocketKeepAliveTimeout);
config.httpAgent.freeSocketKeepAliveTimeout = config.freeSocketKeepAliveTimeout;
config.httpsAgent.freeSocketKeepAliveTimeout = config.freeSocketKeepAliveTimeout;
// compatibility httpclient.freeSocketKeepAliveTimeout => httpclient.freeSocketTimeout
if (config.freeSocketKeepAliveTimeout && !config.freeSocketTimeout) {
config.freeSocketTimeout = config.freeSocketKeepAliveTimeout;
delete config.freeSocketKeepAliveTimeout;
}
if (config.freeSocketTimeout) {
config.freeSocketTimeout = ms(config.freeSocketTimeout);
config.httpAgent.freeSocketTimeout = config.freeSocketTimeout;
config.httpsAgent.freeSocketTimeout = config.freeSocketTimeout;
} else {
// compatibility agent.freeSocketKeepAliveTimeout
if (config.httpAgent.freeSocketKeepAliveTimeout && !config.httpAgent.freeSocketTimeout) {
config.httpAgent.freeSocketTimeout = config.httpAgent.freeSocketKeepAliveTimeout;
delete config.httpAgent.freeSocketKeepAliveTimeout;
}
if (config.httpsAgent.freeSocketKeepAliveTimeout && !config.httpsAgent.freeSocketTimeout) {
config.httpsAgent.freeSocketTimeout = config.httpsAgent.freeSocketKeepAliveTimeout;
delete config.httpsAgent.freeSocketKeepAliveTimeout;
}
}
if (typeof config.maxSockets === 'number') {
config.httpAgent.maxSockets = config.maxSockets;
config.httpsAgent.maxSockets = config.maxSockets;
......
'use strict';
exports.keys = 'test key';
exports.httpclient = {
httpAgent: {
timeout: 1000,
},
};
'use strict';
const assert = require('assert-extends');
const utils = require('../../utils');
describe('test/lib/core/context_httpclient_timeout.test.js', () => {
let url;
let app;
before(() => {
app = utils.app('apps/context_httpclient_timeout');
return app.ready();
});
before(async () => {
url = await utils.startLocalServer();
});
it('should request timeout override agent socket timeout', () => {
app.httpclient.agent.options.timeout = 1000;
const ctx = app.mockContext();
return assert.asyncThrows(async () => {
await ctx.httpclient.request(`${url}/timeout`, { timeout: 1500 });
}, /ResponseTimeoutError: Response timeout for 1500ms/);
});
});
......@@ -104,8 +104,8 @@ describe('test/lib/core/httpclient.test.js', () => {
it('should convert compatibility options to agent options', () => {
// should access httpclient first
assert(app.httpclient);
assert(app.config.httpclient.httpAgent.freeSocketKeepAliveTimeout === 2000);
assert(app.config.httpclient.httpsAgent.freeSocketKeepAliveTimeout === 2000);
assert(app.config.httpclient.httpAgent.freeSocketTimeout === 2000);
assert(app.config.httpclient.httpsAgent.freeSocketTimeout === 2000);
assert(app.config.httpclient.httpAgent.maxSockets === 100);
assert(app.config.httpclient.httpsAgent.maxSockets === 100);
......@@ -376,4 +376,45 @@ describe('test/lib/core/httpclient.test.js', () => {
assert(reqTracers[0].traceId);
});
});
describe('compatibility freeSocketKeepAliveTimeout', () => {
it('should convert freeSocketKeepAliveTimeout to freeSocketTimeout', () => {
let mockApp = {
config: {
httpclient: {
request: {},
freeSocketKeepAliveTimeout: 1000,
httpAgent: {},
httpsAgent: {},
},
},
};
let client = new Httpclient(mockApp);
assert(client);
assert(mockApp.config.httpclient.freeSocketTimeout === 1000);
assert(!mockApp.config.httpclient.freeSocketKeepAliveTimeout);
assert(mockApp.config.httpclient.httpAgent.freeSocketTimeout === 1000);
assert(mockApp.config.httpclient.httpsAgent.freeSocketTimeout === 1000);
mockApp = {
config: {
httpclient: {
request: {},
httpAgent: {
freeSocketKeepAliveTimeout: 1001,
},
httpsAgent: {
freeSocketKeepAliveTimeout: 1002,
},
},
},
};
client = new Httpclient(mockApp);
assert(client);
assert(mockApp.config.httpclient.httpAgent.freeSocketTimeout === 1001);
assert(!mockApp.config.httpclient.httpAgent.freeSocketKeepAliveTimeout);
assert(mockApp.config.httpclient.httpsAgent.freeSocketTimeout === 1002);
assert(!mockApp.config.httpclient.httpsAgent.freeSocketKeepAliveTimeout);
});
});
});
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
鍏堝畬鎴愭娑堟伅鐨勭紪杈戯紒
鎯宠璇勮璇 娉ㄥ唽