通过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 相关文章推荐
在Django中使用Sitemap的方法讲解
Jul 22 Python
python脚本设置超时机制系统时间的方法
Feb 21 Python
python3中dict(字典)的使用方法示例
Mar 22 Python
python 3.6 tkinter+urllib+json实现火车车次信息查询功能
Dec 20 Python
python读文件保存到字典,修改字典并写入新文件的实例
Apr 23 Python
Python使用numpy产生正态分布随机数的向量或矩阵操作示例
Aug 22 Python
python实现写数字文件名的递增保存文件方法
Oct 25 Python
Python文件常见操作实例分析【读写、遍历】
Dec 10 Python
flask框架单元测试原理与用法实例分析
Jul 23 Python
使用Puppeteer爬取微信文章的实现
Feb 11 Python
利用Python如何实时检测自身内存占用
May 09 Python
Python+OpenCV实现在图像上绘制矩形
Mar 21 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
php smarty的预保留变量总结
2008/12/04 PHP
php实现使用正则将文本中的网址转换成链接标签
2014/12/03 PHP
prototype class详解
2006/09/07 Javascript
IE6下JS动态设置图片src地址问题
2010/01/08 Javascript
JS定时关闭窗口的实例
2013/05/22 Javascript
jquery获取选中的文本和值的方法
2014/07/08 Javascript
JS实现黑色风格的网页TAB选项卡效果代码
2015/10/09 Javascript
bootstrap table 多选框分页保留示例代码
2017/03/08 Javascript
JS获取字符对应的ASCII码实例
2017/09/10 Javascript
详解node单线程实现高并发原理与node异步I/O
2017/09/21 Javascript
Router解决跨模块下的页面跳转示例
2018/01/11 Javascript
vue slot 在子组件中显示父组件传递的模板
2018/03/02 Javascript
vue2.x集成百度UEditor富文本编辑器的方法
2018/09/21 Javascript
js实现掷骰子小游戏
2019/10/24 Javascript
JS中间件设计模式的深入探讨与实例分析
2020/04/11 Javascript
jquery实现穿梭框功能
2021/01/19 jQuery
Python中的super()方法使用简介
2015/08/14 Python
Python中set与frozenset方法和区别详解
2016/05/23 Python
浅谈pyhton学习中出现的各种问题(新手必看)
2017/05/17 Python
深入了解Python中pop和remove的使用方法
2018/01/09 Python
python3 requests中使用ip代理池随机生成ip的实例
2018/05/07 Python
pyspark.sql.DataFrame与pandas.DataFrame之间的相互转换实例
2018/08/02 Python
在python中利用KNN实现对iris进行分类的方法
2018/12/11 Python
Python交互式图形编程的实现
2019/07/25 Python
python中利用numpy.array()实现俩个数值列表的对应相加方法
2019/08/26 Python
Python字符串中添加、插入特定字符的方法
2019/09/10 Python
python 将dicom图片转换成jpg图片的实例
2020/01/13 Python
Python安装OpenCV的示例代码
2020/03/05 Python
python topk()函数求最大和最小值实例
2020/04/02 Python
Python 虚拟环境工作原理解析
2020/12/24 Python
租房协议书
2014/04/10 职场文书
运动会表扬稿
2015/01/16 职场文书
社区志愿服务活动感想
2015/08/07 职场文书
详解Nginx 工作原理
2021/03/31 Servers
Go语言设计模式之结构型模式
2021/06/22 Golang
世界无敌的ICOM IC-R9500宽频接收机
2022/03/25 无线电