--- title: 博客友链实时健康监测方案 date: 2026-02-01T01:00:00.000Z draft: false categories: - 技术 tags: - GitHub Actions - Node.js - 博客优化 - 自动化 ai_comment: >- 这个友链监测方案设计得很周全,技术上亮点不少。并发控制+连接复用的组合拳很实用,能有效降低检测延迟。建议可以补充一个重试退避机制,避免因临时网络抖动误判。前端展示的克制设计值得点赞,不过可以考虑在hover时显示具体状态码,方便调试。GitHub Actions的邮件通知处理得很优雅,把运维细节藏在了后台。 slug: 20260201 --- 最近给博客加上了一个实用的功能:**友链实时健康监测**。 起因是备案审查越来越严格。对于个人博客来说,如果友链中的某个域名过期被抢注,摇身一变成为博彩或色情网站,而我的博客还挂着它的链接,那么我的域名很有可能因为“导流违规内容”而被注销备案,甚至面临关站风险。 为了避免这种“人在家中坐,锅从天上来”的情况,手动每天一个个点开检查显然是不现实的。于是,利用 GitHub Actions 和简单的 Node.js 脚本实现自动化监测,就成了最佳解决方案。 ## 实现思路 整体流程分为三个环节: 1. **数据源**:读取博客现有的友链配置文件(YAML 格式)。 2. **监测脚本**:编写 Node.js 脚本,利用并发和连接复用技术,批量检测 HTTP 状态码。 3. **自动化与通知**:通过 GitHub Actions 定时执行,生成状态报告(JSON),并在发现异常时发送邮件通知。 4. **前端展示**:在页面上以不打扰的 UI 风格(黑白极简风格)展示友链状态。 ## 1. 编写监测脚本 在 `scripts/check_links.js` 中,我使用了 `axios` 发送请求,并配合 `https.Agent` 实现了连接复用(Keep-Alive),同时通过并发池控制请求速率。 这个脚本的核心亮点是: - **并发控制**:开启 10 个 Worker 并行检测,大幅缩短耗时。 - **连接复用**:开启 `keepAlive: true`,减少 TCP/TLS 握手开销。 - **智能重试**:优先使用 `HEAD` 请求(省流量),失败后自动降级为 `GET` 请求。 - **异常汇总**:将失效链接写入 `failed_links_summary.txt`,用于后续邮件通知。 ```javascript const fs = require('fs'); const yaml = require('js-yaml'); const axios = require('axios'); const path = require('path'); const https = require('https'); const http = require('http'); // ... 路径配置 ... // 优化 Axios 实例:开启 Keep-Alive 复用连接 const axiosInstance = axios.create({ timeout: 10000, maxRedirects: 5, httpAgent: new http.Agent({ keepAlive: true }), httpsAgent: new https.Agent({ keepAlive: true }), headers: { 'User-Agent': 'Mozilla/5.0 ...' // 模拟浏览器 UA }, validateStatus: (status) => status >= 200 && status < 400 }); async function checkUrl(url) { try { await axiosInstance.head(url); return true; } catch (error) { try { await axiosInstance.get(url); // HEAD 失败尝试 GET return true; } catch (err2) { return false; } } } // ... 并发 Worker 逻辑 ... ``` ## 2. 配置 GitHub Actions 为了保证数据的实时性,我在 `.github/workflows/upy.yml` 中配置了定时任务。 - **定时触发**:每 12 小时自动运行一次 (`cron: '0 */12 * * *'`)。 - **邮件通知**:如果发现失效友链,Workflow 会读取脚本生成的摘要文件,并通过邮件推送到我的邮箱。 ```yaml on: schedule: - cron: '0 */12 * * *' # 每12小时自动检查一次 jobs: deploy: steps: # ... 其他步骤 ... - name: Check Link Status run: node scripts/check_links.js - name: Read Failed Links Summary if: always() run: | if [ -f failed_links_summary.txt ]; then echo "LINK_SUMMARY<> $GITHUB_ENV cat failed_links_summary.txt >> $GITHUB_ENV echo "EOF" >> $GITHUB_ENV fi # ... 构建步骤 ... - name: Send deployment success notification if: success() uses: dawidd6/action-send-mail@v3 with: # ... 邮件配置 ... body: | # ... 其他信息 ... 📊 友链监测报告 ---------------------------------- ${{ env.LINK_SUMMARY }} ``` ## 3. 前端展示:极简设计 为了不破坏博客原本的黑白极简风格,我并没有使用传统的“红/绿”大色块,而是设计了一套低调的状态指示器。 ### JS 逻辑 (`main.js`) 前端脚本会异步加载 `link_status.json`,并智能匹配 URL(自动处理 `https` 和尾部 `/` 的差异)。 ```javascript window.initLinkStatus = function() { fetch('/link_status.json?t=' + new Date().getTime()) .then(response => response.json()) .then(data => { // ... 遍历 DOM 元素 ... // getUrlStatus 逻辑:尝试匹配 url, url/, https/http 变体 if (status === 'alive') { $item.append(''); } else if (status === 'dead') { $item.append(''); } }); }; ``` ### CSS 样式 (`main.css`) 这里花了一些心思调整配色。为了避免“红绿灯”配色的突兀感: - **正常状态**:使用**实心灰点** (`#9ca3af`),在暗色模式下为浅灰 (`#d1d5db`)。 - **失效状态**:使用**空心灰圈**(白色/深色中心 + 灰色边框)。 这种设计既能传达状态信息,又完美融入了黑白主题。 ```css /* Card View - Active (实心灰点) */ .link-active-badge { position: absolute; top: 8px; right: 8px; width: 8px; height: 8px; background-color: #9ca3af; border-radius: 50%; border: 2px solid #fff; } /* Card View - Dead (空心灰圈) */ .link-dead-badge { position: absolute; top: 8px; right: 8px; width: 8px; height: 8px; background-color: #fff; border-radius: 50%; border: 2px solid #9ca3af; /* 灰色边框形成空心效果 */ } ``` ## 总结 这套方案最大的好处是**零成本、自动化且优雅**。 1. **零成本**:完全利用 GitHub Actions 的计算资源。 2. **自动化**:定时检查 + 邮件报警,无需人工干预。 3. **优雅**:前端 UI 克制且统一,不喧宾夺主。 对于注重 SEO 和网站安全的博主来说,这是一个性价比极高的“基建”工作。既对自己负责,也对访客负责。毕竟,谁也不想点击一个链接后发现是 404,或者跳转到奇怪的页面吧。