refactor: speed test

pull/67/head
xiaojunnuo 2021-03-25 01:00:45 +08:00
parent 006420e06e
commit 7cf5c6119e
15 changed files with 221 additions and 33 deletions

View File

@ -107,9 +107,13 @@ const configApi = {
} }
const merged = lodash.cloneDeep(newConfig) const merged = lodash.cloneDeep(newConfig)
const clone = lodash.cloneDeep(defConfig) const clone = lodash.cloneDeep(defConfig)
lodash.merge(merged, clone) function customizer (objValue, srcValue) {
lodash.merge(merged, newConfig) if (lodash.isArray(objValue)) {
return srcValue
}
}
lodash.mergeWith(merged, clone, customizer)
lodash.mergeWith(merged, newConfig, customizer)
_deleteDisabledItem(merged) _deleteDisabledItem(merged)
configTarget = merged configTarget = merged
return configTarget return configTarget

View File

@ -65,13 +65,13 @@ module.exports = {
'raw.githubusercontent.com': { 'raw.githubusercontent.com': {
'.*': { proxy: 'raw.fastgit.org' } '.*': { proxy: 'raw.fastgit.org' }
}, },
'github.githubassets.com': { // 'github.githubassets.com': {
'.*': { // '.*': {
proxy: 'assets-gh.docmirror.top/_proxy', // proxy: 'assets-gh.docmirror.top/_proxy',
test: 'https://github.githubassets.com/favicons/favicon.svg', // test: 'https://github.githubassets.com/favicons/favicon.svg',
desc: '静态资源加速' // desc: '静态资源加速'
} // }
}, // },
'customer-stories-feed.github.com': { 'customer-stories-feed.github.com': {
'.*': { proxy: 'customer-stories-feed.fastgit.org' } '.*': { proxy: 'customer-stories-feed.fastgit.org' }
}, },

View File

@ -1,5 +1,5 @@
module.exports = { module.exports = {
name: 'Git代理', name: 'Git.exe代理',
enabled: false, enabled: false,
setting: { setting: {
sslVerify: true // 是否关闭sslVerify sslVerify: true // 是否关闭sslVerify

View File

@ -75,7 +75,7 @@ const serverApi = {
} }
} }
serverProcess.on('message', function (msg) { serverProcess.on('message', function (msg) {
log.info('收到子进程消息', msg) log.info('收到子进程消息', msg.type, msg.event.key)
if (msg.type === 'status') { if (msg.type === 'status') {
fireStatus(msg.event) fireStatus(msg.event)
} else if (msg.type === 'error') { } else if (msg.type === 'error') {
@ -83,6 +83,8 @@ const serverApi = {
fireStatus(false) // 启动失败 fireStatus(false) // 启动失败
} }
event.fire('error', { key: 'server', value: 'EADDRINUSE', error: msg.event }) event.fire('error', { key: 'server', value: 'EADDRINUSE', error: msg.event })
} else if (msg.type === 'speed') {
event.fire('speed', msg.event)
} }
}) })
return { port: runningConfig.port } return { port: runningConfig.port }
@ -128,6 +130,16 @@ const serverApi = {
}, },
getServer () { getServer () {
return server return server
},
getSpeedTestList () {
if (server) {
server.process.send({ type: 'speed', event: { key: 'getList' } })
}
},
reSpeedTest () {
if (server) {
server.process.send({ type: 'speed', event: { key: 'reTest' } })
}
} }
} }
module.exports = serverApi module.exports = serverApi

View File

@ -144,6 +144,9 @@ export default {
log.error('bridge on error', event) log.error('bridge on error', event)
win.webContents.send('error.core', event) win.webContents.send('error.core', event)
}) })
DevSidecar.api.event.register('speed', (event) => {
win.webContents.send('speed', event)
})
// 合并用户配置 // 合并用户配置
DevSidecar.api.config.reload() DevSidecar.api.config.reload()

View File

