🔍 整体诊断流程
graph TB
Start([App访问CDN失败
无访问日志]) --> Check1{1. DNS解析
是否正常?} Check1 -->|解析失败| Problem1[DNS问题] Check1 -->|解析成功| Check2{2. 解析到的IP
是否正确?} Check2 -->|IP错误| Problem2[DNS劫持/配置错误] Check2 -->|IP正确| Check3{3. 网络连通性
是否正常?} Check3 -->|不通| Problem3[网络层问题] Check3 -->|连通| Check4{4. HTTP请求
是否发出?} Check4 -->|未发出| Problem4[App代码问题] Check4 -->|已发出| Check5{5. CDN节点
是否响应?} Check5 -->|无响应| Problem5[CDN节点问题] Check5 -->|有响应| Check6{6. 响应状态码
是什么?} Check6 -->|4xx| Problem6[资源/权限问题] Check6 -->|5xx| Problem7[CDN服务器问题] Check6 -->|其他| Problem8[其他异常] Problem1 --> Solution1[诊断方案1:
DNS排查] Problem2 --> Solution2[诊断方案2:
DNS劫持检测] Problem3 --> Solution3[诊断方案3:
网络连通性检测] Problem4 --> Solution4[诊断方案4:
App代码审查] Problem5 --> Solution5[诊断方案5:
CDN节点检测] Problem6 --> Solution6[诊断方案6:
资源配置检查] Problem7 --> Solution7[诊断方案7:
CDN服务检查] Problem8 --> Solution8[诊断方案8:
综合分析] style Start fill:#f44336,stroke:#c62828,color:#fff style Problem1 fill:#ff9800,stroke:#f57c00,color:#fff style Problem2 fill:#ff9800,stroke:#f57c00,color:#fff style Problem3 fill:#ff9800,stroke:#f57c00,color:#fff style Problem4 fill:#ff9800,stroke:#f57c00,color:#fff style Problem5 fill:#ff9800,stroke:#f57c00,color:#fff style Problem6 fill:#ff9800,stroke:#f57c00,color:#fff style Problem7 fill:#ff9800,stroke:#f57c00,color:#fff style Problem8 fill:#ff9800,stroke:#f57c00,color:#fff style Solution1 fill:#4caf50,stroke:#388e3c,color:#fff style Solution2 fill:#4caf50,stroke:#388e3c,color:#fff style Solution3 fill:#4caf50,stroke:#388e3c,color:#fff style Solution4 fill:#4caf50,stroke:#388e3c,color:#fff style Solution5 fill:#4caf50,stroke:#388e3c,color:#fff style Solution6 fill:#4caf50,stroke:#388e3c,color:#fff style Solution7 fill:#4caf50,stroke:#388e3c,color:#fff style Solution8 fill:#4caf50,stroke:#388e3c,color:#fff
无访问日志]) --> Check1{1. DNS解析
是否正常?} Check1 -->|解析失败| Problem1[DNS问题] Check1 -->|解析成功| Check2{2. 解析到的IP
是否正确?} Check2 -->|IP错误| Problem2[DNS劫持/配置错误] Check2 -->|IP正确| Check3{3. 网络连通性
是否正常?} Check3 -->|不通| Problem3[网络层问题] Check3 -->|连通| Check4{4. HTTP请求
是否发出?} Check4 -->|未发出| Problem4[App代码问题] Check4 -->|已发出| Check5{5. CDN节点
是否响应?} Check5 -->|无响应| Problem5[CDN节点问题] Check5 -->|有响应| Check6{6. 响应状态码
是什么?} Check6 -->|4xx| Problem6[资源/权限问题] Check6 -->|5xx| Problem7[CDN服务器问题] Check6 -->|其他| Problem8[其他异常] Problem1 --> Solution1[诊断方案1:
DNS排查] Problem2 --> Solution2[诊断方案2:
DNS劫持检测] Problem3 --> Solution3[诊断方案3:
网络连通性检测] Problem4 --> Solution4[诊断方案4:
App代码审查] Problem5 --> Solution5[诊断方案5:
CDN节点检测] Problem6 --> Solution6[诊断方案6:
资源配置检查] Problem7 --> Solution7[诊断方案7:
CDN服务检查] Problem8 --> Solution8[诊断方案8:
综合分析] style Start fill:#f44336,stroke:#c62828,color:#fff style Problem1 fill:#ff9800,stroke:#f57c00,color:#fff style Problem2 fill:#ff9800,stroke:#f57c00,color:#fff style Problem3 fill:#ff9800,stroke:#f57c00,color:#fff style Problem4 fill:#ff9800,stroke:#f57c00,color:#fff style Problem5 fill:#ff9800,stroke:#f57c00,color:#fff style Problem6 fill:#ff9800,stroke:#f57c00,color:#fff style Problem7 fill:#ff9800,stroke:#f57c00,color:#fff style Problem8 fill:#ff9800,stroke:#f57c00,color:#fff style Solution1 fill:#4caf50,stroke:#388e3c,color:#fff style Solution2 fill:#4caf50,stroke:#388e3c,color:#fff style Solution3 fill:#4caf50,stroke:#388e3c,color:#fff style Solution4 fill:#4caf50,stroke:#388e3c,color:#fff style Solution5 fill:#4caf50,stroke:#388e3c,color:#fff style Solution6 fill:#4caf50,stroke:#388e3c,color:#fff style Solution7 fill:#4caf50,stroke:#388e3c,color:#fff style Solution8 fill:#4caf50,stroke:#388e3c,color:#fff
📋 可能原因分析
| 层级 | 可能原因 | 无日志原因 | 概率 | 影响范围 |
|---|---|---|---|---|
| DNS层 | DNS解析失败 | 请求未到达CDN节点 | 高 | 特定网络环境 |
| DNS层 | DNS劫持/污染 | 解析到错误IP,未访问CDN | 中高 | 特定运营商/地区 |
| DNS层 | DNS缓存错误 | 使用旧IP,CDN节点已下线 | 中 | 个别设备 |
| 网络层 | 防火墙/运营商拦截 | 请求在中间环节被阻断 | 中高 | 特定网络/地区 |
| 网络层 | 网络不可达 | TCP连接建立失败 | 中 | 弱网环境 |
| 网络层 | 代理服务器问题 | 代理未转发到CDN | 中 | 使用代理的设备 |
| CDN层 | CDN域名配置错误 | 域名未接入CDN | 中高 | 全部用户 |
| CDN层 | 回源配置错误 | CDN无法记录失败请求 | 中 | 全部用户 |
| CDN层 | 日志采集异常 | 有访问但日志系统故障 | 低 | 日志查询 |
| 应用层 | App代码未发起请求 | 请求在App内被拦截/跳过 | 中高 | 特定版本/场景 |
| 应用层 | URL拼接错误 | 访问了错误域名 | 中 | 特定版本 |
| 应用层 | 证书验证失败 | HTTPS握手失败,请求中断 | 中 | HTTPS资源 |
🔧 诊断方案1:DNS解析排查
🌐
DNS解析全链路检测
sequenceDiagram
participant App as 📱 App应用
participant LocalDNS as 🖥️ 设备本地DNS
participant ISP as 🌍 运营商DNS
participant AuthDNS as ⚙️ 权威DNS
participant CDN as 🚀 CDN节点
App->>LocalDNS: 1. 查询 cdn.example.com
alt 本地有缓存
LocalDNS-->>App: 返回缓存IP
Note over LocalDNS: ⚠️ 可能是过期IP
else 无缓存
LocalDNS->>ISP: 2. 递归查询
ISP->>AuthDNS: 3. 查询权威DNS
alt DNS正常
AuthDNS-->>ISP: 4. 返回CDN IP
ISP-->>LocalDNS: 5. 返回结果
LocalDNS-->>App: 6. 返回IP
else DNS劫持
ISP-->>LocalDNS: ❌ 返回错误IP
LocalDNS-->>App: ❌ 返回错误IP
else DNS超时
AuthDNS--xISP: ⏱️ 解析超时
ISP--xLocalDNS: ⏱️ 超时
LocalDNS--xApp: ❌ 解析失败
end
end
App->>CDN: 7. 访问解析到的IP
alt IP正确
CDN-->>App: ✅ 返回资源
else IP错误
Note over App,CDN: ❌ 无法访问
无CDN日志 end
无CDN日志 end
检测步骤:
1
App内DNS解析测试
在App代码中添加DNS解析日志:
// iOS示例
NSString *hostname = @"cdn.example.com";
CFHostRef host = CFHostCreateWithName(kCFAllocatorDefault, (__bridge CFStringRef)hostname);
CFHostStartInfoResolution(host, kCFHostAddresses, NULL);
NSArray *addresses = (__bridge NSArray *)CFHostGetAddressing(host, NULL);
for (NSData *addressData in addresses) {
struct sockaddr_in *addr = (struct sockaddr_in *)[addressData bytes];
NSString *ip = [NSString stringWithUTF8String:inet_ntoa(addr->sin_addr)];
NSLog(@"DNS解析结果: %@ -> %@", hostname, ip);
}
// Android示例
InetAddress[] addresses = InetAddress.getAllByName("cdn.example.com");
for (InetAddress addr : addresses) {
Log.d("DNS", "解析结果: " + addr.getHostAddress());
}
2
命令行DNS查询
使用多个DNS服务器进行对比测试:
# 使用系统默认DNS
nslookup cdn.example.com
# 使用公共DNS对比
nslookup cdn.example.com 8.8.8.8 # Google DNS
nslookup cdn.example.com 114.114.114.114 # 国内DNS
nslookup cdn.example.com 1.1.1.1 # Cloudflare DNS
# 详细查询
dig cdn.example.com +trace # 追踪完整解析路径
dig cdn.example.com @8.8.8.8 +short # 简洁输出
3
验证解析结果
正常情况:
- 返回CDN节点IP(通常是CNAME指向)
- IP归属地应该是CDN服务商
- 不同地区返回不同IP(CDN智能调度)
- ❌ 解析超时或失败
- ❌ 返回源站IP而非CDN IP
- ❌ 返回非预期IP(可能被劫持)
- ❌ 不同DNS服务器返回结果不一致
4
DNS劫持检测图示
graph LR
A[App查询DNS] --> B{使用哪个DNS?}
B -->|运营商DNS| C[运营商DNS服务器]
B -->|公共DNS| D[公共DNS: 8.8.8.8]
C --> E{是否被劫持?}
D --> F[正确CDN IP]
E -->|是| G[错误IP
如: 广告服务器] E -->|否| H[正确CDN IP] G --> I[❌ 无法访问CDN
无访问日志] H --> J[✅ 正常访问] F --> J style A fill:#2196F3,stroke:#1976D2,color:#fff style G fill:#f44336,stroke:#c62828,color:#fff style I fill:#f44336,stroke:#c62828,color:#fff style J fill:#4caf50,stroke:#388e3c,color:#fff
如: 广告服务器] E -->|否| H[正确CDN IP] G --> I[❌ 无法访问CDN
无访问日志] H --> J[✅ 正常访问] F --> J style A fill:#2196F3,stroke:#1976D2,color:#fff style G fill:#f44336,stroke:#c62828,color:#fff style I fill:#f44336,stroke:#c62828,color:#fff style J fill:#4caf50,stroke:#388e3c,color:#fff
🛠️ 推荐工具
nslookup
dig
host
Charles (手机抓包)
Wireshark
在线DNS检测工具
🔧 诊断方案2:网络连通性检测
🌍
网络层连通性全面检测
graph TB
Start[DNS解析成功
获得CDN IP] --> Test1[ICMP测试
ping] Test1 --> Result1{能ping通?} Result1 -->|是| Test2[TCP连接测试
telnet/nc] Result1 -->|否| Check1[检查防火墙
ICMP可能被禁] Check1 --> Test2 Test2 --> Result2{端口连通?} Result2 -->|是| Test3[HTTP请求测试
curl/wget] Result2 -->|否| Problem1[❌ 端口被封
或CDN节点异常] Test3 --> Result3{HTTP响应?} Result3 -->|有响应| Check2[检查响应状态码] Result3 -->|无响应| Problem2[❌ HTTP层异常] Check2 --> Status{状态码} Status -->|200| Success[✅ 网络正常
问题在其他层] Status -->|4xx| Problem3[❌ 客户端错误
检查URL/权限] Status -->|5xx| Problem4[❌ 服务器错误
检查CDN配置] style Start fill:#2196F3,stroke:#1976D2,color:#fff style Success fill:#4caf50,stroke:#388e3c,color:#fff style Problem1 fill:#f44336,stroke:#c62828,color:#fff style Problem2 fill:#f44336,stroke:#c62828,color:#fff style Problem3 fill:#ff9800,stroke:#f57c00,color:#fff style Problem4 fill:#f44336,stroke:#c62828,color:#fff
获得CDN IP] --> Test1[ICMP测试
ping] Test1 --> Result1{能ping通?} Result1 -->|是| Test2[TCP连接测试
telnet/nc] Result1 -->|否| Check1[检查防火墙
ICMP可能被禁] Check1 --> Test2 Test2 --> Result2{端口连通?} Result2 -->|是| Test3[HTTP请求测试
curl/wget] Result2 -->|否| Problem1[❌ 端口被封
或CDN节点异常] Test3 --> Result3{HTTP响应?} Result3 -->|有响应| Check2[检查响应状态码] Result3 -->|无响应| Problem2[❌ HTTP层异常] Check2 --> Status{状态码} Status -->|200| Success[✅ 网络正常
问题在其他层] Status -->|4xx| Problem3[❌ 客户端错误
检查URL/权限] Status -->|5xx| Problem4[❌ 服务器错误
检查CDN配置] style Start fill:#2196F3,stroke:#1976D2,color:#fff style Success fill:#4caf50,stroke:#388e3c,color:#fff style Problem1 fill:#f44336,stroke:#c62828,color:#fff style Problem2 fill:#f44336,stroke:#c62828,color:#fff style Problem3 fill:#ff9800,stroke:#f57c00,color:#fff style Problem4 fill:#f44336,stroke:#c62828,color:#fff
检测步骤:
1
Ping测试(ICMP)
# 基本ping测试
ping cdn.example.com
# 指定次数
ping -c 10 cdn.example.com
# 查看丢包率和延迟
ping -c 100 cdn.example.com | tail -2
# 示例输出(正常):
# 10 packets transmitted, 10 received, 0% packet loss
# rtt min/avg/max/mdev = 20.123/25.456/30.789/3.456 ms
# 示例输出(异常):
# 10 packets transmitted, 0 received, 100% packet loss
2
端口连通性测试
# HTTP端口测试(80)
telnet cdn.example.com 80
nc -zv cdn.example.com 80
# HTTPS端口测试(443)
telnet cdn.example.com 443
nc -zv cdn.example.com 443
# 正常输出:
# Connection to cdn.example.com 443 port [tcp/https] succeeded!
# 异常输出:
# telnet: connect to address xxx.xxx.xxx.xxx: Connection refused
# telnet: Unable to connect to remote host
3
Traceroute路由追踪
# 追踪路由路径
traceroute cdn.example.com
mtr cdn.example.com # 持续监控
# 示例输出分析:
# 1 gateway (192.168.1.1) 1.234 ms
# 2 10.0.0.1 (10.0.0.1) 5.678 ms
# 3 * * * # ⚠️ 某跳无响应
# 4 cdn-node.example.com 25.123 ms
路由异常判断:
- 连续多跳 *** 表示防火墙拦截或网络不可达
- 延迟突然大幅增加表示网络拥塞
- 路由路径绕行国外可能被墙
4
MTR综合网络诊断图示
graph LR
A[用户设备] -->|Hop 1
0.5ms| B[本地网关] B -->|Hop 2
5ms| C[运营商接入层] C -->|Hop 3
15ms| D[运营商骨干网] D -->|Hop 4
25ms| E[CDN节点] D -.->|被拦截| F[❌ 防火墙拦截
无响应] E -->|正常| G[✅ 到达CDN
有访问日志] F -->|异常| H[❌ 未到达CDN
无访问日志] style A fill:#2196F3,stroke:#1976D2,color:#fff style E fill:#4caf50,stroke:#388e3c,color:#fff style F fill:#f44336,stroke:#c62828,color:#fff style G fill:#4caf50,stroke:#388e3c,color:#fff style H fill:#f44336,stroke:#c62828,color:#fff
0.5ms| B[本地网关] B -->|Hop 2
5ms| C[运营商接入层] C -->|Hop 3
15ms| D[运营商骨干网] D -->|Hop 4
25ms| E[CDN节点] D -.->|被拦截| F[❌ 防火墙拦截
无响应] E -->|正常| G[✅ 到达CDN
有访问日志] F -->|异常| H[❌ 未到达CDN
无访问日志] style A fill:#2196F3,stroke:#1976D2,color:#fff style E fill:#4caf50,stroke:#388e3c,color:#fff style F fill:#f44336,stroke:#c62828,color:#fff style G fill:#4caf50,stroke:#388e3c,color:#fff style H fill:#f44336,stroke:#c62828,color:#fff
🛠️ 推荐工具
ping
traceroute
mtr
telnet
nc (netcat)
PingPlotter (Windows)
Network Utility (Mac)
🔧 诊断方案3:HTTP请求层分析
📡
HTTP请求完整流程检测
sequenceDiagram
participant App as 📱 App
participant Proxy as 🔄 代理/VPN
participant CDN as 🚀 CDN节点
participant Origin as 🖥️ 源站
App->>App: 1. 构建HTTP请求
Note over App: 检查URL、Header、Method
alt 使用代理
App->>Proxy: 2. 发送请求
alt 代理配置错误
Proxy--xApp: ❌ 连接失败
Note over App,Proxy: 无CDN日志
else 代理正常
Proxy->>CDN: 3. 转发请求
end
else 直连
App->>CDN: 2. 直接发送请求
end
CDN->>CDN: 4. 检查缓存
alt 缓存命中
CDN-->>App: 5. 返回缓存资源
Note over CDN: ✅ 有访问日志
Cache HIT else 缓存未命中 CDN->>Origin: 6. 回源请求 alt 回源成功 Origin-->>CDN: 7. 返回资源 CDN-->>App: 8. 返回资源 Note over CDN: ✅ 有访问日志
Cache MISS else 回源失败 Origin--xCDN: ❌ 404/5xx CDN--xApp: ❌ 错误响应 Note over CDN: ✅ 有错误日志 end end
Cache HIT else 缓存未命中 CDN->>Origin: 6. 回源请求 alt 回源成功 Origin-->>CDN: 7. 返回资源 CDN-->>App: 8. 返回资源 Note over CDN: ✅ 有访问日志
Cache MISS else 回源失败 Origin--xCDN: ❌ 404/5xx CDN--xApp: ❌ 错误响应 Note over CDN: ✅ 有错误日志 end end
检测步骤:
1
cURL详细请求测试
# 基本GET请求
curl -I https://cdn.example.com/static/app.js
# 详细模式(显示完整交互过程)
curl -v https://cdn.example.com/static/app.js
# 超详细模式(显示SSL握手等)
curl -vv https://cdn.example.com/static/app.js
# 指定User-Agent模拟App
curl -H "User-Agent: MyApp/1.0.0 iOS/15.0" \
https://cdn.example.com/static/app.js
# 检查响应头
curl -I https://cdn.example.com/static/app.js | grep -i "x-cache"
# 示例正常输出:
# HTTP/2 200
# x-cache: HIT from cdn-node-1
# x-cache-lookup: HIT from cdn-node-1
# server: Tengine/CDN
# 示例异常输出:
# curl: (6) Could not resolve host: cdn.example.com
# curl: (7) Failed to connect to cdn.example.com port 443
# curl: (35) SSL connect error
2
移动端抓包分析
使用Charles Proxy抓包:
步骤:
- 手机和电脑连接同一WiFi
- 手机设置HTTP代理:电脑IP + Charles端口(8888)
- 安装Charles SSL证书(HTTPS抓包)
- 在Charles中查看请求详情
- ✓ 请求是否真正发出
- ✓ 请求URL是否正确
- ✓ 请求Header是否完整
- ✓ DNS解析到的IP地址
- ✓ 响应状态码和内容
- ✓ SSL证书是否有效
3
请求流程异常分析图
graph TB
A[App构建请求] --> B{URL是否正确?}
B -->|否| E1[❌ 404错误
CDN有日志] B -->|是| C{DNS解析成功?} C -->|否| E2[❌ DNS失败
无CDN日志] C -->|是| D{TCP连接成功?} D -->|否| E3[❌ 网络不通
无CDN日志] D -->|是| F{SSL握手成功?} F -->|否| E4[❌ 证书错误
无CDN日志] F -->|是| G{发送HTTP请求} G --> H{CDN响应?} H -->|200| S1[✅ 正常
有CDN日志] H -->|3xx| S2[⚠️ 重定向
有CDN日志] H -->|4xx| E5[❌ 客户端错误
有CDN日志] H -->|5xx| E6[❌ 服务器错误
有CDN日志] H -->|超时| E7[❌ 请求超时
可能无日志] style A fill:#2196F3,stroke:#1976D2,color:#fff style S1 fill:#4caf50,stroke:#388e3c,color:#fff style S2 fill:#ffc107,stroke:#ffa000,color:#333 style E1 fill:#ff9800,stroke:#f57c00,color:#fff style E2 fill:#f44336,stroke:#c62828,color:#fff style E3 fill:#f44336,stroke:#c62828,color:#fff style E4 fill:#f44336,stroke:#c62828,color:#fff style E5 fill:#ff9800,stroke:#f57c00,color:#fff style E6 fill:#f44336,stroke:#c62828,color:#fff style E7 fill:#f44336,stroke:#c62828,color:#fff
CDN有日志] B -->|是| C{DNS解析成功?} C -->|否| E2[❌ DNS失败
无CDN日志] C -->|是| D{TCP连接成功?} D -->|否| E3[❌ 网络不通
无CDN日志] D -->|是| F{SSL握手成功?} F -->|否| E4[❌ 证书错误
无CDN日志] F -->|是| G{发送HTTP请求} G --> H{CDN响应?} H -->|200| S1[✅ 正常
有CDN日志] H -->|3xx| S2[⚠️ 重定向
有CDN日志] H -->|4xx| E5[❌ 客户端错误
有CDN日志] H -->|5xx| E6[❌ 服务器错误
有CDN日志] H -->|超时| E7[❌ 请求超时
可能无日志] style A fill:#2196F3,stroke:#1976D2,color:#fff style S1 fill:#4caf50,stroke:#388e3c,color:#fff style S2 fill:#ffc107,stroke:#ffa000,color:#333 style E1 fill:#ff9800,stroke:#f57c00,color:#fff style E2 fill:#f44336,stroke:#c62828,color:#fff style E3 fill:#f44336,stroke:#c62828,color:#fff style E4 fill:#f44336,stroke:#c62828,color:#fff style E5 fill:#ff9800,stroke:#f57c00,color:#fff style E6 fill:#f44336,stroke:#c62828,color:#fff style E7 fill:#f44336,stroke:#c62828,color:#fff
4
App代码层检查
添加网络请求监控代码:
// iOS - 监控NSURLSession请求
- (void)URLSession:(NSURLSession *)session
task:(NSURLSessionTask *)task
didCompleteWithError:(NSError *)error {
if (error) {
NSLog(@"❌ 请求失败: %@", error.localizedDescription);
NSLog(@" URL: %@", task.currentRequest.URL);
NSLog(@" 错误码: %ld", (long)error.code);
NSLog(@" 错误域: %@", error.domain);
// 常见错误分析
// NSURLErrorDomain -1003: 无法找到主机(DNS失败)
// NSURLErrorDomain -1004: 无法连接服务器
// NSURLErrorDomain -1200: SSL错误
}
}
// Android - 监控OkHttp请求
client.interceptors().add(chain -> {
Request request = chain.request();
long startTime = System.currentTimeMillis();
try {
Response response = chain.proceed(request);
long duration = System.currentTimeMillis() - startTime;
Log.d("Network", String.format(
"✅ 请求成功: %s | 状态: %d | 耗时: %dms",
request.url(), response.code(), duration
));
return response;
} catch (Exception e) {
Log.e("Network", "❌ 请求失败: " + request.url(), e);
throw e;
}
});
🛠️ 推荐工具
curl
wget
Charles Proxy
Fiddler
Wireshark
Chrome DevTools
Postman
🔧 诊断方案4:CDN配置检查
⚙️
CDN服务配置完整性检查
graph TB
Start[CDN配置检查] --> Check1[检查域名接入状态]
Check1 --> Q1{域名已接入CDN?}
Q1 -->|否| Fix1[❌ 未接入
需要在CDN控制台添加域名] Q1 -->|是| Check2[检查CNAME配置] Check2 --> Q2{CNAME记录正确?} Q2 -->|否| Fix2[❌ CNAME错误
修改DNS记录] Q2 -->|是| Check3[检查回源配置] Check3 --> Q3{回源地址正确?} Q3 -->|否| Fix3[❌ 回源配置错误
无法获取资源] Q3 -->|是| Check4[检查缓存规则] Check4 --> Q4{缓存规则合理?} Q4 -->|否| Fix4[⚠️ 缓存规则问题
影响访问效率] Q4 -->|是| Check5[检查访问控制] Check5 --> Q5{访问控制配置?} Q5 -->|过严| Fix5[⚠️ IP/Referer限制
可能拦截正常请求] Q5 -->|合理| Check6[检查HTTPS配置] Check6 --> Q6{证书有效?} Q6 -->|否| Fix6[❌ 证书过期/错误
HTTPS访问失败] Q6 -->|是| Success[✅ CDN配置正常] style Start fill:#2196F3,stroke:#1976D2,color:#fff style Success fill:#4caf50,stroke:#388e3c,color:#fff style Fix1 fill:#f44336,stroke:#c62828,color:#fff style Fix2 fill:#f44336,stroke:#c62828,color:#fff style Fix3 fill:#f44336,stroke:#c62828,color:#fff style Fix4 fill:#ff9800,stroke:#f57c00,color:#fff style Fix5 fill:#ff9800,stroke:#f57c00,color:#fff style Fix6 fill:#f44336,stroke:#c62828,color:#fff
需要在CDN控制台添加域名] Q1 -->|是| Check2[检查CNAME配置] Check2 --> Q2{CNAME记录正确?} Q2 -->|否| Fix2[❌ CNAME错误
修改DNS记录] Q2 -->|是| Check3[检查回源配置] Check3 --> Q3{回源地址正确?} Q3 -->|否| Fix3[❌ 回源配置错误
无法获取资源] Q3 -->|是| Check4[检查缓存规则] Check4 --> Q4{缓存规则合理?} Q4 -->|否| Fix4[⚠️ 缓存规则问题
影响访问效率] Q4 -->|是| Check5[检查访问控制] Check5 --> Q5{访问控制配置?} Q5 -->|过严| Fix5[⚠️ IP/Referer限制
可能拦截正常请求] Q5 -->|合理| Check6[检查HTTPS配置] Check6 --> Q6{证书有效?} Q6 -->|否| Fix6[❌ 证书过期/错误
HTTPS访问失败] Q6 -->|是| Success[✅ CDN配置正常] style Start fill:#2196F3,stroke:#1976D2,color:#fff style Success fill:#4caf50,stroke:#388e3c,color:#fff style Fix1 fill:#f44336,stroke:#c62828,color:#fff style Fix2 fill:#f44336,stroke:#c62828,color:#fff style Fix3 fill:#f44336,stroke:#c62828,color:#fff style Fix4 fill:#ff9800,stroke:#f57c00,color:#fff style Fix5 fill:#ff9800,stroke:#f57c00,color:#fff style Fix6 fill:#f44336,stroke:#c62828,color:#fff
检查清单:
📋 CDN配置检查清单
- 域名是否已在CDN控制台添加并启用
- DNS的CNAME记录是否指向CDN提供的CNAME域名
- 回源Host配置是否正确
- 回源协议(HTTP/HTTPS)是否匹配源站
- 源站IP/域名是否可访问
- 缓存规则是否覆盖静态资源
- 是否配置了过于严格的访问控制(IP白名单、Referer防盗链等)
- HTTPS证书是否有效且未过期
- CDN节点是否正常(无大面积故障)
- 日志功能是否正常开启
1
验证CNAME配置
# 查询CNAME记录
dig cdn.example.com CNAME +short
nslookup -type=cname cdn.example.com
# 正确输出示例:
# cdn.example.com.cdn.dnsv1.com.
# 错误情况:
# (无输出) # 未配置CNAME
# source.example.com. # 错误地指向源站
2
测试回源配置
# 直接访问源站验证资源存在
curl -I https://origin.example.com/static/app.js
# 通过CDN访问
curl -I https://cdn.example.com/static/app.js
# 对比响应头
# 源站应该返回: 200 OK
# CDN应该返回: 200 OK + X-Cache头
3
检查访问控制影响
# 测试无Referer访问(模拟直接访问)
curl -I https://cdn.example.com/static/app.js
# 测试带Referer访问(模拟从App访问)
curl -I -H "Referer: https://app.example.com" \
https://cdn.example.com/static/app.js
# 如果配置了Referer白名单,第一个请求可能返回403
🛠️ 需要检查的CDN后台位置
域名管理
回源配置
缓存配置
访问控制
HTTPS配置
日志服务
🎯 综合诊断流程总结
graph TB
Start([App无法访问CDN
且无访问日志]) --> Step1[Step 1: 基础信息收集] Step1 --> Info{收集信息} Info --> I1[CDN域名] Info --> I2[资源URL] Info --> I3[App版本] Info --> I4[手机系统/网络环境] Info --> I5[错误现象描述] I1 --> Step2[Step 2: DNS诊断] I2 --> Step2 I3 --> Step2 I4 --> Step2 I5 --> Step2 Step2 --> DNS{DNS解析正常?} DNS -->|否| Solution1[🔧 修复DNS问题
• 更换DNS服务器
• 联系域名服务商
• 检查域名配置] DNS -->|是| Step3[Step 3: 网络连通性诊断] Step3 --> Network{网络可达?} Network -->|否| Solution2[🔧 修复网络问题
• 检查防火墙
• 联系运营商
• 检查CDN节点状态] Network -->|是| Step4[Step 4: HTTP请求诊断] Step4 --> HTTP{请求发送成功?} HTTP -->|否| Solution3[🔧 修复App问题
• 检查代码逻辑
• 检查证书配置
• 检查代理设置] HTTP -->|是| Step5[Step 5: CDN配置诊断] Step5 --> CDN{CDN配置正确?} CDN -->|否| Solution4[🔧 修复CDN配置
• 添加域名接入
• 配置CNAME
• 修正回源设置
• 调整访问控制] CDN -->|是| Step6[Step 6: 日志系统诊断] Step6 --> Log{日志系统正常?} Log -->|否| Solution5[🔧 联系CDN服务商
• 检查日志服务状态
• 检查日志存储配置] Log -->|是| DeepCheck[深度排查
抓包分析] Solution1 --> Verify[验证修复效果] Solution2 --> Verify Solution3 --> Verify Solution4 --> Verify Solution5 --> Verify DeepCheck --> Verify Verify --> Final{问题解决?} Final -->|是| Success([✅ 问题解决]) Final -->|否| Escalate([升级到专家团队]) style Start fill:#f44336,stroke:#c62828,color:#fff style Success fill:#4caf50,stroke:#388e3c,color:#fff style Solution1 fill:#2196F3,stroke:#1976D2,color:#fff style Solution2 fill:#2196F3,stroke:#1976D2,color:#fff style Solution3 fill:#2196F3,stroke:#1976D2,color:#fff style Solution4 fill:#2196F3,stroke:#1976D2,color:#fff style Solution5 fill:#2196F3,stroke:#1976D2,color:#fff
且无访问日志]) --> Step1[Step 1: 基础信息收集] Step1 --> Info{收集信息} Info --> I1[CDN域名] Info --> I2[资源URL] Info --> I3[App版本] Info --> I4[手机系统/网络环境] Info --> I5[错误现象描述] I1 --> Step2[Step 2: DNS诊断] I2 --> Step2 I3 --> Step2 I4 --> Step2 I5 --> Step2 Step2 --> DNS{DNS解析正常?} DNS -->|否| Solution1[🔧 修复DNS问题
• 更换DNS服务器
• 联系域名服务商
• 检查域名配置] DNS -->|是| Step3[Step 3: 网络连通性诊断] Step3 --> Network{网络可达?} Network -->|否| Solution2[🔧 修复网络问题
• 检查防火墙
• 联系运营商
• 检查CDN节点状态] Network -->|是| Step4[Step 4: HTTP请求诊断] Step4 --> HTTP{请求发送成功?} HTTP -->|否| Solution3[🔧 修复App问题
• 检查代码逻辑
• 检查证书配置
• 检查代理设置] HTTP -->|是| Step5[Step 5: CDN配置诊断] Step5 --> CDN{CDN配置正确?} CDN -->|否| Solution4[🔧 修复CDN配置
• 添加域名接入
• 配置CNAME
• 修正回源设置
• 调整访问控制] CDN -->|是| Step6[Step 6: 日志系统诊断] Step6 --> Log{日志系统正常?} Log -->|否| Solution5[🔧 联系CDN服务商
• 检查日志服务状态
• 检查日志存储配置] Log -->|是| DeepCheck[深度排查
抓包分析] Solution1 --> Verify[验证修复效果] Solution2 --> Verify Solution3 --> Verify Solution4 --> Verify Solution5 --> Verify DeepCheck --> Verify Verify --> Final{问题解决?} Final -->|是| Success([✅ 问题解决]) Final -->|否| Escalate([升级到专家团队]) style Start fill:#f44336,stroke:#c62828,color:#fff style Success fill:#4caf50,stroke:#388e3c,color:#fff style Solution1 fill:#2196F3,stroke:#1976D2,color:#fff style Solution2 fill:#2196F3,stroke:#1976D2,color:#fff style Solution3 fill:#2196F3,stroke:#1976D2,color:#fff style Solution4 fill:#2196F3,stroke:#1976D2,color:#fff style Solution5 fill:#2196F3,stroke:#1976D2,color:#fff
⚡ 快速诊断命令集
🚀
一键诊断脚本(复制粘贴执行)
#!/bin/bash
# CDN访问问题快速诊断脚本
# 使用方法: ./cdn_diagnosis.sh cdn.example.com /static/app.js
CDN_DOMAIN=$1
RESOURCE_PATH=$2
FULL_URL="https://${CDN_DOMAIN}${RESOURCE_PATH}"
echo "========================================="
echo "CDN访问诊断开始"
echo "目标: ${FULL_URL}"
echo "时间: $(date)"
echo "========================================="
# 1. DNS解析测试
echo -e "\n[1] DNS解析测试"
echo "系统默认DNS:"
nslookup ${CDN_DOMAIN} | grep -A 2 "Name:"
echo -e "\nGoogle DNS (8.8.8.8):"
nslookup ${CDN_DOMAIN} 8.8.8.8 | grep -A 2 "Name:"
# 2. CNAME检查
echo -e "\n[2] CNAME配置检查"
dig ${CDN_DOMAIN} CNAME +short
# 3. Ping测试
echo -e "\n[3] Ping连通性测试"
ping -c 5 ${CDN_DOMAIN}
# 4. 端口检测
echo -e "\n[4] 端口连通性测试"
nc -zv ${CDN_DOMAIN} 80 2>&1
nc -zv ${CDN_DOMAIN} 443 2>&1
# 5. HTTP请求测试
echo -e "\n[5] HTTP请求测试"
curl -I -s ${FULL_URL} | head -20
# 6. 详细请求信息
echo -e "\n[6] 详细请求分析"
curl -v ${FULL_URL} 2>&1 | grep -E "^\*|^>|^<"
# 7. 路由追踪
echo -e "\n[7] 路由追踪"
traceroute -m 15 ${CDN_DOMAIN}
# 8. SSL证书检查(HTTPS)
echo -e "\n[8] SSL证书检查"
echo | openssl s_client -connect ${CDN_DOMAIN}:443 -servername ${CDN_DOMAIN} 2>/dev/null | \
openssl x509 -noout -dates -subject
echo -e "\n========================================="
echo "诊断完成"
echo "========================================="
🎯 使用方法:
# 保存脚本
chmod +x cdn_diagnosis.sh
# 执行诊断
./cdn_diagnosis.sh cdn.example.com /static/app.js
# 保存结果到文件
./cdn_diagnosis.sh cdn.example.com /static/app.js > diagnosis_result.txt
📊 常见问题速查表
| 现象 | 是否有CDN日志 | 可能原因 | 诊断命令 | 解决方案 |
|---|---|---|---|---|
| DNS解析失败 | 否 | DNS服务器问题、域名未配置 | nslookup cdn.example.com |
检查域名配置、更换DNS |
| 解析到错误IP | 否 | DNS劫持、CNAME配置错误 | dig cdn.example.com +trace |
修正CNAME、使用HTTPDNS |
| Ping不通 | 否 | 网络不可达、防火墙拦截 | mtr cdn.example.com |
检查防火墙、联系运营商 |
| 端口无法连接 | 否 | CDN节点故障、端口被封 | telnet cdn.example.com 443 |
联系CDN服务商 |
| SSL握手失败 | 否 | 证书过期、证书配置错误 | openssl s_client -connect ... |
更新证书 |
| HTTP 403 | 是 | 访问控制限制(IP/Referer) | curl -I -H "Referer: ..." url |
调整访问控制规则 |
| HTTP 404 | 是 | 资源不存在、URL错误 | curl -I url |
检查资源路径、检查回源 |
| HTTP 5xx | 是 | 源站故障、回源配置错误 | curl -I 源站URL |
检查源站、修正回源配置 |
| 请求超时 | 不一定 | 网络延迟、CDN节点繁忙 | curl -w "time_total: %{time_total}" url |
优化网络、切换CDN节点 |
| App代码未发起请求 | 否 | 代码逻辑错误、条件判断错误 | App日志、Charles抓包 | 修复App代码 |
💡 预防性最佳实践
实施全链路监控
- App端:SDK监控DNS解析、网络请求全过程
- CDN端:配置实时访问监控和告警
- 源站端:监控源站健康状态
- 建立端到端的可观测性体系
使用HTTPDNS
- 避免运营商LocalDNS劫持
- 更精准的CDN节点调度
- 降低DNS解析失败率
- 推荐:阿里云HTTPDNS、腾讯云HTTPDNS
配置多CDN容灾
- 主备CDN服务商切换机制
- 检测到主CDN异常自动切换
- 提高服务可用性
- 降低单一CDN故障影响
完善日志体系
- App端详细记录网络请求日志
- 包含DNS解析结果、请求耗时等
- 失败请求上报到监控平台
- 建立用户反馈渠道和日志上传机制
定期进行压测
- 定期验证CDN性能和可用性
- 模拟不同网络环境测试
- 验证故障切换机制
- 发现潜在问题并提前优化
优化CDN配置
- 合理配置缓存策略
- 避免过度严格的访问控制
- 配置合理的超时和重试策略
- 定期审查和优化配置
捐赠本站(Donate)

如您感觉文章有用,可扫码捐赠本站!(If the article useful, you can scan the QR code to donate))