DNS 性能监控
DNS-Go 提供实时的 DNS 性能监控功能,帮助您了解 DNS 服务器的运行状态和查询性能。
功能概述
DNS 性能监控模块提供以下功能:
- 实时 QPS 监控:显示当前查询速率、平均 QPS、峰值 QPS
- 查询统计:总查询量、今日查询量
- 响应时间分析:平均响应时间、最小/最大响应时间、P50/P95/P99 分位数
- 解析成功率:成功解析次数、失败次数、缓存命中率
- 客户端统计:活跃客户端数、总客户端数、平均每客户端查询量
- 查询类型分布:A、AAAA、CNAME、MX 等查询类型的分布情况
- 上游性能监控:各上游 DNS 服务器的响应时间和成功率
架构设计
数据流
DNS 查询 → 查询日志记录 → 实时统计计算 → SSE 推送 → 前端展示核心组件
- 数据收集层:在 DNS 查询处理过程中记录查询日志
- 统计计算层:定期计算各项性能指标
- 实时推送层:通过 SSE (Server-Sent Events) 向前端推送实时数据
- 可视化层:前端使用图表展示性能数据
实现细节
后端实现
1. 数据模型
go
// 查询统计概览
type QueryStatsOverview struct {
TotalQueries int64 `json:"total_queries"` // 总查询量
TodayQueries int64 `json:"today_queries"` // 今日查询量
CurrentQps float64 `json:"current_qps"` // 当前 QPS
AvgQps float64 `json:"avg_qps"` // 平均 QPS
PeakQps float64 `json:"peak_qps"` // 峰值 QPS
UpdateTime string `json:"update_time"` // 更新时间
FormattedQps string `json:"formatted_qps"` // 格式化 QPS
FormattedAvgQps string `json:"formatted_avg_qps"` // 格式化平均 QPS
}
// 响应时间统计
type ResponseTimeStats struct {
AvgResponseMs float64 `json:"avg_response_ms"` // 平均响应时间
MinResponseMs int64 `json:"min_response_ms"` // 最小响应时间
MaxResponseMs int64 `json:"max_response_ms"` // 最大响应时间
P50ResponseMs int64 `json:"p50_response_ms"` // P50 分位数
P95ResponseMs int64 `json:"p95_response_ms"` // P95 分位数
P99ResponseMs int64 `json:"p99_response_ms"` // P99 分位数
TotalSamples int64 `json:"total_samples"` // 样本总数
}
// 解析统计
type ResolutionStats struct {
SuccessCount int64 `json:"success_count"` // 成功次数
FailedCount int64 `json:"failed_count"` // 失败次数
CachedCount int64 `json:"cached_count"` // 缓存命中次数
TotalCount int64 `json:"total_count"` // 总次数
SuccessRate float64 `json:"success_rate"` // 成功率
CacheHitRate float64 `json:"cache_hit_rate"` // 缓存命中率
}
// 客户端统计
type ClientStats struct {
ActiveClients int64 `json:"active_clients"` // 活跃客户端数
NewClientsToday int64 `json:"new_clients_today"` // 今日新增客户端
AvgQueriesPerClient float64 `json:"avg_queries_per_client"` // 平均每客户端查询量
TotalClients int64 `json:"total_clients"` // 总客户端数
}2. 实时数据推送
使用 SSE (Server-Sent Events) 实现实时数据推送:
go
// SSE 监控流
func (h *DnsMonitorHandler) MonitorSSE(c *gin.Context) {
// 设置 SSE 响应头
c.Header("Content-Type", "text/event-stream")
c.Header("Cache-Control", "no-cache")
c.Header("Connection", "keep-alive")
c.Header("X-Accel-Buffering", "no")
// 创建监控会话
session := h.service.CreateMonitorSession()
defer h.service.CloseMonitorSession(session.ID)
// 发送初始连接成功事件
c.SSEvent("connected", gin.H{
"status": "connected",
"timestamp": time.Now().Format(time.RFC3339),
})
c.Writer.Flush()
// 启动数据推送循环
ticker := time.NewTicker(5 * time.Second)
defer ticker.Stop()
for {
select {
case <-c.Request.Context().Done():
return
case <-ticker.C:
// 获取最新监控数据
data := h.service.GetMonitorData()
c.SSEvent("monitor", data)
c.Writer.Flush()
}
}
}3. 统计计算
go
// 计算当前 QPS
func calculateCurrentQps() float64 {
oneMinuteAgo := time.Now().Add(-1 * time.Minute)
lastMinuteQueries := getQueryCountSince(oneMinuteAgo)
return float64(lastMinuteQueries) / 60.0
}
// 计算平均 QPS
func calculateAvgQps(startTime, endTime time.Time) float64 {
duration := endTime.Sub(startTime).Seconds()
if duration <= 0 {
return 0
}
queryCount := getQueryCountInRange(startTime, endTime)
return float64(queryCount) / duration
}
// 计算响应时间分位数
func calculateResponseTimePercentile(percentile float64) int64 {
// 从数据库获取响应时间数据
responseTimes := getResponseTimes()
return calculatePercentile(responseTimes, percentile)
}前端实现
1. 组件结构
DnsPerformance/
├── index.vue # 主页面
├── components/
│ ├── QueryStatsCard.vue # 查询统计卡片
│ ├── ResponseTimeCard.vue # 响应时间卡片
│ ├── ResolutionStatsCard.vue # 解析统计卡片
│ ├── ClientStatsCard.vue # 客户端统计卡片
│ ├── QueryTypeChart.vue # 查询类型分布图表
│ ├── TrendChart.vue # 趋势图表
│ └── UpstreamPerformanceCard.vue # 上游性能卡片2. SSE 连接管理
typescript
// 创建 SSE 连接
const createSSEConnection = () => {
const eventSource = new EventSource(
`${import.meta.env.VITE_API_URL}/api/monitor/sse`
);
eventSource.addEventListener("connected", (event) => {
console.log("SSE 连接成功:", JSON.parse(event.data));
});
eventSource.addEventListener("monitor", (event) => {
const data = JSON.parse(event.data);
updateMonitorData(data);
});
eventSource.onerror = (error) => {
console.error("SSE 连接错误:", error);
// 自动重连
setTimeout(createSSEConnection, 5000);
};
return eventSource;
};3. 数据展示
使用 Element Plus 的统计卡片和 ECharts 图表展示数据:
vue
<template>
<div class="dns-performance">
<el-row :gutter="16">
<!-- QPS 统计 -->
<el-col :xs="24" :sm="12" :md="6">
<QueryStatsCard :data="queryStats" />
</el-col>
<!-- 响应时间 -->
<el-col :xs="24" :sm="12" :md="6">
<ResponseTimeCard :data="responseStats" />
</el-col>
<!-- 解析成功率 -->
<el-col :xs="24" :sm="12" :md="6">
<ResolutionStatsCard :data="resolutionStats" />
</el-col>
<!-- 客户端统计 -->
<el-col :xs="24" :sm="12" :md="6">
<ClientStatsCard :data="clientStats" />
</el-col>
</el-row>
<!-- 图表区域 -->
<el-row :gutter="16" class="chart-row">
<el-col :xs="24" :lg="12">
<QueryTypeChart :data="queryTypeDistribution" />
</el-col>
<el-col :xs="24" :lg="12">
<TrendChart :data="trendData" />
</el-col>
</el-row>
</div>
</template>API 接口
获取查询统计概览
http
GET /api/monitor/query-stats响应:
json
{
"total_queries": 120,
"today_queries": 20,
"current_qps": 0.33,
"avg_qps": 0.01,
"peak_qps": 0.5,
"update_time": "2026-02-17T13:19:56+08:00",
"formatted_qps": "0.33",
"formatted_avg_qps": "0.01"
}获取响应时间统计
http
GET /api/monitor/response-stats获取解析统计
http
GET /api/monitor/resolution-stats获取客户端统计
http
GET /api/monitor/client-stats获取查询类型分布
http
GET /api/monitor/query-typesSSE 实时监控流
http
GET /api/monitor/sse配置说明
监控参数配置
在 config.toml 中可以配置监控相关参数:
toml
[monitor]
# 数据刷新间隔(秒)
refresh_interval = 5
# 统计时间窗口(分钟)
stats_window = 60
# 是否启用实时监控
enable_realtime = true
# 客户端活跃超时时间(分钟)
client_timeout = 30性能优化
- 数据缓存:使用内存缓存存储最近的数据,减少数据库查询
- 增量更新:只推送变化的数据,减少网络传输
- 连接池管理:合理管理 SSE 连接,避免资源泄漏
- 采样策略:对于高频查询,采用采样策略减少计算量
故障排查
常见问题
SSE 连接失败
- 检查网络连接
- 确认服务器支持 SSE
- 查看浏览器控制台错误信息
数据不更新
- 检查监控服务是否正常运行
- 确认数据库连接正常
- 查看服务端日志
QPS 显示为 0
- 检查是否有 DNS 查询流量
- 确认查询日志记录正常
- 验证时间范围设置
日志查看
bash
# 查看监控服务日志
docker logs dns-go | grep monitor
# 查看实时日志
docker logs -f dns-go最佳实践
- 合理设置刷新间隔:根据实际需求设置刷新间隔,避免过于频繁的更新
- 关注关键指标:重点关注 QPS、响应时间、成功率等核心指标
- 设置告警阈值:为关键指标设置告警阈值,及时发现异常
- 定期分析趋势:通过趋势图表分析 DNS 使用模式和性能变化