通过celery异步处理一个查询任务的完整代码


Posted in Python onNovember 19, 2019

今天介绍通过celery实现一个异步任务。有这样一个需求,前端发起一个查询的请求,但是发起查询后,查询可能不会立即返回结果。这时候,发起查询后,后端可以把这次查询当作一个task,并立即返回一个能唯一表明该task的值,如taskID(用户后面可以通过这个taskID 随时查看结果),用户收到这个taskID后,可以转去处理其他任务,而不必一直等待查询结果。后端API调用celery来处理这个task,并将结果值保存在一个csv文件中,后面用户通过taskID 查询时返回结果。

def application(environ,start_response):
  """部分代码省略"""
  query_string = environ['QUERY_STRING']
  serviceGroupName = ""
  for getParam in query_string.split("&"):
    params = getParam.split("=")
    resultInfo = ""
    if params[0] == "type":
      alertType = params[1]
    elif params[0] == "projectName":
      projectName = params[1]
    elif params[0] == "serviceGroupName":
      serviceGroupName = params[1]
    else:
      resultInfo = error_info(-1, "GET参数只能为type=<?>&projectName=<?>&serviceGroupName=<?>;必须指定三个参数", {})
    return [resultInfo]  
  taskId = 1
  result_file_name = '/var/www/dba_api/api/test/'+ str(taskId) + '.csv'
  contentInfo = json.dumps({"taskId":1,"opType":"continue","serviceGroupName":serviceGroupName,"dbHost":dbHost,"dbPasswd":dbPasswd,"dbUser":dbUser,"dbPort":dbPort})
  result = getServiceInfo.apply_async((contentInfo,),queue="getServiceInfo")
  taskInfo = "任务已经创建,详情请查看:http://10.4.34.254/api/task?taskId=%s"% (taskId)
  return [resultInfo]

getServiceInfo.apply_async((contentInfo,),queue=”getServiceInfo”),重点是这一行,apply_async()方法会返回一个AsyncResult实例,通过这个实例可以跟踪任务状态轨迹。

要使用此功能,需要提供结果后台(result backend),这样才有地方存储任务状态等信息。其中,getServiceInfo是自定义的一个task,后续会介绍到,contentInfo是传递的一个参数,queue是指定队列名称。

上面这个函数的原型如下:

task.apply_async(args[, kwargs[, …]])

其中 args 和 kwargs 分别是 task 接收的参数,当然它也接受额外的参数对任务进行控制。

在 Celery 中执行任务的方法一共有三种:

1. delay, 用来进行最简单便捷的任务执行(delay在第3小节的测试中使用过,它可以看作是apply_async的一个快捷方式);

2. apply_async, 对于任务的执行附加额外的参数,对任务进行控制;

3. app.send_task, 可以执行未在 Celery 中进行注册的任务。

celery文件配置

在python的库存放路径中(一般是/usr/lib/python2.6/site-packages),创建一个文件夹proj,进入proj目录,创建三个文件,init,将proj声明一个python包,celepy,其内容如下:

#_*_ coding:utf-8 _*_
from __future__ import absolute_import
from celery import Celery

app = Celery("proj",
broker="amqp://user:password@localhost//",
backend="amqp",
include=["proj.tasks"]
)
app.conf.update(
CELERY_ROUTES={
"proj.tasks.getServerInfo":{"queue":"getServerInfo"},
}
)
if __name__=="__main__":
  app.start()

这里我们定义了模块名称proj以及celery 路由。

还有一个文件,task.py

#_*_ coding:utf-8 _*_i
from __future__ import absolute_import
from proj.celery import app
import random
import simplejson as json
import types
import time
import MySQLdb
import urllib2
import ConfigParser as cparser
import hmac
import hashlib
import base64
@app.task
def getServiceInfo(contentInfo):
  contentInfo = json.loads(contentInfo)
  serviceGroupName = contentInfo['serviceGroupName']

  dbHost = contentInfo['dbHost']
  dbPort = int(contentInfo['dbPort'])
  dbUser = contentInfo['dbUser']
  dbPasswd = contentInfo['dbPasswd']
  msgLib = MessageLib.MessageLib()
  Sql = "Your SQL"
  #第三步:连接数据库,执行代码逻辑
  try:
    db_connection = MySQLdb.connect(host=dbHost, port=dbPort, passwd=dbPasswd, db="cmdb", user=dbUser, connect_timeout=2, charset="utf8")
    cursor = db_connection.cursor()
    cursor.execute(getServiceGroupHostSql)
    row = cursor.fetchall()
    result = []
    for line in row:
      ...
      result.append(tempMysqlHighInfo)

  resultInfo = msgLib.success_info(result)
  return resultInfo
  except Exception, e:
    raise
    errorInfo = "dbhost:%s, port:%s, error:%s" % (dbHost, dbPort, str(e))
    #return getServiceGroupHostSql,errorInfo
    return msgLib.error_info(-1, errorInfo, {})

启动celery

celery -A proj worker -Q getServiceInfo -l debug -c 6

最后,写一个结果,专门获取查询结果的结果,传入的参数为taskID,部分代码如下:

