You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何加速Ansible中uri模块的loop循环任务?

加速Ansible循环中Web请求的实用方案

首先得说清楚为什么你之前的异步方案反而变慢了——你用poll:0让任务后台跑,然后逐个循环等待每个任务完成,这种方式根本没发挥并行的优势,反而增加了Ansible管理异步任务的额外开销(比如每个任务的状态查询、jid记录),串行等待的逻辑甚至比直接串行执行请求更耗时。

下面给你几个实际可行的优化方向,按效果优先级排序:

1. 优先尝试批量请求(效果最显著)

如果Nagios XI的API支持批量创建服务(大部分新版本都支持),直接把所有要提交的服务数据打包成一个请求发送,这能把N次请求压缩成1次,速度提升是数量级的。

先把所有挂载点的服务参数预整理好,再调用批量API:

- name: 整理批量提交的Nagios服务数据
  set_fact:
    nagios_batch_services: "{{ nagios_batch_services | default([]) + [service_data] }}"
  loop: "{{ ansible_mounts }}"
  vars:
    warning: "{{ fs[ansible_fqdn][item.mount]['warning'] if ((fs is defined) and ansible_fqdn in fs and item.mount in fs[ansible_fqdn] and 'warning' in fs[ansible_fqdn][item.mount]) else fs['defaults']['warning']}}"
    critical: "{{ fs[ansible_fqdn][item.mount]['critical'] if ((fs is defined) and ansible_fqdn in fs and item.mount in fs[ansible_fqdn] and 'critical' in fs[ansible_fqdn][item.mount]) else fs['defaults']['critical']}}"
    service_data:
      host_name: "{{ ansible_fqdn }}"
      service_description: "FS {{ item.mount }}"
      register: 1
      check_command: "check_nrpe!check_fs_single!\'-w {{ warning }} -c {{ critical }} -p {{ item.mount }} -e -l -u {{ 'MB' if item.size_total is defined and item.size_total < 5368709120 else 'GB' }}\'-!!!!!!"
      initial_state: "{{ fs[ansible_fqdn][item.mount]['initial_state'] if ((fs is defined) and ansible_fqdn in fs and item.mount in fs[ansible_fqdn] and 'initial_state' in fs[ansible_fqdn][item.mount]) else service[env]['initial_state']}}"
      max_check_attempts: "{{ fs[ansible_fqdn][item.mount]['max_check_attempts'] if ((fs is defined) and ansible_fqdn in fs and item.mount in fs[ansible_fqdn] and 'max_check_attempts' in fs[ansible_fqdn][item.mount]) else service[env]['max_check_attempts']}}"
      # 把原任务中所有body参数都复制到这里
  when: item.fstype == 'xfs' or item.fstype == 'ext4'

- name: 批量推送服务到Nagios
  delegate_to: localhost
  uri:
    url: "https://nagios/nagiosxi/api/v1/config/services?apikey={{ nagios_apikey }}"
    method: POST
    body_format: json
    body: "{{ nagios_batch_services }}"
  register: batch_upload
  failed_when: 'batch_upload.json is defined and batch_upload.json.error is defined'

注意:不同版本的Nagios XI批量API端点可能有差异,你可以查一下官方文档确认具体的批量提交格式。

2. 正确使用异步并行请求

如果批量API不可用,那调整异步的使用方式,让所有请求同时发起,然后一次性等待所有任务完成,而不是逐个等待:

- name: 异步推送服务到Nagios
  delegate_to: localhost
  uri:
    url: "https://nagios/nagiosxi/api/v1/config/service?apikey={{ nagios_apikey }}&config_name={{ ansible_fqdn }}-fs-{{ item.mount | replace('/','-') }}"
    method: POST
    body_format: form-urlencoded
    body:
      # 保持原body参数不变
  loop: "{{ ansible_mounts }}"
  vars:
    # 原vars不变
  register: upload_tasks
  failed_when: 'upload.json is defined and upload.json.error is defined'
  when: item.fstype == 'xfs' or item.fstype == 'ext4'
  async: 60
  poll: 0

- name: 等待所有异步推送任务完成
  delegate_to: localhost
  async_status:
    jid: "{{ item.ansible_job_id }}"
  register: upload_results
  retries: 20
  delay: 1
  until: upload_results.finished
  loop: "{{ upload_tasks.results }}"
  # 可以加throttle控制并行等待的数量,避免同时发起太多状态查询请求
  # throttle: 5

这样所有uri请求会同时后台运行,Ansible会并行等待它们完成,能有效利用网络并行性。不过要注意Nagios API的并发承受能力,如果并发太高导致API报错,可以调整throttle参数限制并行数。

3. 优化请求本身的耗时

  • 关闭SSL证书验证(如果环境允许):加validate_certs: no,减少证书校验的时间开销。
  • 启用HTTP/2:如果Nagios服务器支持,加http1: false,HTTP/2的多路复用能提升并发请求的效率。
  • 预计算变量,减少循环内的模板渲染:你原任务中每个循环都要做大量的多层条件判断,这些判断每次循环都会重新计算,很耗CPU。可以提前用set_fact把所有参数预计算好,循环时直接引用:
- name: 预计算所有挂载点的服务参数
  set_fact:
    precomputed_mounts: "{{ precomputed_mounts | default([]) + [mount_params] }}"
  loop: "{{ ansible_mounts }}"
  vars:
    mount_params:
      mount: "{{ item.mount }}"
      fstype: "{{ item.fstype }}"
      warning: "{{ fs[ansible_fqdn][item.mount]['warning'] if ((fs is defined) and ansible_fqdn in fs and item.mount in fs[ansible_fqdn] and 'warning' in fs[ansible_fqdn][item.mount]) else fs['defaults']['warning']}}"
      critical: "{{ fs[ansible_fqdn][item.mount]['critical'] if ((fs is defined) and ansible_fqdn in fs and item.mount in fs[ansible_fqdn] and 'critical' in fs[ansible_fqdn][item.mount]) else fs['defaults']['critical']}}"
      initial_state: "{{ fs[ansible_fqdn][item.mount]['initial_state'] if ((fs is defined) and ansible_fqdn in fs and item.mount in fs[ansible_fqdn] and 'initial_state' in fs[ansible_fqdn][item.mount]) else service[env]['initial_state']}}"
      # 把所有需要的参数都预计算好
  when: item.fstype == 'xfs' or item.fstype == 'ext4'

# 然后在uri任务中直接引用precomputed_mounts的参数

4. 调整Ansible的forks参数

如果你的Playbook是针对多主机的,调整ansible.cfg中的forks值(默认是5),增加并行处理的主机数量。但如果是单主机内的循环,这个参数只影响异步任务的并行数,配合上面的异步方案使用效果更好。

最后再强调一下:批量请求是最优解,能从根本上减少请求次数;如果只能用并行异步,一定要确保Nagios API能承受并发压力,避免适得其反。

内容的提问来源于stack exchange,提问作者Chris

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 08:20:30