HDFS均衡操作完整指南

目录 概述 什么时候需要HDFS均衡 HDFS均衡原理 均衡参数详解 操作步骤 监控和管理 故障排除 最佳实践 性能优化建议 概述 HDFS均衡器(Balancer)是Hadoop分布式文件系统中的一个重要工具,用于重新分布数据块,确保集群中所有DataNode的存储使用率保持相对均衡。当集群中添加新节点或删除节点后,数据分布可能会变得不均匀,这时就需要使用均衡器来重新分布数据。 什么时候需要HDFS均衡 1. 集群扩容后 新增DataNode节点:新节点加入集群后,存储使用率为0%,而原有节点可能已经接近满载 添加存储设备:为现有DataNode添加新的磁盘后 2. 集群缩容后 移除DataNode节点:节点下线前需要将其数据迁移到其他节点 磁盘故障:某个磁盘故障后,需要重新分布数据 3. 数据倾斜 节点间使用率差异过大:标准差超过10-15% 热点数据:某些节点存储了过多的热点数据 写入模式不均:应用写入模式导致的数据分布不均 4. 性能优化 负载均衡:提高集群整体I/O性能 故障恢复:确保数据副本分布合理 判断标准 # 计算节点使用率标准差 # 标准差 > 10%:建议进行均衡 # 标准差 > 20%:强烈建议立即均衡 # 标准差 < 5%:认为已均衡 HDFS均衡原理 1. 均衡策略 DataNode策略:基于整个DataNode的使用率进行均衡 BlockPool策略:基于命名空间的使用率进行均衡(适用于Federation) 2. 均衡算法 识别源节点:使用率高于平均值的节点 识别目标节点:使用率低于平均值的节点 选择数据块:从源节点选择合适的数据块 数据迁移:通过三阶段复制进行数据迁移 验证完整性:确保数据迁移成功 3. 数据迁移过程 源节点 → 中间节点 → 目标节点 避免直接复制,减少网络压力 通过中间节点进行数据转发 确保数据完整性和一致性 均衡参数详解 1. 基本参数 -threshold <threshold> 用途:设置均衡阈值,单位为百分比 默认值:10% 说明:只有当节点使用率差异超过此阈值时才开始均衡 推荐值: 生产环境:5-10% 测试环境:10-15% 紧急情况:20% # 示例 hdfs balancer -threshold 5 # 5%阈值,更严格的均衡 hdfs balancer -threshold 15 # 15%阈值,更宽松的均衡 -policy <policy> 用途:指定均衡策略 可选值: datanode:基于DataNode使用率(默认) blockpool:基于BlockPool使用率 推荐:一般使用datanode策略 # 示例 hdfs balancer -policy datanode # DataNode策略 hdfs balancer -policy blockpool # BlockPool策略 2. 节点选择参数 -exclude [-f <hosts-file> | <comma-separated list of hosts>] 用途:排除指定的DataNode节点 使用场景: 节点维护期间 性能较差的节点 网络不稳定的节点 # 排除单个节点 hdfs balancer -exclude 192.168.1.100 # 排除多个节点 hdfs balancer -exclude 192.168.1.100,192.168.1.101 # 从文件读取排除列表 hdfs balancer -exclude -f /path/to/exclude_hosts.txt -include [-f <hosts-file> | <comma-separated list of hosts>] 用途:只对指定的DataNode节点进行均衡 使用场景: 只均衡特定节点 测试环境 部分节点维护 # 只均衡指定节点 hdfs balancer -include 192.168.1.100,192.168.1.101 -source [-f <hosts-file> | <comma-separated list of hosts>] 用途:指定源节点(数据来源) 使用场景: 特定节点需要减少负载 节点即将下线 # 指定源节点 hdfs balancer -source 192.168.1.100,192.168.1.101 3. 性能控制参数 -idleiterations <idleiterations> 用途:设置连续空闲迭代次数 默认值:5 说明:连续N次迭代没有数据移动时退出 推荐值: 生产环境:3-5 测试环境:1-2 # 示例 hdfs balancer -idleiterations 3 # 连续3次无移动则退出 -runDuringUpgrade 用途:在HDFS升级期间运行均衡器 默认值:false 说明:通常不建议在升级期间运行 4. 高级参数 -blockpools <comma-separated list of blockpool ids> 用途:指定要均衡的BlockPool ID 适用场景:Federation环境 # 示例 hdfs balancer -blockpools BP-REPLACE_WITH_NEW_PASSWORD789-192.168.1.100-REPLACE_WITH_NEW_PASSWORD7890123 操作步骤 1. 环境检查 检查集群状态 # 检查HDFS状态 hdfs dfsadmin -report # 检查NameNode状态 hdfs haadmin -getServiceState nn1 # 检查DataNode状态 hdfs dfsadmin -printTopology 检查磁盘空间 # 检查各节点磁盘使用情况 for node in $(hdfs dfsadmin -printTopology | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+'); do echo "=== $node ===" ssh $node "df -h" done 检查网络状况 # 检查节点间网络延迟 hdfs dfsadmin -printTopology | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+' | while read node; do echo "Testing $node..." ping -c 3 $node done 2. 均衡前准备 备份重要配置 # 备份HDFS配置 cp -r $HADOOP_CONF_DIR /backup/hdfs_conf_$(date +%Y%m%d) # 记录当前状态 hdfs dfsadmin -report > /backup/hdfs_report_$(date +%Y%m%d_%H%M%S).txt 设置均衡参数 # 设置均衡带宽(可选) # 在hdfs-site.xml中添加: # <property> # <name>dfs.datanode.balance.bandwidthPerSec</name> # <value>10485760</value> <!-- 10MB/s --> # </property> 3. 执行均衡 基本均衡命令 # 标准均衡命令 nohup hdfs balancer -threshold 10 -policy datanode > /tmp/hdfs_balancer.log 2>&1 & # 获取进程ID BALANCER_PID=$! # 记录PID echo $BALANCER_PID > /tmp/hdfs_balancer.pid 高级均衡命令 # 排除特定节点的均衡 nohup hdfs balancer -threshold 5 -policy datanode \ -exclude 192.168.1.100,192.168.1.101 \ -idleiterations 3 > /tmp/hdfs_balancer.log 2>&1 & # 只对特定节点进行均衡 nohup hdfs balancer -threshold 10 -policy datanode \ -include 192.168.1.102,192.168.1.103 > /tmp/hdfs_balancer.log 2>&1 & 4. 监控均衡进度 实时监控脚本 #!/usr/bin/env python3 # monitor_hdfs_balancer.py import subprocess import time import re from datetime import datetime def get_hdfs_report(): try: result = subprocess.run(['hdfs', 'dfsadmin', '-report'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, check=True) return result.stdout except subprocess.CalledProcessError as e: print("获取HDFS报告失败: {}".format(e)) return None def parse_datanode_info(report): datanodes = [] lines = report.split('\n') current_node = {} in_datanode_section = False for line in lines: line = line.strip() if line.startswith('Name:'): if current_node: datanodes.append(current_node) current_node = {'name': line.split(':', 1)[1].strip()} in_datanode_section = True elif in_datanode_section and line.startswith('DFS Used%:'): current_node['used_percent'] = float(line.split(':')[1].strip().replace('%', '')) elif in_datanode_section and line.startswith('DFS Remaining%:'): current_node['remaining_percent'] = float(line.split(':')[1].strip().replace('%', '')) if current_node: datanodes.append(current_node) return datanodes def calculate_balance_metrics(datanodes): if not datanodes: return None used_percents = [node.get('used_percent', 0) for node in datanodes] avg_used_percent = sum(used_percents) / len(used_percents) # 计算标准差 variance = sum((x - avg_used_percent) ** 2 for x in used_percents) / len(used_percents) std_dev = variance ** 0.5 # 找出最高和最低使用率节点 max_used_node = max(datanodes, key=lambda x: x.get('used_percent', 0)) min_used_node = min(datanodes, key=lambda x: x.get('used_percent', 0)) return { 'avg_used_percent': avg_used_percent, 'std_dev': std_dev, 'max_used_node': max_used_node, 'min_used_node': min_used_node, 'datanodes': datanodes } def monitor_balancer(): print("HDFS均衡监控开始...") print("=" * 80) start_time = datetime.now() try: while True: current_time = datetime.now() elapsed = current_time - start_time report = get_hdfs_report() if not report: print("[{}] 无法获取HDFS报告".format(current_time.strftime('%H:%M:%S'))) time.sleep(30) continue datanodes = parse_datanode_info(report) if not datanodes: print("[{}] 无法解析datanode信息".format(current_time.strftime('%H:%M:%S'))) time.sleep(30) continue metrics = calculate_balance_metrics(datanodes) if not metrics: continue # 显示当前状态 print("\n[{}] 运行时间: {}".format(current_time.strftime('%H:%M:%S'), elapsed)) print("平均使用率: {:.2f}%".format(metrics['avg_used_percent'])) print("均衡度(标准差): {:.2f}%".format(metrics['std_dev'])) print("最高使用率节点: {} ({:.2f}%)".format( metrics['max_used_node'].get('name', 'N/A'), metrics['max_used_node'].get('used_percent', 0))) print("最低使用率节点: {} ({:.2f}%)".format( metrics['min_used_node'].get('name', 'N/A'), metrics['min_used_node'].get('used_percent', 0))) print("\n各节点使用率:") for node in sorted(metrics['datanodes'], key=lambda x: x.get('used_percent', 0), reverse=True): name = node.get('name', 'N/A') used_pct = node.get('used_percent', 0) remaining_pct = node.get('remaining_percent', 0) print(" {}: {:.2f}% (剩余: {:.2f}%)".format(name, used_pct, remaining_pct)) # 检查是否达到均衡 if metrics['std_dev'] < 5.0: print("\n🎉 均衡完成! 标准差: {:.2f}%".format(metrics['std_dev'])) break print("=" * 80) time.sleep(60) except KeyboardInterrupt: print("\n\n监控已停止") except Exception as e: print("\n监控出错: {}".format(e)) if __name__ == "__main__": monitor_balancer() 手动检查命令 # 检查均衡进程状态 ps aux | grep balancer # 查看均衡日志 tail -f /tmp/hdfs_balancer.log # 检查集群状态 hdfs dfsadmin -report | grep -A 20 "Live datanodes" # 计算当前均衡度 python3 -c " import subprocess import re result = subprocess.run(['hdfs', 'dfsadmin', '-report'], stdout=subprocess.PIPE, universal_newlines=True) report = result.stdout used_percents = [] for line in report.split('\n'): if 'DFS Used%:' in line: percent = float(re.search(r'(\d+\.?\d*)%', line).group(1)) used_percents.append(percent) if used_percents: avg = sum(used_percents) / len(used_percents) variance = sum((x - avg) ** 2 for x in used_percents) / len(used_percents) std_dev = variance ** 0.5 print(f'平均使用率: {avg:.2f}%') print(f'标准差: {std_dev:.2f}%') print(f'最高使用率: {max(used_percents):.2f}%') print(f'最低使用率: {min(used_percents):.2f}%') " 监控和管理 1. 均衡状态监控 实时监控 # 启动监控脚本 python3 /tmp/monitor_hdfs_balancer.py # 后台运行监控 nohup python3 /tmp/monitor_hdfs_balancer.py > /tmp/balancer_monitor.log 2>&1 & 定期检查 # 创建定期检查脚本 cat > /tmp/check_balance.sh << 'EOF' #!/bin/bash LOG_FILE="/tmp/balance_check.log" DATE=$(date '+%Y-%m-%d %H:%M:%S') echo "[$DATE] 开始检查HDFS均衡状态" >> $LOG_FILE # 检查均衡进程 if pgrep -f "hdfs.*balancer" > /dev/null; then echo "[$DATE] 均衡进程正在运行" >> $LOG_FILE else echo "[$DATE] 警告: 均衡进程未运行" >> $LOG_FILE fi # 检查集群状态 hdfs dfsadmin -report | grep -A 20 "Live datanodes" >> $LOG_FILE echo "[$DATE] 检查完成" >> $LOG_FILE echo "----------------------------------------" >> $LOG_FILE EOF chmod +x /tmp/check_balance.sh # 添加到crontab,每10分钟检查一次 echo "*/10 * * * * /tmp/check_balance.sh" | crontab - 2. 均衡进程管理 启动均衡 # 基本启动 nohup hdfs balancer -threshold 10 > /tmp/balancer.log 2>&1 & # 高级启动 nohup hdfs balancer -threshold 5 -policy datanode \ -exclude 192.168.1.100 -idleiterations 3 \ > /tmp/balancer.log 2>&1 & 停止均衡 # 查找均衡进程 BALANCER_PID=$(pgrep -f "hdfs.*balancer") # 停止均衡进程 if [ ! -z "$BALANCER_PID" ]; then kill $BALANCER_PID echo "均衡进程 $BALANCER_PID 已停止" else echo "未找到运行中的均衡进程" fi 重启均衡 # 停止现有均衡 pkill -f "hdfs.*balancer" # 等待进程完全停止 sleep 5 # 重新启动均衡 nohup hdfs balancer -threshold 10 > /tmp/balancer.log 2>&1 & 3. 日志分析 均衡日志分析 # 统计移动的数据块数量 grep "Successfully moved" /tmp/hdfs_balancer.log | wc -l # 统计移动的数据量 grep "Successfully moved" /tmp/hdfs_balancer.log | \ awk '{sum += $NF} END {print "总移动数据量: " sum/1024/1024/1024 " GB"}' # 分析移动速度 grep "Successfully moved" /tmp/hdfs_balancer.log | \ awk '{print $1, $2, $NF}' | \ tail -100 | \ awk 'BEGIN{prev_time=""} { if(prev_time != "") { split($1" "$2, time_arr, ":") current_sec = time_arr[1]*3600 + time_arr[2]*60 + time_arr[3] split(prev_time, prev_arr, ":") prev_sec = prev_arr[1]*3600 + prev_arr[2]*60 + prev_arr[3] if(current_sec > prev_sec) { speed = $3 / (current_sec - prev_sec) print "移动速度: " speed/1024/1024 " MB/s" } } prev_time = $1" "$2 }' 故障排除 1. 常见问题 均衡进程无法启动 症状:执行均衡命令后立即退出 可能原因: ...

