通过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 相关文章推荐
python实现在字符串中查找子字符串的方法
Jul 11 Python
python 数据的清理行为实例详解
Jul 12 Python
python计算列表内各元素的个数实例
Jun 29 Python
Python实现聊天机器人的示例代码
Jul 09 Python
python+opencv实现霍夫变换检测直线
Oct 23 Python
Python基于opencv调用摄像头获取个人图片的实现方法
Feb 21 Python
在python tkinter中Canvas实现进度条显示的方法
Jun 14 Python
django将数组传递给前台模板的方法
Aug 06 Python
Python计算指定日期是今年的第几天(三种方法)
Mar 26 Python
Python3 webservice接口测试代码详解
Jun 23 Python
OpenCV3.3+Python3.6实现图片高斯模糊
May 18 Python
Python借助with语句实现代码段只执行有限次
Mar 23 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
smarty模板嵌套之include与fetch性能测试
2010/12/05 PHP
php异常:Parse error: syntax error, unexpected T_ENCAPSED_AND_WHITESPACE  eval()'d code error
2011/05/19 PHP
phpize的深入理解
2013/06/03 PHP
PHP 用session与gd库实现简单验证码生成与验证的类方法
2016/11/15 PHP
Jquery+JSon 无刷新分页实现代码
2010/04/01 Javascript
读jQuery之九 一些瑕疵说明
2011/06/21 Javascript
form表单中去掉默认的enter键提交并绑定js方法实现代码
2013/04/01 Javascript
iframe调用父页面函数示例详解
2014/07/17 Javascript
node.js中使用socket.io的方法
2014/12/15 Javascript
深入理解JavaScript系列(29):设计模式之装饰者模式详解
2015/03/03 Javascript
javascript实现简单的on事件绑定
2016/08/23 Javascript
Vue中的v-cloak使用解读
2017/03/27 Javascript
微信小程序实战之自定义toast(6)
2017/04/18 Javascript
SpringMVC+bootstrap table实例详解
2017/06/02 Javascript
深入浅析javascript继承体系
2017/10/23 Javascript
ligerUI---ListBox(列表框可移动的实例)
2017/11/28 Javascript
微信小程序实现点击按钮修改文字大小功能【附demo源码下载】
2017/12/06 Javascript
使用svg实现动态时钟效果
2018/07/17 Javascript
详解Vue组件之间通信的七种方式
2019/04/14 Javascript
javascript+HTML5 canvas绘制时钟功能示例
2019/05/15 Javascript
详解vue3.0 的 Composition API 的一种使用方法
2020/10/26 Javascript
vuex Module将 store 分割成模块的操作
2020/12/07 Vue.js
[05:03]显微镜下的DOTA2第十期——Ti3豪之超神幽鬼
2014/06/23 DOTA
使用Python抓取模板之家的CSS模板
2015/03/16 Python
六个窍门助你提高Python运行效率
2015/06/09 Python
关于python列表增加元素的三种操作方法
2018/08/22 Python
keras 解决加载lstm+crf模型出错的问题
2020/06/10 Python
Web前端绘制0.5像素的几种方法
2017/08/11 HTML / CSS
台湾网友喜爱的综合型网路购物商城:Yahoo! 奇摩购物中心
2018/03/10 全球购物
瑞典的玛丽小姐:Miss Mary of Sweden
2019/02/13 全球购物
法律专业自我鉴定
2013/10/03 职场文书
医科大学生的自我评价
2013/12/04 职场文书
上班时间打瞌睡检讨书
2014/09/26 职场文书
2014年学校办公室工作总结
2014/12/19 职场文书
2015年财务经理工作总结
2015/05/13 职场文书
《神奇的鸟岛》教学反思
2016/02/22 职场文书