✨ 优化监控服务,无感更新状态
This commit is contained in:
parent
09e107b8d9
commit
54f54c1f55
@ -6,7 +6,7 @@ async function getHostList({ res }) {
|
|||||||
data?.sort((a, b) => Number(b.index || 0) - Number(a.index || 0))
|
data?.sort((a, b) => Number(b.index || 0) - Number(a.index || 0))
|
||||||
for (const item of data) {
|
for (const item of data) {
|
||||||
let { username, port, authType, _id: id, credential } = item
|
let { username, port, authType, _id: id, credential } = item
|
||||||
console.log('解密凭证title: ', credential)
|
// console.log('解密凭证title: ', credential)
|
||||||
if (credential) credential = await AESDecryptSync(credential)
|
if (credential) credential = await AESDecryptSync(credential)
|
||||||
const isConfig = Boolean(username && port && (item[authType]))
|
const isConfig = Boolean(username && port && (item[authType]))
|
||||||
Object.assign(item, { id, isConfig, password: '', privateKey: '', credential })
|
Object.assign(item, { id, isConfig, password: '', privateKey: '', credential })
|
||||||
@ -51,11 +51,10 @@ async function updateHost({ res, request }) {
|
|||||||
}
|
}
|
||||||
} = request
|
} = request
|
||||||
let isBatch = Array.isArray(hosts)
|
let isBatch = Array.isArray(hosts)
|
||||||
console.log('isBatch:', isBatch)
|
|
||||||
if (isBatch) {
|
if (isBatch) {
|
||||||
if (!hosts.length) return res.fail({ msg: 'hosts为空' })
|
if (!hosts.length) return res.fail({ msg: 'hosts为空' })
|
||||||
let hostList = await readHostList()
|
let hostList = await readHostList()
|
||||||
console.log('批量修改: ', isBatch)
|
// console.log('批量修改实例')
|
||||||
let newHostList = []
|
let newHostList = []
|
||||||
for (let oldRecord of hostList) {
|
for (let oldRecord of hostList) {
|
||||||
let record = hosts.find(item => item.host === oldRecord.host)
|
let record = hosts.find(item => item.host === oldRecord.host)
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
const { Server: ServerIO } = require('socket.io')
|
const { Server: ServerIO } = require('socket.io')
|
||||||
const { io: ClientIO } = require('socket.io-client')
|
const { io: ClientIO, connect } = require('socket.io-client')
|
||||||
const { readHostList } = require('../utils')
|
const { readHostList } = require('../utils')
|
||||||
const { clientPort } = require('../config')
|
const { clientPort } = require('../config')
|
||||||
const { verifyAuthSync } = require('../utils')
|
const { verifyAuthSync } = require('../utils')
|
||||||
|
|
||||||
let clientSockets = {}, clientsData = {}
|
let clientsData = {}
|
||||||
|
async function getClientsInfo(clientSockets, clear = false) {
|
||||||
async function getClientsInfo(socketId) {
|
clientSockets = []
|
||||||
|
if (clear) clientsData = {}
|
||||||
let hostList = await readHostList()
|
let hostList = await readHostList()
|
||||||
hostList
|
hostList
|
||||||
?.map(({ host, name }) => {
|
?.map(({ host, name }) => {
|
||||||
@ -14,11 +15,11 @@ async function getClientsInfo(socketId) {
|
|||||||
path: '/client/os-info',
|
path: '/client/os-info',
|
||||||
forceNew: true,
|
forceNew: true,
|
||||||
timeout: 5000,
|
timeout: 5000,
|
||||||
reconnectionDelay: 3000,
|
reconnectionDelay: 5000,
|
||||||
reconnectionAttempts: 3
|
reconnectionAttempts: 1000
|
||||||
})
|
})
|
||||||
// 将与客户端连接的socket实例保存起来,web端断开时关闭这些连接
|
// 将与客户端连接的socket实例保存起来,web端断开时关闭这些连接
|
||||||
clientSockets[socketId].push(clientSocket)
|
clientSockets.push(clientSocket)
|
||||||
return {
|
return {
|
||||||
host,
|
host,
|
||||||
name,
|
name,
|
||||||
@ -26,23 +27,37 @@ async function getClientsInfo(socketId) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.map(({ host, name, clientSocket }) => {
|
.map(({ host, name, clientSocket }) => {
|
||||||
|
clientsData[host] = { connect: false }
|
||||||
clientSocket
|
clientSocket
|
||||||
.on('connect', () => {
|
.on('connect', () => {
|
||||||
consola.success('client connect success:', host, name)
|
consola.success('client connect success:', host, name)
|
||||||
clientSocket.on('client_data', (osData) => {
|
clientSocket.on('client_data', (osData) => {
|
||||||
clientsData[host] = osData
|
try {
|
||||||
|
// clientsData[host] = { connect: true, osData: JSON.parse(osData) }
|
||||||
|
clientsData[host] = { connect: true, ...osData }
|
||||||
|
} catch (error) {
|
||||||
|
console.warn('client_data, parse osData error: ', error.message)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
clientSocket.on('client_error', (error) => {
|
clientSocket.on('client_error', (error) => {
|
||||||
clientsData[host] = error
|
clientsData[host] = { connect: true, error: `client_error: ${ error }` }
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.on('connect_error', (error) => {
|
.on('connect_error', (error) => { // 连接失败
|
||||||
// consola.error('client connect fail:', host, name, error.message)
|
// consola.error('client connect fail:', host, name, error.message)
|
||||||
clientsData[host] = null
|
try {
|
||||||
|
clientsData[host] = { connect: false, error: `client_connect_error: ${ error }` }
|
||||||
|
} catch (error) {
|
||||||
|
console.warn('connect_error: ', error.message)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.on('disconnect', () => {
|
.on('disconnect', (error) => { // 一方主动断开连接
|
||||||
consola.info('client connect disconnect:', host, name)
|
// consola.info('client connect disconnect:', host, name)
|
||||||
clientsData[host] = null
|
try {
|
||||||
|
clientsData[host] = { connect: false, error: `client_disconnect: ${ error }` }
|
||||||
|
} catch (error) {
|
||||||
|
console.warn('disconnect: ', error.message)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -59,7 +74,6 @@ module.exports = (httpServer) => {
|
|||||||
// 前者兼容nginx反代, 后者兼容nodejs自身服务
|
// 前者兼容nginx反代, 后者兼容nodejs自身服务
|
||||||
let clientIp = socket.handshake.headers['x-forwarded-for'] || socket.handshake.address
|
let clientIp = socket.handshake.headers['x-forwarded-for'] || socket.handshake.address
|
||||||
socket.on('init_clients_data', async ({ token }) => {
|
socket.on('init_clients_data', async ({ token }) => {
|
||||||
// 校验登录态
|
|
||||||
const { code, msg } = await verifyAuthSync(token, clientIp)
|
const { code, msg } = await verifyAuthSync(token, clientIp)
|
||||||
if (code !== 1) {
|
if (code !== 1) {
|
||||||
socket.emit('token_verify_fail', msg || '鉴权失败')
|
socket.emit('token_verify_fail', msg || '鉴权失败')
|
||||||
@ -67,30 +81,28 @@ module.exports = (httpServer) => {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 收集web端连接的id
|
let clientSockets = []
|
||||||
clientSockets[socket.id] = []
|
clientSockets.push(socket)
|
||||||
consola.info('client连接socketId: ', socket.id, 'clients-socket已连接数: ', Object.keys(clientSockets).length)
|
|
||||||
|
|
||||||
// 获取客户端数据
|
getClientsInfo(clientSockets, true)
|
||||||
getClientsInfo(socket.id)
|
|
||||||
|
|
||||||
// 立即推送一次
|
|
||||||
socket.emit('clients_data', clientsData)
|
socket.emit('clients_data', clientsData)
|
||||||
|
|
||||||
// 向web端推送数据
|
socket.on('refresh_clients_data', async () => {
|
||||||
|
consola.info('refresh clients-socket: ', clientSockets.length)
|
||||||
|
getClientsInfo(clientSockets, false)
|
||||||
|
})
|
||||||
|
|
||||||
let timer = null
|
let timer = null
|
||||||
timer = setInterval(() => {
|
timer = setInterval(() => {
|
||||||
socket.emit('clients_data', clientsData)
|
socket.emit('clients_data', clientsData)
|
||||||
}, 1000)
|
}, 1500)
|
||||||
|
|
||||||
// 关闭连接
|
|
||||||
socket.on('disconnect', () => {
|
socket.on('disconnect', () => {
|
||||||
// 防止内存泄漏
|
|
||||||
if (timer) clearInterval(timer)
|
if (timer) clearInterval(timer)
|
||||||
// 当web端与服务端断开连接时, 服务端与每个客户端的socket也应该断开连接
|
clientSockets.forEach(socket => socket.close && socket.close())
|
||||||
clientSockets[socket.id].forEach(socket => socket.close && socket.close())
|
clientSockets = null
|
||||||
delete clientSockets[socket.id]
|
clientsData = null
|
||||||
consola.info('断开socketId: ', socket.id, 'clients-socket剩余连接数: ', Object.keys(clientSockets).length)
|
consola.info('clients-socket 连接断开: ', socket.id)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -40,32 +40,27 @@ const useStore = defineStore({
|
|||||||
await this.getHostList()
|
await this.getHostList()
|
||||||
await this.getSSHList()
|
await this.getSSHList()
|
||||||
await this.getScriptList()
|
await this.getScriptList()
|
||||||
// await this.getLocalScriptList()
|
this.wsHostStatus()
|
||||||
},
|
},
|
||||||
async getHostList() {
|
async getHostList() {
|
||||||
const { data: hostList } = await $api.getHostList()
|
const { data: hostList } = await $api.getHostList()
|
||||||
// console.log('hostList:', hostList)
|
|
||||||
this.$patch({ hostList })
|
this.$patch({ hostList })
|
||||||
this.wsHostStatus()
|
this.HostStatusSocket?.emit('refresh_clients_data')
|
||||||
},
|
},
|
||||||
async getGroupList() {
|
async getGroupList() {
|
||||||
const { data: groupList } = await $api.getGroupList()
|
const { data: groupList } = await $api.getGroupList()
|
||||||
// console.log('groupList:', groupList)
|
|
||||||
this.$patch({ groupList })
|
this.$patch({ groupList })
|
||||||
},
|
},
|
||||||
async getSSHList() {
|
async getSSHList() {
|
||||||
const { data: sshList } = await $api.getSSHList()
|
const { data: sshList } = await $api.getSSHList()
|
||||||
// console.log('sshList:', sshList)
|
|
||||||
this.$patch({ sshList })
|
this.$patch({ sshList })
|
||||||
},
|
},
|
||||||
async getScriptList() {
|
async getScriptList() {
|
||||||
const { data: scriptList } = await $api.getScriptList()
|
const { data: scriptList } = await $api.getScriptList()
|
||||||
// console.log('scriptList:', scriptList)
|
|
||||||
this.$patch({ scriptList })
|
this.$patch({ scriptList })
|
||||||
},
|
},
|
||||||
async getLocalScriptList() {
|
async getLocalScriptList() {
|
||||||
const { data: localScriptList } = await $api.getLocalScriptList()
|
const { data: localScriptList } = await $api.getLocalScriptList()
|
||||||
// console.log('localScriptList:', localScriptList)
|
|
||||||
this.$patch({ localScriptList })
|
this.$patch({ localScriptList })
|
||||||
},
|
},
|
||||||
// getHostPing() {
|
// getHostPing() {
|
||||||
@ -93,10 +88,11 @@ const useStore = defineStore({
|
|||||||
let token = this.token
|
let token = this.token
|
||||||
socketInstance.emit('init_clients_data', { token })
|
socketInstance.emit('init_clients_data', { token })
|
||||||
socketInstance.on('clients_data', (data) => {
|
socketInstance.on('clients_data', (data) => {
|
||||||
|
// console.log(data)
|
||||||
this.hostList.forEach(item => {
|
this.hostList.forEach(item => {
|
||||||
const { host } = item
|
const { host } = item
|
||||||
if (data[host] === null) return { ...item }
|
if (data[host] === null) return
|
||||||
return Object.assign(item, data[host])
|
return Object.assign(item, { monitorData: data[host] })
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
socketInstance.on('token_verify_fail', (message) => {
|
socketInstance.on('token_verify_fail', (message) => {
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
</el-table-column> -->
|
</el-table-column> -->
|
||||||
<el-table-column property="isConfig" label="监控服务">
|
<el-table-column property="isConfig" label="监控服务">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<el-tag v-if="scope.row.osInfo" type="success">已安装</el-tag>
|
<el-tag v-if="scope.row.connect || scope.row.monitorData?.connect" type="success">已安装</el-tag>
|
||||||
<el-tag v-else type="warning">未安装</el-tag>
|
<el-tag v-else type="warning">未安装</el-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
@ -59,14 +59,19 @@ const emit = defineEmits(['update-list', 'update-host', 'select-change',])
|
|||||||
|
|
||||||
let tableData = ref([])
|
let tableData = ref([])
|
||||||
|
|
||||||
watch(() => props.hosts, (newVal) => {
|
const updateTableData = () => {
|
||||||
console.log('newVal:', newVal)
|
console.log('refresh server table data')
|
||||||
tableData.value = newVal?.map(item => {
|
tableData.value = props.hosts?.map(item => {
|
||||||
// eslint-disable-next-line no-unused-vars
|
let { monitorData, ...rest } = item
|
||||||
let { cpuInfo, memInfo, osInfo, driveInfo, ipInfo, netstatInfo, ...rest } = item
|
return { ...rest, connect: monitorData?.connect || false }
|
||||||
return rest
|
|
||||||
}) || []
|
}) || []
|
||||||
}, { immediate: true, deep: false })
|
}
|
||||||
|
|
||||||
|
const connectValues = computed(() => {
|
||||||
|
return props.hosts.map(item => item.monitorData?.connect).join(',')
|
||||||
|
})
|
||||||
|
// 监听到连接状态变化,刷新列表
|
||||||
|
watch(connectValues, updateTableData)
|
||||||
|
|
||||||
const hostInfo = computed(() => props.hostInfo || {})
|
const hostInfo = computed(() => props.hostInfo || {})
|
||||||
// const host = computed(() => hostInfo.value?.host)
|
// const host = computed(() => hostInfo.value?.host)
|
||||||
|
@ -226,7 +226,7 @@ const pingTimer = ref(null)
|
|||||||
const sftpStatus = ref(false)
|
const sftpStatus = ref(false)
|
||||||
|
|
||||||
const token = computed(() => $store.token)
|
const token = computed(() => $store.token)
|
||||||
const hostData = computed(() => props.hostInfo)
|
const hostData = computed(() => props.hostInfo.monitorData || {})
|
||||||
const host = computed(() => hostData.value.host)
|
const host = computed(() => hostData.value.host)
|
||||||
const ipInfo = computed(() => hostData.value?.ipInfo || {})
|
const ipInfo = computed(() => hostData.value?.ipInfo || {})
|
||||||
// const isError = computed(() => !Boolean(hostData.value?.osInfo))
|
// const isError = computed(() => !Boolean(hostData.value?.osInfo))
|
||||||
@ -269,44 +269,6 @@ const clickInputCommand = () => {
|
|||||||
emit('click-input-command')
|
emit('click-input-command')
|
||||||
}
|
}
|
||||||
|
|
||||||
const connectIO = () => {
|
|
||||||
socket.value = socketIo($serviceURI, {
|
|
||||||
path: '/host-status',
|
|
||||||
forceNew: true,
|
|
||||||
timeout: 5000,
|
|
||||||
reconnectionDelay: 3000,
|
|
||||||
reconnectionAttempts: 3
|
|
||||||
})
|
|
||||||
|
|
||||||
socket.value.on('connect', () => {
|
|
||||||
console.log('/host-status socket已连接:', socket.value.id)
|
|
||||||
socket.value.emit('init_host_data', { token: token.value, host: props.host })
|
|
||||||
// getHostPing()
|
|
||||||
socket.value.on('host_data', (data) => {
|
|
||||||
if (!data) return hostData.value = null
|
|
||||||
hostData.value = data
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
socket.value.on('connect_error', (err) => {
|
|
||||||
console.error('host status websocket 连接错误:', err)
|
|
||||||
$notification({
|
|
||||||
title: '连接客户端失败(重连中...)',
|
|
||||||
message: '请检查客户端服务是否正常',
|
|
||||||
type: 'error'
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
socket.value.on('disconnect', () => {
|
|
||||||
hostData.value = null
|
|
||||||
$notification({
|
|
||||||
title: '客户端连接主动断开(重连中...)',
|
|
||||||
message: '请检查客户端服务是否正常',
|
|
||||||
type: 'error'
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleCopy = async () => {
|
const handleCopy = async () => {
|
||||||
await navigator.clipboard.writeText(host.value)
|
await navigator.clipboard.writeText(host.value)
|
||||||
$message.success({ message: 'success', center: true })
|
$message.success({ message: 'success', center: true })
|
||||||
|
Loading…
x
Reference in New Issue
Block a user