2024-05-01 · 10 分钟 · 2069 字 · heyaohua

Redis Docker开发环境配置指南

Redis Docker开发环境配置指南 本文档详细介绍如何使用Docker搭建Redis开发环境,包括环境配置、启动方式、维护方法等内容。 目录结构 Redis_Docker/ ├── .env # 环境变量配置文件 ├── README.md # 项目说明文档 ├── config/ # 配置文件目录 │ └── redis.conf # Redis配置文件 ├── data/ # 数据存储目录 └── logs/ # 日志文件目录 配置文件说明 1. docker-compose.yml version: '3.8' services: redis: container_name: redis-server image: redis:7.2 ports: - "${REDIS_PORT}:6379" volumes: - ./data:/data - ./logs:/var/log/redis - ./config/redis.conf:/usr/local/etc/redis/redis.conf command: redis-server /usr/local/etc/redis/redis.conf environment: - TZ=Asia/Shanghai networks: - redis-network healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 10s timeout: 5s retries: 5 start_period: 5s networks: redis-network: driver: bridge 2. .env 环境变量配置 # Redis 配置环境变量 REDIS_PORT=6379 # Redis端口映射 REDIS_PASSWORD=your_password # Redis访问密码 3. redis.conf 主要配置 # 网络设置 bind 0.0.0.0 port 6379 protected-mode yes tcp-keepalive 300 # 基本设置 databases 16 loglevel notice logfile "/var/log/redis/redis.log" # 内存设置 maxmemory 256mb maxmemory-policy allkeys-lru maxmemory-samples 5 # 持久化设置 save 900 1 # 900秒内至少1个键被修改 save 300 10 # 300秒内至少10个键被修改 save 60 10000 # 60秒内至少10000个键被修改 # AOF设置 appendonly yes appendfilename "appendonly.aof" appendfsync everysec 使用说明 1. 启动服务 # 启动服务 docker-compose up -d # 查看服务状态 docker-compose ps # 查看日志 docker-compose logs redis 2. 连接Redis # 使用容器内的redis-cli docker-compose exec redis redis-cli -a your_password # 使用主机的redis-cli(如果已安装) redis-cli -h localhost -p 6379 -a your_password # 测试连接 redis-cli -h localhost -p 6379 -a your_password ping 3. 停止服务 # 停止服务 docker-compose down 数据持久化 Redis配置了双重持久化机制: ...

