首页 > 其他分享 >前端利用fetch实现服务器健康检查

前端利用fetch实现服务器健康检查

时间:2023-10-02 22:59:55浏览次数:37  
标签:flex url com seentao checkStatus 服务器 健康检查 border fetch

最近公司赛事较多,一些大型赛事部署了多台服务器,为了实时了解的运行状态,保障服务器正常运行,我用前端实现了一个服务器健康检查程序,可设置自动轮询检查或手动检查。

使用fetch发送ajax请求(服务器需要设置允许跨域),判断请求状态和结果来得出正常、超时、连接失败状态。代码使用vue3了浏览器版前端框架。

效果:

 代码:

<!doctype html>
<head>
    <meta charset="utf-8">
    <title>服务器健康检查</title>
    <meta name="keywords" content="" />
    <meta name="description" content="" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" />
    <style>
        * {
            cursor: default;
            box-sizing: border-box;
        }
        html,body {
            display: flex;flex-direction: column; align-items: center;
        }
        #app {
            width:800px;
        }
        .controls {
            display: flex; justify-content: flex-end;
        }
        .mode-switch {
            width:100px;height:30px;border-radius: 6px;display: flex;overflow: hidden;border:1px solid rgb(57, 166, 255);
        }
        .mode-switch-item {
            width:100%; display: flex; justify-content: center; align-items: center;
        }
        .mode-switch-item-active {
            background-color: rgb(57, 166, 255);color:white;
        }

        .button {
            background-color: rgb(57, 166, 255);border: none;color:white;display: flex;padding: 6px 10px;
        }
        .button:active {
            transform: scale(0.95);
        }

        .tab-header {
            display: flex; align-items: center;
        }
        .tab-header-item {
            padding: 4px 8px; border: 1px solid #ccc; border-top-left-radius: 6px; border-top-right-radius: 6px;
        }
        .tab-header-item-active {
            border: 1px solid rgb(57, 166, 255); background-color: rgb(57, 166, 255);color:white;
        }

        .tab-bodyer {
            width:100%;border-top:10px solid rgb(57, 166, 255);overflow-y: auto;
        }
        .tab-bodyer-item {
            display: none;
        }
        .tab-bodyer-item-active {
            display: flex; flex-direction: column;
        }

        .tab-bodyer-item-server {
            width:100%;height:60px;border:1px solid rgb(57, 166, 255); background-color: rgb(207, 233, 255);border-radius: 6px;margin-top:10px;
            display: flex;justify-content: space-between;align-items: center;
        }
        
        /* loading效果 开始 */
        .circular-box {
            animation: loading-rotate 2s linear infinite;
        }
        
        .circle {
            stroke-dasharray: 900;
            stroke-dashoffset: -3;
            animation: loading-dash 1.5s ease-in-out infinite;
        }
        @keyframes loading-dash {
            0% {
                stroke-dasharray: 1, 200;
                stroke-dashoffset: 0;
            }
            50% {
                stroke-dasharray: 90, 150;
                stroke-dashoffset: -40;
            }
            100% {
                stroke-dasharray: 90, 150;
                stroke-dashoffset: -120;
            }
        }
        @keyframes loading-rotate {
            100% {
                transform: rotate(360deg);
            }
        }
        /* loading效果 结束 */
    
        .check-status {
            display: flex; justify-content: flex-start; align-items: center;
        }
    </style>
    <script src="lib/vue.global.prod.js"></script>
    <script>

    </script>
