`choise/index.js` 的代码简单调整一下。
parent
166ccd13a1
commit
17bf7c4e36
|
@ -25,40 +25,44 @@ class ChoiceCache {
|
|||
class DynamicChoice {
|
||||
constructor (key) {
|
||||
this.key = key
|
||||
this.count = {}
|
||||
this.countMap = {} /* ip -> count { value, total, error, keepErrorCount, successRate } */
|
||||
this.value = null // 当前使用的host
|
||||
this.backupList = [] // 备选host列表
|
||||
this.createTime = new Date()
|
||||
}
|
||||
|
||||
doRank () {
|
||||
// 将count里面根据权重排序
|
||||
const list = []
|
||||
for (const key in this.count) {
|
||||
list.push(this.count[key])
|
||||
// 将count里面根据成功率排序
|
||||
const countList = []
|
||||
for (const key in this.countMap) {
|
||||
countList.push(this.countMap[key])
|
||||
}
|
||||
list.sort((a, b) => {
|
||||
|
||||
// 将countList根据成功率排序
|
||||
countList.sort((a, b) => {
|
||||
return b.successRate - a.successRate
|
||||
})
|
||||
log.info('do rank', JSON.stringify(list))
|
||||
const backup = list.map(item => item.value)
|
||||
|
||||
this.setBackupList(backup)
|
||||
log.info('Do rank:', JSON.stringify(countList))
|
||||
|
||||
const newBackupList = countList.map(item => item.value)
|
||||
this.setBackupList(newBackupList)
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置新的backup列表
|
||||
* @param backupList
|
||||
* @param newBackupList 新的backupList
|
||||
*/
|
||||
setBackupList (backupList) {
|
||||
this.backup = backupList
|
||||
let defaultTotal = backupList.length
|
||||
for (const item of backupList) {
|
||||
if (this.count[item]) {
|
||||
continue
|
||||
setBackupList (newBackupList) {
|
||||
this.backupList = newBackupList
|
||||
let defaultTotal = newBackupList.length
|
||||
for (const ip of newBackupList) {
|
||||
if (!this.countMap[ip]) {
|
||||
this.countMap[ip] = { value: ip, total: defaultTotal, error: 0, keepErrorCount: 0, successRate: 0.5 }
|
||||
defaultTotal--
|
||||
}
|
||||
this.count[item] = { value: item, total: defaultTotal, error: 0, keepErrorCount: 0, successRate: 0.5 }
|
||||
defaultTotal--
|
||||
}
|
||||
this.value = backupList.shift()
|
||||
this.value = newBackupList.shift()
|
||||
this.doCount(this.value, false)
|
||||
}
|
||||
|
||||
|
@ -67,45 +71,52 @@ class DynamicChoice {
|
|||
}
|
||||
|
||||
/**
|
||||
* 换下一个
|
||||
* @param count
|
||||
*/
|
||||
* 换下一个
|
||||
* @param count 计数器
|
||||
*/
|
||||
changeNext (count) {
|
||||
log.info('切换backup', count, this.backup)
|
||||
log.info('切换backup', count, this.backupList)
|
||||
count.keepErrorCount = 0 // 清空连续失败
|
||||
count.total = 0
|
||||
count.error = 0
|
||||
if (this.backup.length > 0) {
|
||||
this.value = this.backup.shift()
|
||||
|
||||
const valueBackup = this.value
|
||||
if (this.backupList.length > 0) {
|
||||
this.value = this.backupList.shift()
|
||||
log.info(`切换backup完成: ${this.key}, ip: ${valueBackup} ➜ ${this.value}, this:`, this)
|
||||
} else {
|
||||
this.value = null
|
||||
log.info(`切换backup完成: ${this.key}, backupList为空了,设置this.value: from '${valueBackup}' to null. this:`, this)
|
||||
}
|
||||
log.info('切换backup完成', this.value, this.backup)
|
||||
}
|
||||
|
||||
/**
|
||||
* 记录使用次数或错误次数
|
||||
* @param value
|
||||
* @param isError
|
||||
*/
|
||||
doCount (value, isError) {
|
||||
let count = this.count[value]
|
||||
* 记录使用次数或错误次数
|
||||
* @param ip
|
||||
* @param isError
|
||||
*/
|
||||
doCount (ip, isError) {
|
||||
let count = this.countMap[ip]
|
||||
if (count == null) {
|
||||
count = this.count[value] = { value: value, total: 5, error: 0, keepErrorCount: 0, successRate: 1 }
|
||||
count = this.countMap[ip] = { value: ip, total: 5, error: 0, keepErrorCount: 0, successRate: 1 }
|
||||
}
|
||||
|
||||
if (isError) {
|
||||
// 失败次数+1,累计连续失败次数+1
|
||||
count.error++
|
||||
count.keepErrorCount++
|
||||
} else {
|
||||
count.total += 1
|
||||
// 总次数+1
|
||||
count.total++
|
||||
}
|
||||
// 计算成功率
|
||||
count.successRate = 1.0 - (count.error / count.total)
|
||||
if (isError && this.value === value) {
|
||||
if (isError && this.value === ip) {
|
||||
// 连续错误3次,切换下一个
|
||||
if (count.keepErrorCount >= 3) {
|
||||
this.changeNext(count)
|
||||
}
|
||||
// 成功率小于50%,切换下一个
|
||||
// 成功率小于40%,切换下一个
|
||||
if (count.successRate < 0.4) {
|
||||
this.changeNext(count)
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ module.exports = function createConnectHandler (sslConnectInterceptor, middlewar
|
|||
function connect (req, cltSocket, head, hostname, port, dnsConfig/* , sniRegexpMap */) {
|
||||
// tunneling https
|
||||
// log.info('connect:', hostname, port)
|
||||
const start = new Date().getTime()
|
||||
const start = new Date()
|
||||
let isDnsIntercept = null
|
||||
const hostport = `${hostname}:${port}`
|
||||
// const replaceSni = matchUtil.matchHostname(sniRegexpMap, hostname, 'sni')
|
||||
|
@ -102,13 +102,13 @@ function connect (req, cltSocket, head, hostname, port, dnsConfig/* , sniRegexpM
|
|||
log.error(`cltSocket error: ${hostport}, errorMsg: ${e.message}`)
|
||||
})
|
||||
proxySocket.on('timeout', () => {
|
||||
const end = new Date().getTime()
|
||||
log.info('代理socket timeout:', hostname, port, (end - start) + 'ms')
|
||||
const cost = new Date() - start
|
||||
log.info('代理socket timeout:', hostname, port, cost + 'ms')
|
||||
})
|
||||
proxySocket.on('error', (e) => {
|
||||
// 连接失败,可能被GFW拦截,或者服务端拥挤
|
||||
const end = new Date().getTime()
|
||||
log.error('代理连接失败:', e.message, hostname, port, (end - start) + 'ms')
|
||||
const cost = new Date() - start
|
||||
log.error('代理连接失败:', e.message, hostname, port, cost + 'ms')
|
||||
cltSocket.destroy()
|
||||
if (isDnsIntercept) {
|
||||
const { dns, ip, hostname } = isDnsIntercept
|
||||
|
|
|
@ -109,7 +109,7 @@ module.exports = function createRequestHandler (createIntercepts, middlewares, e
|
|||
|
||||
function onFree () {
|
||||
const url = `${rOptions.protocol}//${rOptions.hostname}:${rOptions.port}${rOptions.path}`
|
||||
const start = new Date().getTime()
|
||||
const start = new Date()
|
||||
log.info('代理请求:', url, rOptions.method, rOptions.servername ? ', sni: ' + rOptions.servername : '')
|
||||
let isDnsIntercept
|
||||
if (dnsConfig) {
|
||||
|
@ -147,8 +147,7 @@ module.exports = function createRequestHandler (createIntercepts, middlewares, e
|
|||
// log.debug('agent:', rOptions.agent)
|
||||
// log.debug('agent.options:', rOptions.agent.options)
|
||||
proxyReq = (rOptions.protocol === 'https:' ? https : http).request(rOptions, (proxyRes) => {
|
||||
const end = new Date().getTime()
|
||||
const cost = end - start
|
||||
const cost = new Date() - start
|
||||
if (rOptions.protocol === 'https:') {
|
||||
log.info('代理请求返回:', url, cost + 'ms')
|
||||
}
|
||||
|
@ -161,8 +160,7 @@ module.exports = function createRequestHandler (createIntercepts, middlewares, e
|
|||
|
||||
// 代理请求的事件监听
|
||||
proxyReq.on('timeout', () => {
|
||||
const end = new Date().getTime()
|
||||
const cost = end - start
|
||||
const cost = new Date() - start
|
||||
log.error('代理请求超时', rOptions.protocol, rOptions.hostname, rOptions.path, cost + 'ms')
|
||||
countSlow(isDnsIntercept, 'to slow ' + cost + 'ms')
|
||||
proxyReq.end()
|
||||
|
@ -172,15 +170,13 @@ module.exports = function createRequestHandler (createIntercepts, middlewares, e
|
|||
reject(error)
|
||||
})
|
||||
proxyReq.on('error', (e) => {
|
||||
const end = new Date().getTime()
|
||||
const cost = end - start
|
||||
const cost = new Date() - start
|
||||
log.error('代理请求错误', e.code, e.message, rOptions.hostname, rOptions.path, cost + 'ms')
|
||||
countSlow(isDnsIntercept, 'error:' + e.message)
|
||||
reject(e)
|
||||
})
|
||||
proxyReq.on('aborted', () => {
|
||||
const end = new Date().getTime()
|
||||
const cost = end - start
|
||||
const cost = new Date() - start
|
||||
log.error('代理请求被取消', rOptions.hostname, rOptions.path, cost + 'ms')
|
||||
|
||||
if (cost > MAX_SLOW_TIME) {
|
||||
|
|
|
@ -24,7 +24,7 @@ utils.createCA = function (CN) {
|
|||
const cert = pki.createCertificate()
|
||||
cert.publicKey = keys.publicKey
|
||||
cert.serialNumber = (new Date()).getTime() + ''
|
||||
cert.validity.notBefore = new Date(new Date().getTime() - (60 * 60 * 1000))
|
||||
cert.validity.notBefore = new Date(new Date() - (60 * 60 * 1000))
|
||||
cert.validity.notAfter = new Date()
|
||||
cert.validity.notAfter.setFullYear(cert.validity.notAfter.getFullYear() + 20)
|
||||
const attrs = [{
|
||||
|
|
Loading…
Reference in New Issue