docker下載redis
docker下載rabbitmq
docker run -d -p 5672:5672 rabbitmq
docker run -d -p 6379:6379 redis:alpine
docker exec -it 16e701cfb49b redis-cli
你的環(huán)境下下載
pip3 install celery
pip3 install rabbitmq
pip3 install redis
pip3 install django-debug-toolbar
在你的項(xiàng)目下創(chuàng)建一個(gè)celery.py的文件

image.png
寫(xiě)入如下代碼
import os
from celery import Celery
# set the default Django settings module for the 'celery' program.
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'auto_cmdb.settings')
app = Celery('auto_cmdb')
# Using a string here means the worker doesn't have to serialize
# the configuration object to child processes.
# - namespace='CELERY' means all celery-related configuration keys
# should have a `CELERY_` prefix.
app.config_from_object('django.conf:settings', namespace='CELERY')
# Load task modules from all registered Django app configs.
app.autodiscover_tasks()
再在settings里配置如下
# Celery 配置
# 配置消息中間件
CELERY_BROKER_URL = 'amqp://shark:123456@localhost:5672/lianjiu'
# 以上信息需要在 rabbitmq 中添加:
# 用戶(hù) shark 命令為: rabbitmqctl add_user shark 123456
# 虛擬主機(jī) qfvhost 命令為: rabbitmqctl add_vhost qfvhost
# 授權(quán)信息 命令為: rabbitmqctl set_permissions -p qfvhost shark ".*" ".*" ".*"
# CELERY_RESULT_BACKEND = 'db+sqlite:///results.sqlite'
CELERY_RESULT_BACKEND = 'redis://localhost:6379/1'
# CELERY_TASK_SERIALIZER = 'json'
# 執(zhí)行任務(wù)的異步工作進(jìn)程/線(xiàn)程/綠色線(xiàn)程的數(shù)量。
# 如果您主要執(zhí)行I / O,則可以有更多的進(jìn)程,
# 但如果主要是CPU約束,請(qǐng)嘗試使其與計(jì)算機(jī)上的CPU數(shù)量保持接近。
# 如果未設(shè)置,將使用主機(jī)上的CPU /內(nèi)核數(shù)。
CELERY_WORKER_CONCURRENCY = 6
# 延遲確認(rèn) 意味著任務(wù)消息將在任務(wù)執(zhí)行后得到確認(rèn)
CELERY_TASK_ACKS_LATE = True
# 每個(gè) worker 最多執(zhí)行 60 個(gè)任務(wù)就自動(dòng)銷(xiāo)毀,防止內(nèi)存泄露
CELERY_WORKER_MAX_TASKS_PER_CHILD = 60
# 單個(gè)任務(wù)的硬時(shí)間限制(秒)。
# 超過(guò)此值時(shí),處理任務(wù)的工作進(jìn)程將被終止并替換為新的工作進(jìn)程。
CELERY_TASk_TIME_LIMIT = 5 * 60
######################################
# 配置 django-debug-toolbar
# 僅當(dāng)IP地址列在“內(nèi)部IP”設(shè)置中時(shí),才會(huì)顯示“調(diào)試”工具欄。
# 這意味著對(duì)于本地開(kāi)發(fā),必須將“127.0.0.1”添加到IntualIPS中;
# 如果在設(shè)置模塊中不存在此設(shè)置,則需要?jiǎng)?chuàng)建此設(shè)置:
INTERNAL_IPS = [
'127.0.0.1',
]
DEBUG_TOOLBAR_CONFIG = {
# Toolbar options
'RESULTS_CACHE_SIZE': 3,
'SHOW_COLLAPSED': True,
# Panel options
'SQL_WARNING_THRESHOLD': 0.5, # milliseconds 毫秒
}
這是用來(lái)連接redis的 rabbitmqctl是一個(gè)連接redis的中間件
之后在項(xiàng)目下創(chuàng)建tasks.py文件 (不能改)
在tasks里邊寫(xiě)要并發(fā)的函數(shù)之類(lèi)的
from __future__ import absolute_import, unicode_literals
from celery import shared_task
from .utils.handle_commend import HandleCommand
from cmdb.models import InventoryPool
import time
@shared_task
def cmdb_celery(command):
inventorys = InventoryPool.objects.all()
handle = HandleCommand(command,inventorys)
ret = handle.exec_command()
print("任務(wù)執(zhí)行中")
return ret
@shared_task
def add(n):
import time
time.sleep(8)
return n + 1
之后在對(duì)應(yīng)的視圖導(dǎo)入
from .tasks import cmdb_celery,add
class AsyncView(View):
def get(self,request):
return render(request,'octopus/async.html')
def post(self,request):
num = request.POST.get("num")
task = add.delay(int(num))
print("命令已送達(dá)。。。。。。。")
return JsonResponse({"task_id":task.id})
第二個(gè)例子
class RunViewajax(View):
def get(self,request):
inventorys = InventoryPool.objects.all()
return render(request,"octopus/run1.html",{
"inventorys":inventorys
})
def post(self,request):
command= request.POST.get('command')
task1 = cmdb_celery.delay(command)
要用delay才能實(shí)現(xiàn)異步 并且他自己可以實(shí)現(xiàn)一個(gè)ID這樣.出來(lái)就行
下面實(shí)現(xiàn)傳入前端的數(shù)據(jù)
from celery.result import AsyncResult
class TaskResultView(View):
def get(self, request):
task_id = self.request.GET.get("task_id")
task_obj = AsyncResult(id=task_id)
task_json = {
"id": task_obj.id,
"status": task_obj.status,
"success": task_obj.successful(),
"result": task_obj.result
}
return JsonResponse(task_json)
前端實(shí)例
{% load staticfiles %}
{% block first%}
ansible 執(zhí)行命令
{% endblock %}
{% block second %}run
{% endblock %}
{% block content %}
<div class="row">
<div class="col-md-3">
<h3>組列表</h3>
{% for inventory in inventorys %}
<div class="box box-solid collapsed-box">
<div class="box-header with-border">
<h3 class="box-title">{{ inventory.group }}</h3>
<div class="box-tools">
<button type="button" class="btn btn-box-tool" data-widget="collapse"><i class="fa fa-plus"></i>
</button>
</div>
</div>
<div class="box-body no-padding" style="display: none">
<ul class="nav nav-pills nav-stacked">
{% for server in inventory.server.all %}
<li><a href="#"><i class="fa fa-laptop"></i> {{ server.manager_ip }}</a></li>
{% endfor %}
</ul>
</div>
<!-- /.box-body -->
</div>
{% endfor %}
<!-- /.box -->
</div>
<!-- /.col -->
<div class="col-md-9">
<div class="box box-primary">
<div class="box-header with-border">
<h3 class="box-title">執(zhí)行 Ansible 命令</h3>
</div>
<!-- /.box-header -->
<!-- /.box-body -->
<div class="box-footer no-padding">
<div class="box-footer">
<div class="input-group">
<input type="text" name="command" placeholder="ansible all -m shell -a 'ls /tmp'" style="font-size: 30px;height: 50px" class="form-control">
<span class="input-group-btn" >
<button type="submit" class="btn btn-success" id="sendinfo">Send</button>
</span>
</div>
</div>
</div>
</div>
<!-- /. box -->
<div class="box box-primary">
<div class="box-header with-border">
<h3 class="box-title">命名結(jié)果展示</h3>
</div>
<div class="box-footer no-padding" >
<span id="result"></span>
</div>
</div>
</div>
</div>
{% endblock %}
{% block script %}
<script>
$(function(){
function handleTask(task_id){
var timer = setTimeout(function f(task_id) {
// 根據(jù) task_id 獲取 task 對(duì)象
$.getJSON(
url=`/octopus/get_task/?task_id=${task_id}`,
function(ret){
if (ret.success){
$("#result").append(`<div><code >${ret.id}</code><div>`)
$("#result").append(`<div><code >${ret.status}</code><div>`)
$("#result").append(`<div><code >任務(wù)結(jié)果${ret.result.msg}</code><div>`);
clearTimeout(timer);
}else{
$("#result").append(`<div><code >${ret.id}</code><div>`);
$("#result").append(`<div><code >${ret.status}</code><div>`);
};
}
)
timer = setTimeout(f, 2000, task_id);
}, 2000, task_id);
}
$("#sendinfo").on("click", function(){
let command = $(this).parent().siblings().val();
if( !command){
alert("命令為空");
return false
}
$.ajax({
url: "{% url 'octopus:run' %}",
type: "POST",
data: {"command": command,'csrfmiddlewaretoken':'{{ csrf_token }}'},
dataType:'json',
success: function(res){
$("#commandResult").empty();
let task_id = res.task_id;
// alert("task_id");
// $("#result").text(task_id);
handleTask(task_id);
}
}
)
})
})
</script>
{% endblock %}
前端中要注意的是定時(shí)期JS
延遲多少事件后在執(zhí)行一個(gè)函數(shù)
setTimeout(function(形參){},2000,實(shí)參)//毫秒
-每隔多長(zhǎng)時(shí)間執(zhí)行一次函數(shù)
setInventory(function(形參){},2000,實(shí)參)
clearTimeout(timer)清除定時(shí)器
url

image.png
運(yùn)行這個(gè)celery
celery -A auto_cmdb worker -l info