2024-03-19 · 2 分钟 · 317 字 · heyaohua

PostgreSQL Docker开发环境配置指南

PostgreSQL Docker开发环境配置指南 本文档详细介绍如何使用Docker搭建PostgreSQL开发环境,包括环境配置、启动方式、维护方法等内容。 目录结构 PgSQL_Docker/ ├── .env # 环境变量配置文件 ├── README.md # 项目说明文档 ├── config/ # 配置文件目录 │ ├── pg_hba.conf # 访问控制配置 │ └── postgresql.conf # PostgreSQL主配置文件 ├── data/ # 数据存储目录 └── logs/ # 日志文件目录 配置文件说明 1. docker-compose.yml version: '3.8' services: postgres: container_name: postgres-server image: postgres:15 environment: - POSTGRES_DB=${POSTGRES_DB} - POSTGRES_USER=${POSTGRES_USER} - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} ports: - "${POSTGRES_PORT}:5432" volumes: - ./data:/var/lib/postgresql/data - ./logs:/var/log/postgresql - ./config/postgresql.conf:/etc/postgresql/postgresql.conf - ./config/pg_hba.conf:/etc/postgresql/pg_hba.conf command: postgres -c 'config_file=/etc/postgresql/postgresql.conf' networks: - postgres-network healthcheck: test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"] interval: 10s timeout: 5s retries: 5 start_period: 10s networks: postgres-network: driver: bridge 2. .env 环境变量配置 # PostgreSQL 配置环境变量 POSTGRES_DB=test_db # 数据库名称 POSTGRES_USER=data # 默认超级用户 POSTGRES_PASSWORD=your_password # 用户密码 POSTGRES_PORT=5432 # 端口映射 3. postgresql.conf 主要配置 # 连接设置 listen_addresses = '*' port = 5432 max_connections = 100 # 内存设置 shared_buffers = 128MB work_mem = 4MB maintenance_work_mem = 64MB effective_cache_size = 512MB # 写入设置 wal_level = replica max_wal_size = 1GB min_wal_size = 80MB # 日志设置 log_destination = 'stderr' logging_collector = on log_directory = '/var/log/postgresql' log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log' log_rotation_age = 1d log_rotation_size = 10MB # 区域设置 datestyle = 'iso, mdy' timezone = 'UTC' lc_messages = 'en_US.utf8' 4. pg_hba.conf 访问控制配置 # TYPE DATABASE USER ADDRESS METHOD local all all trust host all all 127.0.0.1/32 scram-sha-256 host all all ::1/128 scram-sha-256 host all all 0.0.0.0/0 scram-sha-256 使用说明 1. 启动服务 # 启动服务 docker-compose up -d # 查看服务状态 docker-compose ps # 查看日志 docker-compose logs postgres 2. 连接数据库 # 使用超级用户连接 docker-compose exec postgres psql -U data -d test_db # 查看用户列表和权限 \du # 查看数据库列表 \l # 退出psql \q 3. 停止服务 # 停止服务 docker-compose down 用户和权限管理 PostgreSQL使用角色(Role)概念来管理用户权限。在我们的配置中: ...