</head>
<body>
    <div id="app">
        <h2>服务器健康检查</h2>
        <div class="controls">
            <div class="mode-switch">
                <div :class="['mode-switch-item', mode === 'Auto' ? 'mode-switch-item-active' : '']" @click="switchMode('Auto')">自动</div>
                <div :class="['mode-switch-item', mode === 'Manual' ? 'mode-switch-item-active' : '']" @click="switchMode('Manual')">手动</div>
            </div>
            <button class="button" @click="start" :disable="status === 'Start'" style="margin-left:100px;">
                <div v-if="status === 'Stoped'">开始</div>
                <div v-if="status === 'Started'">进行中</div>
            </button>
            <button class="button" @click="stop" :disable="status === 'Stoped'" style="margin-left:10px;">停止</button>
        </div>
        <div style="margin-top:20px;">
            <div class="tab-header">
                <div v-for="(group, index) in serverGroups" :class="['tab-header-item', currentTabIndex === index ? 'tab-header-item-active' : '']" @click="switchGroup(index)">
                    {{ group.groupName }}
                </div>
            </div>
            <div class="tab-bodyer">
                <div v-for="(group, index) in serverGroups" :class="['tab-bodyer-item', currentTabIndex === index ? 'tab-bodyer-item-active' : '']">
                    <div v-for="(server, ii) in group.servers" class="tab-bodyer-item-server">
                        <div style="width:100%;padding-left:20px;">
                            <div style="font-size:20px;font-weight: bold;">{{ server.name }}</div>
                            <div style="color:#444;">{{ server.url }}</div>
                        </div>
                        <div style="width:200px;display: flex;justify-content: flex-start;align-items: center;">
                            <div v-if="server.checkStatus === 'checking'" class="check-status">
                                <svg style="width:26px;height:26px;" viewBox="0 0 50 50" class="circular-box">
                                    <circle class="circle" cx="25" cy="25" r="20" fill="none" stroke-width="2" stroke="blue"></circle>
                                </svg>
                                <div style="margin-left:10px;">
                                    检查中...
                                </div>
                            </div>
                            <div v-if="server.checkStatus === 'fail'" class="check-status">
                                <svg xmlns="http://www.w3.org/2000/svg" style="width:30px;height:30px;" viewBox="0 0 24 24" stroke-width="1.5" stroke="#ff2825" fill="none" stroke-linecap="round" stroke-linejoin="round">
                                    <path stroke="none" d="M0 0h24v24H0z" fill="none"/>
                                    <path d="M18 6l-12 12" />
                                    <path d="M6 6l12 12" />
                                </svg>
                                <div style="margin-left:2px;">
                                    连接失败
                                </div>
                            </div>
                            <div v-if="server.checkStatus === 'timeout'" class="check-status">
                                <svg xmlns="http://www.w3.org/2000/svg" style="width:30px;height:30px;" viewBox="0 0 24 24" stroke-width="1.5" stroke="#ff2825" fill="none" stroke-linecap="round" stroke-linejoin="round">
                                    <path stroke="none" d="M0 0h24v24H0z" fill="none"/>
                                    <path d="M20.986 12.502a9 9 0 1 0 -5.973 7.98" />
                                    <path d="M12 7v5l3 3" />
                                    <path d="M19 16v3" />
                                    <path d="M19 22v.01" />
                                </svg>
                                <div style="margin-left:6px;">
                                    超时
                                </div>
                            </div>
                            <div v-if="server.checkStatus === 'success'" class="check-status">
                                <svg xmlns="http://www.w3.org/2000/svg" style="width:30px;height:30px;" viewBox="0 0 24 24" stroke-width="1.5" stroke="#00b341" fill="none" stroke-linecap="round" stroke-linejoin="round">
                                    <path stroke="none" d="M0 0h24v24H0z" fill="none"/>
                                    <path d="M5 12l5 5l10 -10" />
                                </svg>
                                <div style="margin-left:2px;">
                                    正常
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>



        
    </div>
    <script>
        const { createApp, ref, onMounted } = Vue
        createApp({
            setup() {
                const serverGroups = ref([
                    {
                        groupName: 'tplus',
                        servers: [
                            {
                                name: '601',
                                url: 'http://tplus601.seentao.com/tplus/tapi/v1/customlogo/getLogo',
                                checkStatus: 'none'
                            }, {
                                name: '602',
                                url: 'http://tplus602.seentao.com/tplus/tapi/v1/customlogo/getLogo',
                                checkStatus: 'none'
                            }, {
                                name: '603',
                                url: 'http://tplus603.seentao.com/tplus/tapi/v1/customlogo/getLogo',
                                checkStatus: 'none'
                            }, {
                                name: '604',
                                url: 'http://tplus604.seentao.com/tplus/tapi/v1/customlogo/getLogo',
                                checkStatus: 'none'
                            }, {
                                name: '605',
                                url: 'http://tplus605.seentao.com/tplus/tapi/v1/customlogo/getLogo',
                                checkStatus: 'none'
                            }
                        ]
                    },
                    {
                        groupName: 't3',
                        servers: [
                            {
                                name: 't01',
                                url: 'https://t3.seentao.com/portal/portal.jsp',
                                checkStatus: 'success'
                            }, {
                                name: 't02',
                                url: 'https://t3.seentao.com/portal/portal.jsp',
                                checkStatus: 'fail'
                            }, {
                                name: 't03',
                                url: 'https://t3.seentao.com/portal/portal.jsp',
                                checkStatus: 'timeout'
                            }, {
                                name: 't03',
                                url: 'https://t3.seentao.com/portal/portal.jsp',
                                checkStatus: 'checking'
                            },
                        ]
                    }
                ])

                const mode = ref('Auto')
                const currentTabIndex = ref(0)
                let autoCheckIntval = null
                const status = ref('Stoped')
                function start() {
                    console.log('start')
                    if (mode.value === 'Manual') {
                        checkCurrentServersGroup()
                    } else {
                        checkCurrentServersGroup()
                        autoCheckIntval = setInterval(checkCurrentServersGroup, 10 * 1000)
                    }
                    status.value = 'Started'
                }
                
                function stop() {
                    clearInterval(autoCheckIntval)
                    status.value = 'Stoped'
                }

                function checkCurrentServersGroup()  {
                    console.log('checked...')
                    serverGroups.value[currentTabIndex.value].servers.forEach(server => {
                        server.checkStatus = 'checking'
                        const controller = new AbortController(); // 超时处理
                        const signal = controller.signal;
                        setTimeout(() => {
                            controller.abort(); // 放弃请求
                            server.checkStatus = 'timeout'
                        }, 5000);
                        // (get、post、跨域)请求参考:https://blog.csdn.net/m0_71469120/article/details/130795756
                        fetch(server.url, {
                            method: 'get',
                            headers: {
                                'Origin': 'https://tplus.seentao.com/' // 设置请求的来源,后端需要在响应头中添加Access-Control-Allow-Origin,包含此值,支持跨域。
                            },
                            responseType: 'json',
                            signal: signal // 超时处理配置
                        })
                        .then(response => {
                            if (response.ok) { // HTTP状态码200-299范围
                                server.checkStatus = 'success'
                                return response.json()
                            } else { // 其他的都是发生了错误
                                server.checkStatus = 'fail'
                            }
                        })
                        .then(result => {
                            console.info('res:', result);
                        })
                        .catch(error => {
                            console.error('Error:', error);
                        })
                    });
                }

                function switchMode(modeValue) {
                    mode.value = modeValue
                }

                function switchGroup(index) {
                    currentTabIndex.value = index
                }

                

                return {
                    serverGroups, mode, currentTabIndex, status, start, stop, switchMode, switchGroup
                }
            }
        }).mount('#app')
    </script>
