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

使用async仍存在Ansible多主机任务调用延迟,如何优化?

如何减少Ansible中带with_items的异步REST API调用延迟?

我来帮你分析问题根源,以及对应的解决办法:

首先看你的场景:你用Ansible的uri模块配合async/poll批量调用多节点的REST API,但日志里每个任务项之间有2-3秒的延迟,和预期的无延迟调用不符。

先贴出你的任务代码:

- name: Perform operation on Multiple Nodes
  uri:
    url: "http://{{item.ipAddress}}:{{item.port}}/api/internal/operations"
    method: POST
    body: "{{jobData}}"
    headers:
      Accept: "******/*******.{{resource}}.{{resourceVersion}}+json"
    status_code: 200
    body_format: json
  when: (item.ipAddress is defined) and (item.port is defined)
  with_items: '{{nodeData}}'
  async: '{{connectionTimeout | int}}'
  poll: 1
  register: instances
  ignore_errors: True

以及显示延迟的日志片段:

2018-05-28 *11:26:51* ,530 p=7744 u=ops | TASK [Perform operation on Multiple Nodes] *************************************
2018-05-28 *11:26:53* ,871 p=7744 u=ops | ok: [localhost] => (item={u'a': u'host0', u'ipAddress':', u'port': u''})
2018-05-28 *11:26:56* ,095 p=7744 u=ops | ok: [localhost] => (item={u'a': u'host1', u'ipAddress': u'', u'': u''})
2018-05-28 *11:26:58* ,324 p=7744 u=ops | ok: [localhost] => (item={u'a': u'host2', u'ipAddress': u'', u'port': u''})

问题根源

你可能误以为async会让with_items的任务并行执行,但实际上默认情况下,with_items会串行处理每个任务项,哪怕用了async。Ansible会先启动第一个异步任务,等它完成第一次poll(也就是你设置的poll:1的1秒等待),再启动第二个任务,以此类推——这就是每个调用间出现2-3秒延迟的核心原因。

解决办法

1. 推荐方案:使用async_batch(Ansible 2.10+)

如果你用的是Ansible 2.10或更高版本,直接用新增的async_batch参数就能实现批量并行启动异步任务,无需拆分任务:

- name: Perform operation on Multiple Nodes
  uri:
    url: "http://{{item.ipAddress}}:{{item.port}}/api/internal/operations"
    method: POST
    body: "{{jobData}}"
    headers:
      Accept: "******/*******.{{resource}}.{{resourceVersion}}+json"
    status_code: 200
    body_format: json
  when: (item.ipAddress is defined) and (item.port is defined)
  with_items: '{{nodeData}}'
  async: '{{connectionTimeout | int}}'
  poll: 1
  async_batch: 5  # 一次性启动5个异步任务,可根据你的节点数量调整
  register: instances
  ignore_errors: True

这个参数会让Ansible同时启动指定数量的异步任务,彻底消除串行带来的延迟。

2. 兼容旧版Ansible:拆分任务为「启动+等待」两步

如果你的Ansible版本低于2.10,可以把任务拆成两步:先批量启动所有异步任务(不等待),再统一检查任务状态:

第一步:批量启动所有异步任务(并行)

- name: Start operation on all nodes
  uri:
    url: "http://{{item.ipAddress}}:{{item.port}}/api/internal/operations"
    method: POST
    body: "{{jobData}}"
    headers:
      Accept: "******/*******.{{resource}}.{{resourceVersion}}+json"
    status_code: 200
    body_format: json
  when: (item.ipAddress is defined) and (item.port is defined)
  with_items: '{{nodeData}}'
  async: '{{connectionTimeout | int}}'
  poll: 0  # 立即返回,不等待任务执行,直接启动所有任务
  register: async_jobs
  ignore_errors: True

第二步:统一等待所有任务完成

- name: Wait for all operations to finish
  async_status:
    jid: "{{ item.ansible_job_id }}"
  register: async_results
  until: async_results.finished
  retries: "{{ connectionTimeout | int // 1 }}"  # 根据超时时间设置重试次数
  delay: 1
  with_items: "{{ async_jobs.results }}"
  when: item.ansible_job_id is defined

这种方式下,第一步会瞬间启动所有异步任务(没有串行间隔),第二步统一轮询所有任务的状态,完美解决延迟问题。

3. 额外优化:调整Ansible forks数量

别忘了确保Ansible的forks参数(默认是5)足够大,能支撑你需要并行的任务数。可以在ansible.cfg里配置:

[defaults]
forks = 10  # 数值根据你的节点数量和服务器资源调整

或者运行playbook时临时指定:

ansible-playbook your_playbook.yml --forks 10

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:53:27