2024-03-19 · 2 分钟 · 380 字 · heyaohua

MySQL Docker开发环境配置指南

如何使用Docker启动MySQL开发环境 目录结构 MySQL_Docker/ ├── docker-compose.yml # Docker Compose 配置文件 ├── .env # 环境变量配置 ├── config/ │ └── my.cnf # MySQL 配置文件 ├── data/ # MySQL 数据目录 (挂载) └── logs/ # MySQL 日志目录 (挂载) 配置文件说明 1. docker-compose.yml 配置要点 version: '3.8' services: mysql: image: mysql:8.0 container_name: mysql-server restart: unless-stopped environment: MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:-root123} MYSQL_DATABASE: ${MYSQL_DATABASE:-testdb} MYSQL_USER: ${MYSQL_USER:-testuser} MYSQL_PASSWORD: ${MYSQL_PASSWORD:-testpass} ports: - "${MYSQL_PORT:-3306}:3306" volumes: - ./data:/var/lib/mysql - ./logs:/var/log/mysql - ./config/my.cnf:/etc/mysql/conf.d/my.cnf 重要配置说明: restart: unless-stopped - 容器异常退出时自动重启 environment - 环境变量配置,支持从.env文件读取 volumes - 数据持久化配置,确保数据安全 ports - 端口映射,允许外部访问 2. MySQL配置文件 (my.cnf) 要点 [mysqld] # 基本设置 port = 3306 bind-address = 0.0.0.0 default-storage-engine = InnoDB # 字符集设置(重要) character-set-server = utf8mb4 collation-server = utf8mb4_unicode_ci # 连接设置 max_connections = 200 max_connect_errors = 10 # 缓冲区设置 innodb_buffer_pool_size = 256M innodb_log_file_size = 64M innodb_log_buffer_size = 16M # 日志设置 log-error = /var/log/mysql/error.log slow_query_log = 1 slow_query_log_file = /var/log/mysql/slow.log long_query_time = 2 配置注意事项: ...

