关于Hadoop集群352台机器间SSH双向延迟捕获及全量互访检测方案的技术问询
嘿,针对你352台机器的Hadoop集群的两个SSH需求,我整理了实用的实现方案,一起来看看:
需求1:统计master1到所有节点的SSH命令执行耗时
你现有的遍历脚本已经能批量执行SSH命令,只需要增加时间统计逻辑就行,这里提供两种简单的实现方式:
方式一:用系统自带的time命令(快速实现)
time命令可以直接统计命令的执行耗时,把它套在SSH命令外层就能拿到结果,还能把输出写入日志方便后续分析:
all_ips=/tmp/ip.txt # 定义日志文件路径,用来保存每个节点的耗时数据 output_log=/tmp/master1_ssh_latency.log > $output_log # 先清空日志文件,避免旧数据干扰 for i in $(awk '{print $1}' $all_ips); do echo "=== 检测节点 $i ===" >> $output_log # 使用time -p输出更易解析的格式(real用户感知时间就是我们要的SSH耗时) time -p ssh $i "pwd" >> $output_log 2>&1 echo "---------------------" >> $output_log done
日志里的real行就是从执行SSH到命令完成的总耗时,比如real 0.234代表耗时0.234秒。
方式二:自定义时间戳(更灵活可控)
如果需要更精细的时间计算(比如保留更多小数位),可以用date命令记录开始和结束时间,手动计算差值:
all_ips=/tmp/ip.txt output_log=/tmp/master1_ssh_latency.log > $output_log for i in $(awk '{print $1}' $all_ips); do # 记录开始时间(精确到纳秒) start_time=$(date +%s.%N) # 执行SSH命令,这里把输出丢到/dev/null只统计耗时,你也可以保留输出 ssh $i "pwd" > /dev/null 2>&1 # 记录结束时间 end_time=$(date +%s.%N) # 用bc计算时间差,awk格式化保留3位小数 latency=$(echo "$end_time - $start_time" | bc -l | awk '{printf "%.3f", $0}') echo "节点 $i 的SSH执行耗时: ${latency}s" >> $output_log done
这种方式可以自由控制输出格式,还能结合SSH的退出码判断连接是否成功。
需求2:集群内每台机器到其他所有机器的SSH连接检测
352台机器两两检测的话,总共有352*351=123552次连接,手动跑肯定不现实,这里提供两种自动化方案:
方案一:用Ansible批量执行(推荐,适合大规模集群)
Ansible是自动化运维工具,能轻松批量管理集群节点,前提是你已经配置好Ansible的节点清单和SSH免密登录:
- 先准备集群IP列表文件
/tmp/ip.txt,和你的现有文件一致。 - 编写Ansible Playbook(
ssh_connectivity_check.yml):
- name: 集群内SSH全连接检测 hosts: all gather_facts: no tasks: # 第一步:把IP列表分发到所有节点 - name: 同步集群IP列表 copy: src: /tmp/ip.txt dest: /tmp/ip.txt mode: '0644' # 第二步:每个节点执行到其他所有节点的SSH检测 - name: 执行本地到全节点的SSH检测 shell: | output_log=/tmp/ssh_self_to_all.log > $output_log # 获取当前节点的IP local_ip=$(hostname -i | awk '{print $1}') for ip in $(awk '{print $1}' /tmp/ip.txt); do # 跳过自己到自己的检测 if [ "$ip" != "$local_ip" ]; then start_time=$(date +%s.%N) # 设置5秒连接超时,避免长时间等待无响应节点 ssh -o ConnectTimeout=5 $ip "echo connected" > /dev/null 2>&1 exit_code=$? end_time=$(date +%s.%N) latency=$(echo "$end_time - $start_time" | bc -l | awk '{printf "%.3f", $0}') # 根据退出码记录连接状态 if [ $exit_code -eq 0 ]; then echo "$local_ip -> $ip: SUCCESS, 耗时=${latency}s" >> $output_log else echo "$local_ip -> $ip: FAILED, 耗时=${latency}s" >> $output_log fi fi done args: executable: /bin/bash # 第三步:把所有节点的检测结果收集到master1 - name: 收集检测日志到master1 fetch: src: /tmp/ssh_self_to_all.log dest: /tmp/ssh_cluster_check/{{ ansible_host }}_log.txt flat: yes
- 执行Playbook(假设你的Ansible清单文件是
inventory.ini):
ansible-playbook -i inventory.ini ssh_connectivity_check.yml
执行完成后,所有节点的检测日志会被收集到/tmp/ssh_cluster_check/目录下,每个节点对应一个日志文件。
方案二:纯Shell脚本+并行执行(无需额外工具)
如果不想用Ansible,可以用Shell脚本分发+parallel工具实现批量执行:
- 先编写检测脚本
/tmp/ssh_check.sh:
all_ips=/tmp/ip.txt output_log=/tmp/ssh_self_to_all.log > $output_log local_ip=$(hostname -i | awk '{print $1}') for ip in $(awk '{print $1}' $all_ips); do if [ "$ip" != "$local_ip" ]; then start_time=$(date +%s.%N) ssh -o ConnectTimeout=5 $ip "echo ok" > /dev/null 2>&1 exit_code=$? end_time=$(date +%s.%N) latency=$(echo "$end_time - $start_time" | bc -l | awk '{printf "%.3f", $0}') if [ $exit_code -eq 0 ]; then echo "$local_ip -> $ip: SUCCESS, latency=${latency}s" >> $output_log else echo "$local_ip -> $ip: FAILED, latency=${latency}s" >> $output_log fi fi done
- 在master1上分发脚本到所有节点:
all_ips=/tmp/ip.txt for i in $(awk '{print $1}' $all_ips); do scp /tmp/ssh_check.sh $i:/tmp/ done
- 用
parallel并行执行脚本(需要先在master1安装parallel,比如yum install parallel或apt install parallel):
# -j 10 代表同时执行10个任务,根据集群网络情况调整 parallel -j 10 ssh {} "chmod +x /tmp/ssh_check.sh && /tmp/ssh_check.sh" ::: $(awk '{print $1}' $all_ips)
- 收集所有节点的结果:
mkdir -p /tmp/ssh_cluster_check for i in $(awk '{print $1}' $all_ips); do scp $i:/tmp/ssh_self_to_all.log /tmp/ssh_cluster_check/${i}_log.txt done
关键注意事项
- 必须先配置全节点SSH免密登录:不管用哪种方案,批量执行都需要节点之间能无密码SSH登录,否则会卡在输入密码环节。
- 控制并发数:大规模集群执行时,不要一次性跑太多并发任务,避免网络拥堵影响集群正常业务。
- 设置超时时间:用
ssh -o ConnectTimeout=5设置5秒超时,避免单个无响应节点拖慢整个检测流程。
内容的提问来源于stack exchange,提问作者jessica
相关产品推荐
相关产品推荐