@ -69,7 +69,7 @@ export default {
}, },
menuClick (item) { menuClick (item) {
console.log('menu click', item) console.log('menu click', item)
this.$router.push(item.path) this.$router.replace(item.path)
} }
} }
} }
@ -79,6 +79,15 @@ export default {
body{ body{
height: 100%; height: 100%;
} }
.mt10{
margin-top:10px;
}
.mt5{
margin-top:5px;
}
.mt20{
margin-top:20px;
}
.ds_layout { .ds_layout {
font-family: Avenir, Helvetica, Arial, sans-serif; font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;

View File

@ -21,6 +21,9 @@ const apiObj = {
on (channel, callback) { on (channel, callback) {
ipcRenderer.on(channel, callback) ipcRenderer.on(channel, callback)
}, },
removeAllListeners (channel) {
ipcRenderer.removeAllListeners(channel)
},
invoke, invoke,
send, send,
openExternal (href) { openExternal (href) {

View File

@ -49,14 +49,12 @@
<div>如果它解决了你的问题请不要吝啬你的star哟 <a-icon style="margin-right:10px;" type="smile" theme="outlined" /></div> <div>如果它解决了你的问题请不要吝啬你的star哟 <a-icon style="margin-right:10px;" type="smile" theme="outlined" /></div>
<a @click="openExternal('https://gitee.com/docmirror/dev-sidecar')"><img src='https://gitee.com/docmirror/dev-sidecar/badge/star.svg?theme=dark' alt='star'/></a> <a @click="openExternal('https://gitee.com/docmirror/dev-sidecar')"><img src='https://gitee.com/docmirror/dev-sidecar/badge/star.svg?theme=dark' alt='star'/></a>
<a @click="openExternal('https://github.com/docmirror/dev-sidecar')"><img alt="GitHub stars" src="https://img.shields.io/github/stars/docmirror/dev-sidecar?logo=github"></a> <a @click="openExternal('https://github.com/docmirror/dev-sidecar')"><img alt="GitHub stars" src="https://img.shields.io/github/stars/docmirror/dev-sidecar?logo=github"></a>
</div> </div>
</div> </div>
<a-modal title="捐赠" v-model="donateModal" cancelText="不了" okText="支持一下" @ok="goDonate"> <a-modal title="捐赠" v-model="donateModal" width="550px" cancelText="不了" okText="支持一下" @ok="goDonate">
<div>* 随着越来越多用户来使用我的1m带宽的小服务器已经满负荷运转了</div> <div>* 随着越来越多用户来使用我的1m带宽的小服务器已经满负荷运转了</div>
<div>* 也请大家不要看油管视频把带宽留给想要访问github的同学致敬爱学习的你</div> <div>* 请大家不要看油管视频把带宽留给想要访问github的同学致敬爱学习的你</div>
<div>* 如果您觉得这个软件帮助到你而你也想帮助更多的人可以捐赠我, 我将会用捐赠的钱来购买带宽感谢支持</div>
<div class="payQrcode"> <div class="payQrcode">
<img height="200px" src="/pay.jpg"/> <img height="200px" src="/pay.jpg"/>
</div> </div>

View File

@ -1,7 +1,7 @@
<template> <template>
<ds-container> <ds-container>
<template slot="header"> <template slot="header">
Git代理设置 Git代理设置 仅针对git命令行的代理设置github网站的访问无需设置
<span> <span>
</span> </span>
</template> </template>

View File

@ -80,6 +80,60 @@
</div> </div>
</a-tab-pane> </a-tab-pane>
<a-tab-pane tab="DNS测速设置" key="4">
<div>
<div>使用以下dns获取ip进行测速</div>
<a-row style="margin-top:10px">
<a-col span="24">
<a-checkbox-group
v-model="getSpeedTestConfig().dnsProviders"
:options="speedDnsOptions"
/>
</a-col>
</a-row>
<a-row :gutter="10" class="mt20" >
<a-col :span="21">
以下域名在启动后立即进行测速其他域名在第一次访问时才测速
</a-col>
<a-col :span="2">
<a-button style="margin-left:10px" type="primary" icon="plus" @click="addSpeedHostname()" />
</a-col>
</a-row>
<a-row :gutter="10" style="margin-top: 10px" v-for="(item,index) of getSpeedTestConfig().hostnameList" :key = 'index'>
<a-col :span="21">
<a-input v-model="getSpeedTestConfig().hostnameList[index]"/>
</a-col>
<a-col :span="2">
<a-button style="margin-left:10px" type="danger" icon="minus" @click="delSpeedHostname(item,index)" />
</a-col>
</a-row>
</div>
</a-tab-pane>
<a-tab-pane tab="DNS测速详情" key="5">
<div>
<div>对获取到的ip进行测速</div>
<a-row :gutter="10" class="mt10">
<a-col span="24">
<a-button type="primary" icon="plus" @click="reSpeedTest()" >重新测速</a-button>
<a-button class="md-ml-10" type="primary" icon="refresh" @click="reloadAllSpeedTester()" >刷新</a-button>
</a-col>
</a-row>
<a-row :gutter="20">
<a-col span="12" v-for="(item,key) of speedTestList" :key='key'>
<a-card size="small" class="md-mt-10" :title="key" >
<a slot="extra" href="#">
<a-icon v-if="item.alive.length>0" type="check" />
<a-icon v-else type="info-circle" />
</a>
<a-tag style="margin:2px;" v-for="(element,index) of item.backupList" :color="element.time?'green':'red'" :key = 'index'>{{element.host}} {{element.time}}{{element.time?'ms':''}}</a-tag>
</a-card>
</a-col>
</a-row>
</div>
</a-tab-pane>
</a-tabs> </a-tabs>
</div> </div>
<template slot="footer"> <template slot="footer">
@ -95,6 +149,7 @@
<script> <script>
import vueJsonEditor from 'vue-json-editor' import vueJsonEditor from 'vue-json-editor'
import Plugin from '../mixins/plugin' import Plugin from '../mixins/plugin'
import _ from 'lodash'
export default { export default {
name: 'Server', name: 'Server',
components: { components: {
@ -106,12 +161,30 @@ export default {
key: 'server', key: 'server',
labelCol: { span: 4 }, labelCol: { span: 4 },
wrapperCol: { span: 20 }, wrapperCol: { span: 20 },
dnsMappings: [] dnsMappings: [],
speedTestList: []
} }
}, },
created () { created () {
}, },
mounted () { mounted () {
this.registerSpeedTestEvent()
},
computed: {
speedDnsOptions () {
const options = []
console.log('this.config', this.config)
if (!this.config || !this.config.server || !this.config.server.dns || !this.config.server.dns.providers) {
return options
}
_.forEach(this.config.server.dns.providers, (dnsConf, key) => {
options.push({
value: key,
label: key
})
})
return options
}
}, },
methods: { methods: {
async onCrtSelect () { async onCrtSelect () {
@ -136,6 +209,9 @@ export default {
key, value key, value
}) })
} }
if (this.config.server.dns.speedTest.dnsProviders) {
this.speedDns = this.config.server.dns.speedTest.dnsProviders
}
}, },
async applyBefore () { async applyBefore () {
const dnsMapping = {} const dnsMapping = {}
@ -163,6 +239,43 @@ export default {
async openLog () { async openLog () {
const dir = await this.$api.info.getConfigDir() const dir = await this.$api.info.getConfigDir()
this.$api.ipc.openPath(dir + '/logs/') this.$api.ipc.openPath(dir + '/logs/')
},
getSpeedTestConfig () {
return this.config.server.dns.speedTest
},
addSpeedHostname () {
this.getSpeedTestConfig().hostnameList.unshift('')
},
delSpeedHostname (item, index) {
this.getSpeedTestConfig().hostnameList.splice(index, 1)
},
reSpeedTest () {
this.$api.server.reSpeedTest()
},
registerSpeedTestEvent () {
const listener = async (event, message) => {
console.log('get speed event', event, message)
if (message.key === 'getList') {
this.speedTestList = message.value
}
}
this.$api.ipc.on('speed', listener)
const interval = this.startSpeedRefreshInterval()
this.reloadAllSpeedTester()
this.$once('hook:beforeDestroy', () => {
clearInterval(interval)
this.$api.ipc.removeAllListeners('speed')
})
},
async reloadAllSpeedTester () {
this.$api.server.getSpeedTestList()
},
startSpeedRefreshInterval () {
return setInterval(() => {
this.reloadAllSpeedTester()
}, 5000)
} }
} }
} }

View File

@ -1,7 +1,7 @@
export default function createMenus (app) { export default function createMenus (app) {
const plugins = [ const plugins = [
{ title: 'NPM加速', path: '/plugin/node', icon: 'like' }, { title: 'NPM加速', path: '/plugin/node', icon: 'like' },
{ title: 'Git代理', path: '/plugin/git', icon: 'github' } { title: 'Git.exe代理', path: '/plugin/git', icon: 'github' }
] ]
const menus = [ const menus = [
{ title: '首页', path: '/index', icon: 'home' }, { title: '首页', path: '/index', icon: 'home' },

View File

@ -3,7 +3,7 @@ const ProxyOptions = require('./options')
const proxyConfig = require('./lib/proxy/common/config') const proxyConfig = require('./lib/proxy/common/config')
const log = require('./utils/util.log') const log = require('./utils/util.log')
const { fireError, fireStatus } = require('./utils/util.process') const { fireError, fireStatus } = require('./utils/util.process')
const speedTest = require('./lib/speed/index.js')
let server let server
function registerProcessListener () { function registerProcessListener () {
@ -11,6 +11,8 @@ function registerProcessListener () {
log.info('child get msg: ' + JSON.stringify(msg)) log.info('child get msg: ' + JSON.stringify(msg))
if (msg.type === 'action') { if (msg.type === 'action') {
api[msg.event.key](msg.event.params) api[msg.event.key](msg.event.params)
} else if (msg.type === 'speed') {
speedTest.action(msg.event)
} }
}) })
@ -98,5 +100,6 @@ const api = {
module.exports = { module.exports = {
...api, ...api,
config: proxyConfig, config: proxyConfig,
log log,
speedTest
} }

View File

@ -1,8 +1,9 @@
// 1个小时不访问取消获取
const _ = require('lodash')
const net = require('net') const net = require('net')
const config = require('./config.js') const config = require('./config.js')
const log = require('../../utils/util.log.js') const log = require('../../utils/util.log.js')
const DISABLE_TIMEOUT = 60 * 60 * 1000 // 1个小时不访问取消获取 const DISABLE_TIMEOUT = 60 * 60 * 1000
class SpeedTester { class SpeedTester {
constructor ({ hostname }) { constructor ({ hostname }) {
this.dnsMap = config.getConfig().dnsMap this.dnsMap = config.getConfig().dnsMap
@ -82,6 +83,9 @@ class SpeedTester {
this.backupList = await this.getIpListFromDns(this.dnsMap) this.backupList = await this.getIpListFromDns(this.dnsMap)
log.info('[speed]', this.hostname, ' ips:', this.backupList) log.info('[speed]', this.hostname, ' ips:', this.backupList)
await this.testBackups() await this.testBackups()
if (config.notify) {
config.notify({ key: 'test' })
}
} }
async testBackups () { async testBackups () {
@ -98,8 +102,10 @@ class SpeedTester {
async doTest (item, aliveList) { async doTest (item, aliveList) {
try { try {
const ret = await this.testOne(item) const ret = await this.testOne(item)
_.merge(item, ret)
aliveList.push({ ...ret, ...item }) aliveList.push({ ...ret, ...item })
aliveList.sort((a, b) => a.time - b.time) aliveList.sort((a, b) => a.time - b.time)
this.backupList.sort((a, b) => a.time - b.time)
} catch (e) { } catch (e) {
log.error('[speed] test error', this.hostname, item.host, e.message) log.error('[speed] test error', this.hostname, item.host, e.message)
} }

View File

@ -1,5 +1,6 @@
const config = { const config = {
notify () {},
dnsMap: {}
} }
module.exports = { module.exports = {
getConfig () { getConfig () {

View File

@ -14,15 +14,51 @@ function initSpeedTestPool ({ hostnameList, dnsMap }) {
console.log('[speed] dnsMap', dnsMap) console.log('[speed] dnsMap', dnsMap)
} }
module.exports = { function getAllSpeedTester () {
SpeedTester, const allSpeed = {}
initSpeedTestPool, _.forEach(SpeedTestPool, (item, key) => {
getSpeedTester (hostname) { allSpeed[key] = {
hostname: key,
alive: item.alive,
backupList: item.backupList
}
})
return allSpeed
}
function getSpeedTester (hostname) {
let instance = SpeedTestPool[hostname] let instance = SpeedTestPool[hostname]
if (instance == null) { if (instance == null) {
instance = new SpeedTester({ hostname }) instance = new SpeedTester({ hostname })
SpeedTestPool[hostname] = instance SpeedTestPool[hostname] = instance
} }
return instance return instance
}
function registerNotify (notify) {
config.notify = notify
}
function reSpeedTest () {
_.forEach(SpeedTestPool, (item, key) => {
item.test()
})
}
// action调用
function action (event) {
if (event.key === 'reTest') {
reSpeedTest()
} else if (event.key === 'getList') {
process.send({ type: 'speed', event: { key: 'getList', value: getAllSpeedTester() } })
} }
} }
module.exports = {
SpeedTester,
initSpeedTestPool,
getSpeedTester,
getAllSpeedTester,
registerNotify,
reSpeedTest,
action
}