本文目录导读:

针对PHP项目的域名解析异常告警与DNS自动切换,可以采用以下分层方案:
核心监控脚本(PHP + Shell)
监控脚本示例 (dns_monitor.sh)
#!/bin/bash
# DNS解析监控脚本
DOMAIN="yourdomain.com"
PRIMARY_DNS="8.8.8.8" # 主DNS
BACKUP_DNS="1.1.1.1" # 备用DNS
ALERT_EMAIL="ops@yourcompany.com"
CHECK_INTERVAL=60
check_dns() {
local dns=$1
local result=$(dig @$dns $DOMAIN +short +timeout=5 2>/dev/null)
if [ -z "$result" ]; then
echo "DNS解析失败: $dns"
return 1
fi
echo "DNS正常: $result"
return 0
}
# 主DNS重试检测
for i in {1..3}; do
if check_dns $PRIMARY_DNS; then
echo "主DNS正常"
exit 0
fi
sleep 2
done
# 触发告警并切换
echo "主DNS异常,尝试切换到备用DNS" | mail -s "【紧急】DNS解析异常告警" $ALERT_EMAIL
# 切换系统DNS
echo "nameserver $BACKUP_DNS" > /etc/resolv.conf.bak
cp /etc/resolv.conf.bak /etc/resolv.conf
# 验证备用DNS
if ! check_dns $BACKUP_DNS; then
echo "备用DNS也异常,启动紧急预案" | mail -s "【严重】双DNS异常" $ALERT_EMAIL
fi
PHP应用层监控组件
自定义DNS解析类 (DnsMonitor.php)
<?php
class DnsMonitor {
private $domain;
private $primaryDns = ['8.8.8.8', '8.8.4.4'];
private $backupDns = ['1.1.1.1', '1.0.0.1'];
private $errorThreshold = 3;
private $errorCount = 0;
public function __construct($domain) {
$this->domain = $domain;
}
/**
* 智能DNS解析(带自动切换)
*/
public function resolveWithFailover() {
// 尝试主DNS
$result = $this->resolveWithDNS($this->primaryDns);
if ($result !== false) {
$this->errorCount = 0;
return $result;
}
// 记录异常
$this->errorCount++;
$this->logError('主DNS解析失败');
// 触发阈值告警
if ($this->errorCount >= $this->errorThreshold) {
$this->triggerAlert('DNS解析连续失败'.$this->errorCount.'次');
}
// 自动切换到备用DNS
$backupResult = $this->resolveWithDNS($this->backupDns);
if ($backupResult !== false) {
$this->log('已切换至备用DNS');
return $backupResult;
}
// 双DNS均失败
$this->triggerAlert('主备DNS均解析失败,使用PHP默认DNS');
return dns_get_record($this->domain, DNS_A);
}
private function resolveWithDNS($dnsList) {
$context = stream_context_create([
'dns' => [
'nameservers' => $dnsList,
'timeout' => 3
]
]);
$result = @dns_get_record($this->domain, DNS_A, $dnsList);
return $result ?: false;
}
private function triggerAlert($message) {
// 告警方式1:日志
error_log(date('Y-m-d H:i:s')." [DNS_ALERT] $message\n", 3, '/var/log/dns_alert.log');
// 告警方式2:邮件
mail('ops@company.com', 'DNS解析异常', $message);
// 告警方式3:Webhook推送
$this->sendWebhook($message);
}
private function sendWebhook($message) {
$webhookUrl = 'https://hooks.slack.com/services/YOUR_WEBHOOK';
$payload = json_encode(['text' => "[DNS告警] $message"]);
$ch = curl_init($webhookUrl);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
curl_exec($ch);
curl_close($ch);
}
}
// 使用示例
$monitor = new DnsMonitor('api.yourproject.com');
$ips = $monitor->resolveWithFailover();
故障注入与测试
测试脚本 (test_dns_failover.php)
<?php
// 模拟DNS故障
$monitor = new DnsMonitor('example.com');
// 测试1: 正常解析
echo "测试1 - 正常解析:\n";
$result = $monitor->resolveWithFailover();
print_r($result);
// 测试2: 模拟主DNS超时
echo "测试2 - 主DNS超时:\n";
$monitor->primaryDns = ['10.0.0.1']; // 无效DNS
$result = $monitor->resolveWithFailover();
echo $result ? "切换到备用DNS成功\n" : "全部失败\n";
// 测试3: 连续故障告警
echo "测试3 - 连续故障告警:\n";
for ($i=0; $i<5; $i++) {
$monitor->errorCount = 0;
$result = $monitor->resolveWithFailover();
echo "尝试#$i: ".($result ? '成功' : '失败')."\n";
}
生产环境部署建议
系统级配置
# Nginx DNS resolver配置
location /api/ {
resolver 8.8.8.8 1.1.1.1 valid=30s;
set $backend "your-api-server.com";
proxy_pass http://$backend;
}
Docker环境DNS配置
# docker-compose.yml
services:
php:
image: your-php-app
dns:
- 8.8.8.8
- 1.1.1.1
environment:
- DNS_PRIMARY=8.8.8.8
- DNS_BACKUP=1.1.1.1
监控与告警最佳实践
使用Prometheus监测
# prometheus dns_exporter配置
dns:
targets:
- yourdomain.com
query_name: "yourdomain.com"
query_type: "A"
dns_server: "8.8.8.8"
timeout: 5
alert:
- name: dns_resolution_failed
for: 30s
severity: critical
告警通道配置
- 即时告警:Slack/飞书 Webhook(配置在
sendWebhook方法中) - 紧急短信:通过API调用七牛云/阿里云短信接口
- 电话告警:集成PagerDuty或自建IVR系统
异常恢复机制
#!/bin/bash
# 自动恢复脚本 dns_recovery.sh
check_dns_health() {
while true; do
# 尝试恢复主DNS
if dig @8.8.8.8 yourdomain.com +short > /dev/null 2>&1; then
echo "主DNS已恢复"
sed -i 's/nameserver 1.1.1.1/nameserver 8.8.8.8/' /etc/resolv.conf
systemctl restart php-fpm
break
fi
sleep 60
done
}
核心要点:
- 三层检测:系统级(Ping/Dig) → PHP应用层 → 业务逻辑层
- 智能切换:连续错误次数达到阈值才切换,避免误切
- 恢复机制:至少30分钟自动检测恢复,降低管理员负担
- 告警分级:解析失败→切换告警→双DNS失败→严重告警