前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >13-异步与并发

13-异步与并发

原创
作者头像
小朋友呢
修改2020-01-14 17:51:43
5500
修改2020-01-14 17:51:43
举报

异步与并发

fork

尝试

先看一段剧本,要在12台主机进行执行,它的执行顺序是怎样的?

是一台主机执行完一个剧本后,再换下一台主机接着执行,还是多个主机同时执行完剧本中的一个任务后,再接着往下执行?

代码语言:txt
复制
- hosts: all
  gather_facts: no
  tasks:
  - shell: sleep 3

  - debug:
     msg: "lalala"

实验看一下结果

代码语言:txt
复制
[ansible@workstation ~]$ time ansible-playbook forck1.yml
#1.首先是所有主机都执行了剧本中的command任务
TASK [command] 
changed: [serverb]
changed: [serverc]
changed: [servera]
changed: [serverd]

#2.执行完上面一个任务后,它们继续执行下一个debug任务
TASK [debug] 
ok: [serverd] => {
    "msg": "lalala"
}
ok: [servera] => {
    "msg": "lalala"
}
ok: [serverc] => {
    "msg": "lalala"
}
ok: [serverb] => {
    "msg": "lalala"
}

#3.执行时间
real	0m4.699s
user	0m0.853s
sys	    0m0.430s

发现

  • 5台主机,每台主机sleep3秒,如果是一台一台执行,那么它会执行大约15秒;
  • 现在却是4.699秒。说明它是5个主机同时执行一个任务的。
  • 在ansible命令行中有一个-f 选项forck->指定并发数,在ansible.cfg配置文件中也有一个forks选项,默认就是5

再次实验

现在指定3个主机同时执行看下结果

代码语言:txt
复制
time ansible-playbook forck1.yml  -f 3
……
real	0m9.359s
user	0m1.246s
sys	0m0.697s

3台主机一起执行,第一批3台主机执行5秒,第二排2台主机执行5秒,时间±10秒

结论

serial

需求

先让servera,serverb执行完整个剧本,然后再让serverc,serverd执行,怎么做呢?

实验

可以使用serial来控制

代码语言:txt
复制
[ansible@workstation ~]$ cat serial.yml 
- hosts: all
  serial: 2
  tasks:
  - debug: 
     msg: 
     - "1.install httpd"
     - "2.config httpd"
     - "3.start http server"

总结

serial是串行,针对的是play,fock是并行针对的是task

async

async:

代码语言:txt
复制
**触发ansible并行运作任务,而async的值是ansible等待运行这个任务的最大超时值(如果执行超时任务会强制中断导致失败)。**

poll:

代码语言:txt
复制
**ansible检查这个任务是否完成的频率,0就是不检查直接成功。**

注意,async和poll是要一起用的!!

代码语言:txt
复制
[ansible@workstation ~]$ cat fork2.yml 
- hosts: servera
  gather_facts: no
  tasks:
  - shell: sleep 4
    #最大等待1秒
	async: 1
	#不检测完成进度,直接下一个任务
    poll: 0

  - shell: ls /etc/passwd
    register: res

  - debug:
     var: res

执行结果,没超过4秒

代码语言:txt
复制
real	0m2.759s
user	0m0.589s
sys	    0m0.373s

async_status

更新serverc的所有软件包,并且不等待它执行完毕;继续向下执行任务,执行等待更新任务3秒,如果还没有完成就退出剧本的执行。

代码语言:txt
复制
[ansible@workstation ~]$ cat async.yml 
- hosts: serverc
  tasks:
  #更新软件包
  - yum:
     name: "*"
     state: latest
    register: result
    async: 100
    poll: 0
  
	#查看变量信息,可以看到jid
  - debug:
     var: result
  
  - lineinfile:
     path: /tmp/msg
     line: "working...."
     create: yes
     
	#查看异步状态
  - async_status:
     jid: "{{ result.ansible_job_id }}"
	register: job_result
	
	#如果没有结束就继续循环
	until: job_result.finished
	
	#最大等待3秒
    retries: 3

执行后看到jid信息

代码语言:txt
复制
TASK [debug] *************************
ok: [serverc] => {
    "result": {
        "ansible_job_id": "555948486663.1850", 
        "changed": true, 
        "finished": 0, 
        "results_file": "/root/.ansible_async/555948486663.1850", 
        "started": 1
    }
}
TASK [async_status]*************************
FAILED - RETRYING: async_status (3 retries left).
FAILED - RETRYING: async_status (2 retries left).
FAILED - RETRYING: async_status (1 retries left).