2024-03-19 · 2 分钟 · 258 字 · heyaohua

抖音长截图服务使用说明

本文介绍基于 Playwright 封装的抖音长截图服务,涵盖能力范围、接口设计、使用范例以及性能调优建议,便于快速集成到现有业务系统中。 服务概述 核心功能已经封装在 app/services/playwright_service.py 中,经过大量测试验证,推荐使用的默认参数如下: 滚动距离:1000 px 底部裁剪:300 px 平均截图数量:4–5 张 平均文件大小:2–4 MB GitHub 仓库:https://github.com/heyaohua/douyin_screenshot_service 核心能力 移动端模拟:完整模拟 iPhone 设备视口与 UA 智能滚动:自动识别内部滚动容器并控制节奏 懒加载处理:触发页面动态内容渲染 图像拼接:裁剪重叠区域,生成无缝长图 错误处理:封装异常重试、日志与超时机制 主要接口 take_long_screenshot(url, output_dir="screenshots") url:待截图抖音页面 URL output_dir:输出目录(默认 screenshots) 返回值示例: { "success": True, "output_path": "screenshots/douyin_long_screenshot_20250916_135333.png", "screenshot_count": 4, "total_height": 9228, "file_size": 2764800, "original_url": "https://v.douyin.com/...", "current_url": "https://haohuo.jinritemai.com/...", "title": "页面标题" } HTTP API 设计 长截图接口 请求:POST /douyin/long-screenshot 请求体: { "url": "https://v.douyin.com/Zdo3P7Zv51o/" } 响应: { "message": "长截图完成", "data": { "success": true, "output_path": "screenshots/douyin_long_screenshot_20250916_135333.png", "screenshot_count": 4, "total_height": 9228, "file_size": 2764800 } } 测试接口 请求:POST /douyin/test-long-screenshot 说明:使用预设 URL 触发一次完整流程,便于巡检。 使用示例 服务内调用 from app.services.playwright_service import playwright_service async def example(): await playwright_service.initialize() result = await playwright_service.take_long_screenshot( url="https://v.douyin.com/Zdo3P7Zv51o/", output_dir="screenshots" ) if result["success"]: print(f"截图完成: {result['output_path']}") print(f"截图数量: {result['screenshot_count']}") print(f"总高度: {result['total_height']}px") await playwright_service.close() HTTP API 调用 curl -X POST "http://localhost:8000/douyin/long-screenshot" \ -H "Content-Type: application/json" \ -d '{"url": "https://v.douyin.com/Zdo3P7Zv51o/"}' curl -X POST "http://localhost:8000/douyin/test-long-screenshot" 本地测试脚本 cd tests python test_service.py 性能指标 滚动距离 截图数量 平均文件大小 效率评估 1000 px 4–5 张 2.6–3.7 MB ⭐⭐⭐⭐⭐ 推荐参数 900 px 6 张 4.6 MB ⭐⭐⭐⭐ 800 px 6 张 4.3 MB ⭐⭐⭐ 700 px 7 张 5.0 MB ⭐⭐ 600 px 8 张 5.7 MB ⭐ 目录结构 app/services/ ├── playwright_service.py # 主服务入口 │ ├── take_long_screenshot # 长截图方法 │ └── _stitch_screenshots # 图片拼接方法 app/api/ ├── douyin.py # HTTP API 定义 │ ├── /long-screenshot # 长截图接口 │ └── /test-long-screenshot # 测试接口 tests/ ├── test_service.py # 集成测试脚本 └── simple_douyin_test.py # 快速验证脚本 运维与实践建议 生命周期管理:调用前需执行 initialize(),结束后务必调用 close() 释放浏览器资源。 目录权限:确保输出目录具备写权限,并定期清理历史截图。 错误兜底:检查返回的 success 字段并结合日志定位问题。 并发控制:视负载设置队列或限流,避免同时创建大量浏览器实例。 监控告警:建议将成功率、耗时、文件大小等指标纳入监控系统。 日志样例 2025-09-16 13:53:33,832 - INFO - 拼接图片尺寸: 1170 x 9228 2025-09-16 13:53:35,160 - INFO - ✅ 成功: True 2025-09-16 13:53:35,160 - INFO - 📊 截图数量: 4 2025-09-16 13:53:35,160 - INFO - 💾 文件大小: 2.64MB 成功案例 URL:https://v.douyin.com/Zdo3P7Zv51o/ 截图数量:4 张 总高度:9228 px 文件大小:2.64 MB 处理时长:约 22 秒 成功率:100% 如需深入定制或扩展能力,请参考仓库中的完整代码与测试用例。