</body>

 

标签:flex,url,com,seentao,checkStatus,服务器,健康检查,border,fetch
From: https://www.cnblogs.com/jsper/p/17740549.html

相关文章

  • 服务器阿贝云使用体验
    先稍微介绍一下this服务器在网上找了很久的云服务器,真正免费且安全的有阿里云和腾讯的体验服务器,阿里云还有高校学生专属体验服务器,只要通过高校身份验证即可申请创建服务器实例不过这一次谈到,是一个不完全免费的服务器:阿贝云服务器勉强能用的配置带上略微拘谨的带宽,用来挂着(......
  • 主流常见关系数据库分页sql语句写法。MySQL、PostgreSQL、SQLite、Oracle、DB2、SQL S
    前言1.分页sql逻辑:每页10条,取第3页。即取第21~30条数据1.1.MySQL/SQLite/PostgreSQLselect*fromdemolimit10offset20;select*fromdemolimit20,10;--PostgreSQL不支持该写法1.2.Oracle12C+Oracle11g之前很难用,Oracle12C+与MySQL用法格式一样了,只是语法关......
  • Prometheus+Grafana+Jmeter监控服务器资源及中间件(超详细)
    一、Prometheus&node_exporter&Grafana的原理Prometheus:Prometheus是一个开源的系统监控和报警工具包,它负责定时从各种数据源(如NodeExporter)中获取指标数据,并将其存储在自己的时间序列数据库中。Prometheus支持灵活的查询和报警功能,用户可以方便地对这些指标数据进行查询......
  • 三丰 /////云免费云服务器的使用体验
    在网上看到了三风云主机的介绍,想着试试看就注册了账号搞了一个免费云服务器试试,怎么说呢,作为一个新手,之前完全没有接触过云服务器,使用了三f云的免费云服务器,整个过程非常简单,很快就可以完成服务器的设置和部署。官方也提供了带面板的和纯净的centos,对于我来说还是挺方便的,而且我是......
  • VScode中下载了插件但是无法找到SSH Target连接服务器的解决方法(CANNOT find SSH Targ
    VSCode版本vscodeversion:(version1.82)已下载扩展installedextensions:Remote-SSHv0.106.4Remote-SSH:EditingConfigurationFilesv0.86.0RemoteDevelopmentv0.24.0WSLv0.81.3几天前我从pycharm转战vscode,在连接服务器时遇到了一些问题。根据一些较为古早的......
  • Ubuntu服务器安全性提升:修改SSH默认端口号
    在Ubuntu服务器上,SSH(SecureShell)是一种至关重要的远程连接工具。它提供了一种安全的方式来远程连接和管理计算机系统,通过加密通信来确保数据的保密性和完整性。SSH协议广泛用于计算机网络中,用于远程管理、文件传输和安全通信等任务。然而,SSH默认使用的端口号是22,这也是黑客们常常......
  • 解决服务器取证过程中宝塔强制绑定手机号的问题
    声明本文中提及的方式仅是为了便于服务器取证的研究,仅适用于无法出网的真实取证鉴定情况。请不要在生产环境随意修改宝塔服务的任何文件!分析目前,宝塔面板已经强制要求绑定手机号。这给取证工作带来很大的不便,尤其是在实际工作中,服务器是不可以连接互联网的,因此必须解决掉这个......
  • Go每日一库之131:caddy(轻量web服务器)
    一直以来,我都是使用Nginx作为Web服务器,但是配置可以说是非常麻烦了。每次我要新开一个域名,都要先使用acme.sh签发SSL证书,然后再写配置,大概要花上5分钟的时间。曾经想过写个脚本自动完成这些工作,但是苦于对Linux的了解不多,也就作罢了。最近看到了Caddy,一个用Go写的......
  • openGauss学习笔记-84 openGauss 数据库管理-内存优化表MOT管理-内存表特性-MOT部署服
    openGauss学习笔记-84openGauss数据库管理-内存优化表MOT管理-内存表特性-MOT部署服务器优化:x86通常情况下,数据库由以下组件绑定:CPU:更快的CPU可以加速任何CPU绑定的数据库。磁盘:高速SSD/NVME可加速任何I/O绑定数据库。网络:更快的网络可以加速任何SQL*Net绑定数据库。除以......
  • 三f云免费云服务器的使用体验
    在网上看到了三f云主机的介绍,想着试试看就注册了账号搞了一个免费云服务器试试,怎么说呢,作为一个新手,之前完全没有接触过云服务器,使用了三f云的免费云服务器,整个过程非常简单,很快就可以完成服务器的设置和部署。官方也提供了带面板的和纯净的centos,对于我来说还是挺方便的,而且我是......