通过jid查看继续在执行的异步任务

代码语言:txt
复制
[ansible@workstation ~]$ ansible serverc -m async_status -a "jid=555948486663.1850"
serverc | SUCCESS => {
    "ansible_job_id": "555948486663.1850", 
    "changed": true, 
    "finished": 1, 
    "msg": "", 
    "rc": 0, 
}

委派

获取本地主机名

代码语言:txt
复制
[student@workstation ansible]$ cat play.yml 
- hosts: webservers
  tasks:
  - name:  get remote host name
    command: hostname
    register: res

  - debug:
     var: res.stdout

  - name: get local host name
    command: hostname
    register: res
    delegate_to: localhost

  - debug:
     var: res.stdout

执行剧本

代码语言:txt
复制
[student@workstation ansible]$ ansible-playbook play.yml 

PLAY [webservers] **************************************************************************************************

TASK [Gathering Facts] **************************************************************************************************
ok: [serverc]
ok: [serverd]

TASK [get remote host name] **************************************************************************************************
changed: [serverc]
changed: [serverd]

TASK [debug] **************************************************************************************************
ok: [serverc] => {
    "res.stdout": "serverc.lab.example.com"
}
ok: [serverd] => {
    "res.stdout": "serverd.lab.example.com"
}

TASK [get local host name] **************************************************************************************************
changed: [serverc -> localhost]
changed: [serverd -> localhost]

TASK [debug] **************************************************************************************************
ok: [serverc] => {
    "res.stdout": "workstation.lab.example.com"
}
ok: [serverd] => {
    "res.stdout": "workstation.lab.example.com"
}

PLAY RECAP **************************************************************************************************
serverc                    : ok=5    changed=2    unreachable=0    failed=0   
serverd                    : ok=5    changed=2    unreachable=0    failed=0  

委派facts

获取webservers.prod主机组下的主机的ipv4地址

代码语言:txt
复制
[student@workstation ansible]$ cat play.yml 
- hosts: webservers
  tasks:
  - name: gather facts from prod
    setup:
    delegate_to: "{{ item }}"
    with_items: "{{ groups.prod }}"

  - debug:
     var: ansible_default_ipv4.address

执行查看结果

代码语言:txt
复制
[student@workstation ansible]$ ansible-playbook play.yml 

PLAY [webservers] **************************************************************************************************

TASK [Gathering Facts] **************************************************************************************************
ok: [serverd]
ok: [serverc]

TASK [gather facts from prod] **************************************************************************************************
ok: [serverc -> serverc] => (item=serverc)
ok: [serverd -> serverc] => (item=serverc)
ok: [serverd -> serverd] => (item=serverd)
ok: [serverc -> serverd] => (item=serverd)

TASK [debug] **************************************************************************************************
ok: [serverd] => {
    "ansible_default_ipv4.address": "172.25.250.13"
}
ok: [serverc] => {
    "ansible_default_ipv4.address": "172.25.250.13"
}
PLAY RECAP **************************************************************************************************
serverc                    : ok=3    changed=0    unreachable=0    failed=0   
serverd                    : ok=3    changed=0    unreachable=0    failed=0 

等主机开机

重启dev组的主机,然后等待它开机继续执行任务

代码语言:txt
复制
- hosts: dev
  tasks:
  - shell: sleep 1 && shutdown -r now "Ansible~~~"
    async: 1
    poll: 0
    ignore_errors: true

  - wait_for:
     host: "{{ inventory_hostname }}"
     state: started
     delay: 30
     timeout: 300
     port: 22
    delegate_to: localhost

delegate_to:把当前任务交给指定的主机去执行

wait_for模块

timeout

默认超时时间300s。

sleep

两次check之间间隔,默认1s。

delay

延迟30s启动检测任务。

host

监测的主机名或者IP

port

监测的对象端口

path

监视文件

state

状态,present, started(默认), stopped, absent, drained

当检测端口时

检查文件或搜索字符串时

drained 检查活动连接

present 或者 started'检查文件或字符串存在

stopped 检查是否关闭

absent 检查文件是否不存在或已删除

started 检查是否打开

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 异步与并发
    • fork
      • 尝试
      • 发现
      • 再次实验
      • 结论
    • serial
      • 需求
      • 实验
      • 总结
    • async
      • async_status
      • 委派
        • 获取本地主机名
          • 委派facts
            • 等主机开机
              • wait_for模块
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档