def application(environ,start_response):
  status = '400 ERROR'
  response_headers = [('Content-type', 'application/json;charset=utf-8')]
  start_response(status, response_headers)

  status = '200 OK'
  response_headers = [('Content-type', 'application/json;charset=utf-8')]
  start_response(status, response_headers)

  if environ['REQUEST_METHOD'] != "GET":
    resultInfo = msgLib.error_info(-1, "http请求类型不是GET", {})
  return [resultInfo]

  query_string = environ['QUERY_STRING']
  serviceGroupName = ""
  for getParam in query_string.split("&"):
    params = getParam.split("=")
    resultInfo = ""
    if params[0] == "taskId":
      taskId = params[1]
    else:
      resultInfo = msgLib.error_info(-1, "GET参数无比指定taskId这个参数", {})
    return [resultInfo]
  logging.info(query_string)
  result_file_name = '/var/www/dba_api/api/test/'+ str(taskId) + '.csv'
  result = []
  try:
    with open (result_file_name,'rb') as fp:
    lines = csv.reader(fp)
    for line in lines :
    result.append(line)
    resultInfo = msgLib.success_info(result)
  return resultInfo
  except Exception, e:
  errorInfo = "some thing wrong"
  return msgLib.error_info(-1, errorInfo, {})

以上这篇通过celery异步处理一个查询任务的完整代码就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python3实现暴力穷举博客园密码
Jun 19 Python
Python如何获取系统iops示例代码
Sep 06 Python
Python中正则表达式详解
May 17 Python
django 发送邮件和缓存的实现代码
Jul 18 Python
对pandas读取中文unicode的csv和添加行标题的方法详解
Dec 12 Python
pycharm+PyQt5+python最新开发环境配置(踩坑)
Feb 11 Python
用Cython加速Python到“起飞”(推荐)
Aug 01 Python
浅谈django url请求与数据库连接池的共享问题
Aug 29 Python
python实现飞机大战游戏(pygame版)
Oct 26 Python
python GUI库图形界面开发之PyQt5单行文本框控件QLineEdit详细使用方法与实例
Feb 27 Python
Python如何读取、写入JSON数据
Jul 28 Python
python实现测试工具(二)——简单的ui测试工具
Oct 19 Python
Django 自动生成api接口文档教程
Nov 19 #Python
wxpython实现按钮切换界面的方法
Nov 19 #Python
Python性能分析工具Profile使用实例
Nov 19 #Python
使用apiDoc实现python接口文档编写
Nov 19 #Python
wxPython绘图模块wxPyPlot实现数据可视化
Nov 19 #Python
Python浮点数四舍五入问题的分析与解决方法
Nov 19 #Python
python 上下文管理器及自定义原理解析
Nov 19 #Python
You might like
SONY ICF-SW07收音机电路分析
2021/03/02 无线电
PHP 字符串长度判断效率更高的方法
2014/03/02 PHP
php线性表的入栈与出栈实例分析
2015/06/12 PHP
PHP实现冒泡排序的简单实例
2016/05/26 PHP
PHP实现微信小程序用户授权的工具类示例
2019/03/05 PHP
PHP中常用的三种设计模式详解【单例模式、工厂模式、观察者模式】
2019/06/14 PHP
JQuery 国际象棋棋盘 实现代码
2009/06/26 Javascript
javascript学习笔记(五)原型和原型链详解
2014/10/08 Javascript
JS+CSS实现可拖动的弹出提示框
2015/02/16 Javascript
javascript实现表单提交后,提交按钮不可用的方法
2015/04/18 Javascript
jquery+json实现数据二级联动的方法
2015/11/28 Javascript
json字符串传到前台input的方法
2018/08/06 Javascript
微信小程序实现bindtap等事件传参
2019/04/08 Javascript
JS实现li标签的删除
2019/04/12 Javascript
vue实现点击按钮下载文件功能
2019/10/11 Javascript
springboot+vue实现文件上传下载
2020/11/17 Vue.js
原生js中运算符及流程控制示例详解
2021/01/05 Javascript
Python正则获取、过滤或者替换HTML标签的方法
2016/01/28 Python
python中的内置函数max()和min()及mas()函数的高级用法
2018/03/29 Python
Python Unittest根据不同测试环境跳过用例的方法
2018/12/16 Python
Python使用pandas对数据进行差分运算的方法
2018/12/22 Python
Pandas之ReIndex重新索引的实现
2019/06/25 Python
在django模板中实现超链接配置
2019/08/21 Python
python子线程退出及线程退出控制的代码
2019/10/16 Python
Django 实现Admin自动填充当前用户的示例代码
2019/11/18 Python
虚拟环境及venv和virtualenv的区别说明
2021/02/05 Python
Interhome丹麦:在线预订度假屋和公寓
2019/07/18 全球购物
JavaScript实现页面动态验证码的实现示例
2021/03/23 Javascript
2013年保送生自荐信格式
2013/11/20 职场文书
思想汇报格式
2014/01/05 职场文书
运动会通讯稿150字
2014/02/15 职场文书
室内设计专业自荐信
2014/05/31 职场文书
党员个人查摆剖析材料
2014/10/16 职场文书
安全知识竞赛主持词
2015/06/30 职场文书
Redis 哨兵机制及配置实现
2022/03/25 Redis
Apache自带的ab压力测试工具的实现
2022/07/23 Servers