2024-01-15 · 2 分钟 · 280 字 · heyaohua

GitHub Actions 自动部署自检清单

本文用于验证博客的自动化部署链路是否正常运行,并记录一次完整的流水线健康检查结果,便于后续排查或重复执行。 验证目标 工作流 Deploy Blog to ECS and Netlify 能够被 main 分支推送事件正确触发 构建节点成功安装依赖、拉取子模块并生成静态页面 部署阶段能通过 SSH 连接到 ECS,并执行 make publish 与静态资源同步 构建产物最终落地到 /data/Htdocs/heyaohua/blog,前端可访问最新页面 本次检查结果 检查项 结果 说明 GitHub Actions 触发 ✅ main 分支推送后,工作流成功启动 依赖安装与构建 ✅ pip 依赖安装完成,pelican content -s publishconf.py 运行正常 ECS 连接与部署 ✅ appleboy/ssh-action 执行脚本,产物同步至目标目录 页面可见性 ✅ 部署完成后可在博客前台访问本文 执行时间 构建触发时间:2024-01-15 16:00 (UTC+08) 整体耗时:约 3 分钟 后续建议 每次更新部署流程或依赖时,使用此清单快速复测关键节点 结合工作流日志与 ECS 服务器日志,保留 30 天内的关键记录,方便回溯 若未来仅需 ECS 部署,可在工作流中移除 Netlify 步骤,缩短执行时间 若读者能够看到这篇文章,即表明当前自动部署链路运行良好。如发现异常,请根据表格逐项排查。

