通过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中使用HTMLParser解析html实例
Feb 08 Python
在Python中使用列表生成式的教程
Apr 27 Python
Python网络爬虫出现乱码问题的解决方法
Jan 05 Python
Python使用回溯法子集树模板获取最长公共子序列(LCS)的方法
Sep 08 Python
Python图像处理之识别图像中的文字(实例讲解)
May 10 Python
Anaconda下配置python+opencv+contribx的实例讲解
Aug 06 Python
详解PyCharm安装MicroPython插件的教程
Jun 24 Python
Django项目主urls导入应用中views的红线问题解决
Aug 10 Python
Python爬虫实现的根据分类爬取豆瓣电影信息功能示例
Sep 15 Python
pyqt5、qtdesigner安装和环境设置教程
Sep 25 Python
python为什么会环境变量设置不成功
Jun 23 Python
Keras多线程机制与flask多线程冲突的解决方案
May 28 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
手把手教你使用DedeCms V3的在线采集图文教程
2007/04/03 PHP
php高级编程-函数-郑阿奇
2011/07/04 PHP
解析将多维数组转换为支持curl提交的一维数组格式
2013/07/08 PHP
PHP中判断变量为空的几种方法小结
2013/11/12 PHP
PHP运行SVN命令显示某用户的文件更新记录的代码
2014/01/03 PHP
thinkphp3查询mssql数据库乱码解决方法分享
2014/02/11 PHP
yii实现级联下拉菜单的方法
2014/07/31 PHP
PHP图片自动裁切应付不同尺寸的显示
2014/10/16 PHP
把jquery 的dialog和ztree结合实现步骤
2013/08/02 Javascript
JS设置cookie、读取cookie
2016/02/24 Javascript
原生js仿jquery animate动画效果
2016/07/13 Javascript
详细解读Jquery各Ajax函数($.get(),$.post(),$.ajax(),$.getJSON())
2016/08/15 Javascript
原生JS实现网络彩票投注效果
2016/09/25 Javascript
JavaScript防止全局变量污染的方法总结
2018/08/02 Javascript
jQuery实现基本淡入淡出效果的方法详解
2018/09/05 jQuery
iview同时验证多个表单问题总结
2018/09/29 Javascript
基于Echarts图表在div动态切换时不显示的解决方式
2020/07/20 Javascript
jQuery实现异步上传一个或多个文件
2020/08/17 jQuery
[04:16]DOTA2英雄梦之声_第09期_斧王
2014/06/21 DOTA
[04:17]DOTA2完美盛典,rOtk、BurNIng携手巴图演唱《倔强》
2017/11/28 DOTA
10款最好的Web开发的 Python 框架
2015/03/18 Python
在Django中编写模版节点及注册标签的方法
2015/07/20 Python
Python列出一个文件夹及其子目录的所有文件
2016/06/30 Python
Python最火、R极具潜力 2017机器学习调查报告
2017/12/11 Python
python+VTK环境搭建及第一个简单程序代码
2017/12/13 Python
解决python写入mysql中datetime类型遇到的问题
2018/06/21 Python
Python实现识别图片内容的方法分析
2018/07/11 Python
使用pytorch完成kaggle猫狗图像识别方式
2020/01/10 Python
PyCharm 在Windows的有用快捷键详解
2020/04/07 Python
Python之Sklearn使用入门教程
2021/02/19 Python
String和StringBuffer的区别
2015/08/13 面试题
广告学专业毕业生自荐信
2013/09/24 职场文书
职业生涯规划书基本格式
2014/01/06 职场文书
工商企业管理应届生求职信
2014/05/04 职场文书
上班迟到检讨书300字
2014/10/18 职场文书
驳回起诉民事裁定书
2015/05/19 职场文书