🔍 日志管理与监控:做网站的"侦探",洞察一切
🔍 日志管理与监控:做网站的"侦探",洞察一切
网站出问题了?慢了?挂了?别慌,日志会告诉你真相!
今天我们来学习如何成为一名优秀的"网站侦探" 🕵️♂️
🎯 为什么需要日志和监控?
想象一下:
text
1 2 3 4 5 6 7 8 9 | 没有日志 = 盲人摸象 - 不知道发生了什么 - 出问题无从查起 - 用户投诉才发现问题 有日志 = 开启上帝视角 👁️ - 知道发生了什么 - 提前发现问题 - 主动优化性能 |
📊 日志的层次
应用层日志
text
1 2 3 4 | Flask/Gunicorn 日志 ├─ 访问日志:谁在什么时候访问了什么 ├─ 错误日志:出了什么问题 └─ 性能日志:响应时间有多长 |
系统层日志
text
1 2 3 4 | Systemd 日志 ├─ 服务启动/停止 ├─ 进程崩溃记录 └─ 资源使用情况 |
网络层日志
text
1 2 3 4 | Nginx 日志 ├─ 请求详情 ├─ 响应状态 └─ 转发记录 |
🗂️ 第一步:配置访问日志
Nginx 访问日志
/etc/nginx/nginx.conf
nginx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | http { # 自定义日志格式 log_format main '$remote_addr - $remote_user [$time_local] ' '"$request" $status $body_bytes_sent ' '"$http_referer" "$http_user_agent" ' '$request_time $upstream_response_time ' '$upstream_addr $upstream_status'; # 访问日志 access_log /var/log/nginx/access.log main; # 错误日志 error_log /var/log/nginx/error.log warn; } |
日志字段说明:
| 字段 | 说明 | 示例 |
|---|---|---|
$remote_addr |
客户端 IP | 192.168.1.100 |
$request |
请求行 | GET /api/posts HTTP/1.1 |
$status |
状态码 | 200 |
$request_time |
总请求时间 | 0.523 |
$upstream_response_time |
后端响应时间 | 0.500 |
Gunicorn 访问日志
gunicorn_config.py
python
1 2 3 4 5 6 7 8 9 10 11 12 13 | import multiprocessing # 日志配置 loglevel = "info" # 访问日志 accesslog = "logs/gunicorn_access.log" # 错误日志 errorlog = "logs/gunicorn_error.log" # 自定义日志格式 access_log_format = '%(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s" %(D)s' |
字段说明:
%(h)s:客户端 IP%(r)s:请求行%(s)s:状态码%(D)s:请求时间(微秒)
Flask 应用日志
app.py
python
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | import logging from logging.handlers import RotatingFileHandler # 配置日志 if not os.path.exists('logs'): os.mkdir('logs') # 文件日志 file_handler = RotatingFileHandler( 'logs/app.log', maxBytes=10240000, # 10MB backupCount=10 ) file_handler.setFormatter(logging.Formatter( '%(asctime)s %(levelname)s: %(message)s' )) file_handler.setLevel(logging.INFO) # 控制台日志 stream_handler = logging.StreamHandler() stream_handler.setLevel(logging.INFO) # 添加到 Flask app.logger.addHandler(file_handler) app.logger.addHandler(stream_handler) app.logger.setLevel(logging.INFO) # 使用日志 app.logger.info('应用启动') app.logger.error('数据库连接失败') |
📈 第二步:日志分析
实时查看
bash
1 2 3 4 5 6 7 8 | # 查看最新日志 tail -f /var/log/nginx/access.log # 查看最后 50 行 tail -n 50 /var/log/nginx/access.log # 查看并高亮错误 tail -f /var/log/nginx/error.log | grep --color=auto "error" |
统计访问量
bash
1 2 3 4 5 6 7 8 9 10 | # 统计总访问量 wc -l /var/log/nginx/access.log # 按小时统计 awk '{print $4}' /var/log/nginx/access.log | \ cut -d: -f2 | sort | uniq -c # 统计独立 IP awk '{print $1}' /var/log/nginx/access.log | \ sort | uniq | wc -l |
统计状态码
bash
1 2 3 4 5 6 7 8 9 | # 状态码分布 awk '{print $9}' /var/log/nginx/access.log | \ sort | uniq -c | sort -rn # 输出示例: # 15000 200 # 500 404 # 100 500 # 50 301 |
找出慢请求
bash
1 2 3 4 5 6 | # 响应时间 > 1 秒的请求 awk -F'"' '$(NF-1) > 1.0 {print $0}' /var/log/nginx/access.log # 按 IP 统计慢请求 awk -F'"' '$(NF-1) > 1.0 {print $1}' /var/log/nginx/access.log | \ sort | uniq -c | sort -rn | head -10 |
找出热门 URL
bash
1 2 3 4 5 6 7 8 | # 访问最多的页面 awk '{print $7}' /var/log/nginx/access.log | \ sort | uniq -c | sort -rn | head -20 # 输出示例: # 5000 /api/posts # 3000 / # 2000 /about |
🔥 第三步:错误日志分析
分析 Nginx 错误
bash
1 2 3 4 5 6 | # 查看最近的错误 tail -100 /var/log/nginx/error.log # 统计错误类型 awk '{print $2}' /var/log/nginx/error.log | \ sort | uniq -c | sort -rn |
常见错误:
| 错误 | 原因 | 解决方案 |
|---|---|---|
upstream timed out |
后端响应慢 | 增加 proxy_read_timeout |
connect() failed |
后端服务挂了 | 重启后端服务 |
directory index of |
找不到首页 | 检查 index 配置 |
分析 Gunicorn 错误
bash
1 2 3 4 5 6 | # 查看 Gunicorn 错误日志 tail -f logs/gunicorn_error.log # 统计错误类型 grep ERROR logs/gunicorn_error.log | \ awk '{print $3}' | sort | uniq -c |
🔄 第四步:日志轮转
为什么需要轮转?
text
1 2 3 4 5 6 7 8 9 | 不轮转 = 💣 炸弹 - 日志文件无限增长 - 磁盘被占满 - 系统崩溃 轮转 = ✅ 安全 - 定期归档旧日志 - 压缩节省空间 - 自动删除过期日志 |
Logrotate 配置
/etc/logrotate.d/flask-blog
bash
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | /var/www/blog/logs/*.log { daily # 每天轮转 missingok # 文件不存在不报错 rotate 14 # 保留 14 天 compress # 压缩旧日志 delaycompress # 延迟一天压缩 notifempty # 空文件不轮转 create 0644 www-data www-data sharedscripts postrotate # 重启应用(如果需要) systemctl reload flask-blog > /dev/null 2>&1 || true endscript } |
Nginx 日志轮转
/etc/logrotate.d/nginx
bash
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | /var/log/nginx/*.log { daily missingok rotate 14 compress delaycompress notifempty create 0640 nginx nginx sharedscripts prerotate if [ -d /etc/logrotate.d/httpd-prerotate ]; then \ run-parts /etc/logrotate.d/httpd-prerotate; \ fi endscript postrotate [ -f /var/run/nginx.pid ] && kill -USR1 `cat /var/run/nginx.pid` endscript } |
测试 Logrotate
bash
1 2 3 4 5 | # 调试模式(不实际执行) sudo logrotate -d /etc/logrotate.d/flask-blog # 强制执行 sudo logrotate -f /etc/logrotate.d/flask-blog |
📊 第五步:监控指标
系统资源监控
bash
1 2 3 4 5 6 7 8 9 10 11 | # CPU 和内存使用 htop # 磁盘使用 df -h # 进程监控 ps aux | grep gunicorn # 网络连接 netstat -anp | grep :5000 |
应用性能监控
bash
1 2 3 4 5 6 7 8 9 10 | # 统计平均响应时间 awk -F'"' '{print $(NF-1)}' /var/log/nginx/access.log | \ awk '{sum+=$1; count++} END {print sum/count}' # 统计 QPS(每秒请求数) awk '{print $4}' /var/log/nginx/access.log | \ cut -d: -f2 | sort | uniq -c # 统计并发数 netstat -an | grep :5000 | grep ESTABLISHED | wc -l |
自定义监控脚本
monitor.sh
bash
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | #!/bin/bash # 颜色定义 GREEN='\033[0;32m' RED='\033[0;31m' NC='\033[0m' # 检查服务状态 check_service() { if systemctl is-active --quiet "$1"; then echo -e "${GREEN}✓ $1 运行中${NC}" else echo -e "${RED}✗ $1 已停止${NC}" fi } # 检查端口 check_port() { if netstat -tuln | grep -q ":$1 "; then echo -e "${GREEN}✓ 端口 $1 监听中${NC}" else echo -e "${RED}✗ 端口 $1 未监听${NC}" fi } # 检查磁盘空间 check_disk() { USAGE=$(df / | awk 'NR==2 {print $5}' | tr -d '%') if [ $USAGE -gt 80 ]; then echo -e "${RED}⚠ 磁盘使用: ${USAGE}%${NC}" else echo -e "${GREEN}✓ 磁盘使用: ${USAGE}%${NC}" fi } # 主函数 main() { echo "=== 系统监控 $(date) ===" echo "" echo "服务状态:" check_service "flask-blog" check_service "nginx" check_service "frpc" echo "" echo "端口检查:" check_port 5000 check_port 80 echo "" check_disk echo "" } main |
🚨 第六步:告警系统
简单告警脚本
alert.sh
bash
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | #!/bin/bash # 阈值 CPU_THRESHOLD=80 DISK_THRESHOLD=80 MEMORY_THRESHOLD=80 # 检查 CPU CPU_USAGE=$(top -bn1 | grep "Cpu(s)" | awk '{print $2}' | cut -d'%' -f1) if (( $(echo "$CPU_USAGE > $CPU_THRESHOLD" | bc -l) )); then echo "⚠️ CPU 使用率过高: ${CPU_USAGE}%" | mail -s "告警" admin@example.com fi # 检查磁盘 DISK_USAGE=$(df / | awk 'NR==2 {print $5}' | tr -d '%') if [ $DISK_USAGE -gt $DISK_THRESHOLD ]; then echo "⚠️ 磁盘使用率过高: ${DISK_USAGE}%" | mail -s "告警" admin@example.com fi |
系统级监控工具
1. Monit
bash
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | # 安装 sudo apt install monit -y # 配置 sudo tee /etc/monit/monitrc.d/flask-blog > /dev/null << 'EOF' check process flask-blog matching gunicorn start program = "/bin/systemctl start flask-blog" stop program = "/bin/systemctl stop flask-blog" if failed port 5000 protocol http then restart if 5 restarts within 5 cycles then timeout EOF # 启动 sudo systemctl enable monit sudo systemctl start monit |
2. Prometheus + Grafana
架构:
text
1 | 应用 → Exporter → Prometheus → Grafana |
安装 Prometheus:
bash
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | # 安装 sudo apt install prometheus -y # 配置目标 sudo tee /etc/prometheus/prometheus.yml > /dev/null << 'EOF' global: scrape_interval: 15s scrape_configs: - job_name: 'node' static_configs: - targets: ['localhost:9100'] EOF # 启动 sudo systemctl enable prometheus sudo systemctl start prometheus |
📱 第七步:可视化监控
Grafana Dashboard
bash
1 2 3 4 5 6 7 8 9 10 | # 安装 Grafana sudo apt install grafana -y # 启动 sudo systemctl enable grafana-server sudo systemctl start grafana-server # 访问 http://localhost:3000 # 默认用户名/密码:admin/admin |
常用指标面板:
- QPS(每秒请求数)
- 响应时间
- 错误率
- CPU 使用率
- 内存使用率
- 磁盘使用率
- 网络流量
🔍 第八步:实战案例
场景:网站突然变慢
步骤 1:检查系统资源
bash
1 2 | htop
# 发现:CPU 100%,内存正常
|
步骤 2:查看日志
bash
1 2 | tail -f /var/log/nginx/access.log # 发现:大量请求到同一个 URL |
步骤 3:分析请求
bash
1 2 | awk '{print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -5 # 发现:/api/heavy 被频繁访问 |
步骤 4:定位问题
bash
1 2 3 | # 查看 Gunicorn 日志 tail -f logs/gunicorn_error.log # 发现:数据库查询很慢 |
解决方案:
python
1 2 3 4 5 | # 添加缓存 @lru_cache(maxsize=128) def heavy_computation(): # ... 耗时操作 pass |
📋 监控检查清单
基础监控
- [ ] 访问日志正常记录
- [ ] 错误日志正常记录
- [ ] 日志轮转已配置
- [ ] 磁盘空间监控
应用监控
- [ ] 服务状态监控
- [ ] 响应时间监控
- [ ] 错误率监控
- [ ] 并发数监控
告警配置
- [ ] 服务停止告警
- [ ] 磁盘满告警
- [ ] 高负载告警
- [ ] 异常错误告警
🎉 总结
日志和监控的重要性:
- 发现问题 → 从用户抱怨到主动发现
- 定位问题 → 快速找到根本原因
- 预防问题 → 提前发现趋势
- 优化性能 → 数据驱动优化
记住:
"没有监控的系统就像盲人开夜车,迟早要出事!" 🚗💥
🔗 相关工具
- 日志管理:Logstash, Fluentd, Filebeat
- 监控系统:Prometheus, Zabbix, Nagios
- 可视化:Grafana, Kibana
- APM:New Relic, Datadog, Sentry
下一篇:自动化备份策略,别让你的数据丢了!💾
0 人点赞
评论 (0)
暂无评论,快来抢沙发吧~
发表评论