2024-01-15 · 1 分钟 · 68 字 · heyaohua

数学公式示例

本文示范如何在 Pelican 博客中优雅呈现常见数学公式,帮助撰写技术或科研类文章时保持专业排版。示例基于 LaTeX 语法,并依赖 render_math 插件完成渲染。 行内公式 当公式只需要嵌入在段落中时,可使用单个美元符号包裹表达式,例如 $E = mc^2$。这是著名的质能方程,适合在正文中快速引用。 块级公式 对于需要突出显示的公式,可使用双美元符号放在独立段落中: 一元二次方程求根 $$x = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a}$$ 欧拉恒等式 $$e^{i\pi} + 1 = 0$$ 高斯积分 $$\int_{-\infty}^{\infty} e^{-x^2} , dx = \sqrt{\pi}$$ 矩阵乘法 线性代数场景中,矩阵语法有助于展示多维运算: $$ \begin{pmatrix} a & b c & d \end{pmatrix} \begin{pmatrix} x y \end{pmatrix} \begin{pmatrix} ax + by cx + dy \end{pmatrix} $$ 求和公式 常见求和表达式也能通过 LaTeX 清晰呈现: $$\sum_{i=1}^{n} i = \frac{n(n+1)}{2}$$ 提示:撰写公式类文章时,务必确认 pelicanconf.py 中已启用 render_math 插件,并保持 LaTeX 语法正确,以确保静态页面渲染正常。 ...

2024-01-15 · 1 分钟 · 74 字 · heyaohua

Python开发小技巧分享

日常开发中,掌握一些高频技巧能够明显提升代码质量与效率。本文整理了五个常用的小窍门,并配以示例代码,便于在项目中直接应用。 1. 善用列表推导式 列表推导式可以将循环与条件判断浓缩到一行,既简洁又易读: # 传统写法 squares = [] for x in range(10): squares.append(x**2) # 列表推导式 squares = [x**2 for x in range(10)] # 搭配条件过滤 even_squares = [x**2 for x in range(10) if x % 2 == 0] 2. 使用 dict.get 提升容错性 通过 dict.get 读取字典时,可定义默认值,避免 KeyError 并简化分支逻辑: # 可能抛出 KeyError user_name = user_dict['name'] # 更稳健的写法 user_name = user_dict.get('name', 'Unknown') 3. 搭配 enumerate 获取索引 enumerate 能在遍历序列时同时获得索引和值,避免手动维护计数器: fruits = ['apple', 'banana', 'orange'] for index, fruit in enumerate(fruits, start=1): print(f"{index}. {fruit}") 4. 用 zip 打包多组数据 当需要并行遍历多个可迭代对象时,zip 能有效避免索引操作: ...

2024-01-15 · 1 分钟 · 131 字 · heyaohua

欢迎来到我的博客

很高兴在这里与大家见面。这是我基于 Pelican 静态站点生成器搭建的个人技术博客,未来将持续更新开发经验、工程实践与学习笔记,记录我在技术道路上的探索与思考。 博客定位 分享 Python、数据工程、云原生等方向的技术文章 记录项目复盘与实战案例,整理可复用的解决方案 输出读书笔记、课程总结与工具心得 偶尔发布职业发展与个人效率提升的感悟 技术栈概览 Pelican:静态站点生成器,负责内容构建与部署 Markdown:文章撰写格式,方便版本管理与协作 GitHub:代码与内容仓库,配合 CI/CD 完成持续部署 ECS:线上运行环境,托管网站静态资源 内容规划 技术专栏:包含源码解析、性能优化、系统设计等专题 工程实践:记录在企业项目中的落地经验与踩坑总结 学习札记:对前沿技术和优秀论文的阅读体会 工具指南:分享常用开发工具、自动化脚本与效率技巧 联系方式 如有合作、讨论或建议,欢迎通过以下方式联系我: GitHub:https://github.com/heyaohua 邮箱:[email protected] 感谢你的关注,期待在这里与更多技术同好交流与成长。

2024-01-15 · 1 分钟 · 26 字 · heyaohua