通过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实现2048小游戏
Mar 30 Python
Python pickle模块用法实例
Apr 14 Python
Python贪吃蛇游戏编写代码
Oct 26 Python
Collatz 序列、逗号代码、字符图网格实例
Jun 22 Python
老生常谈Python序列化和反序列化
Jun 28 Python
Python实现的旋转数组功能算法示例
Feb 23 Python
Python如何爬取实时变化的WebSocket数据的方法
Mar 09 Python
TensorFlow车牌识别完整版代码(含车牌数据集)
Aug 05 Python
利用python list完成最简单的DB连接池方法
Aug 09 Python
python-序列解包(对可迭代元素的快速取值方法)
Aug 24 Python
使用python-Jenkins批量创建及修改jobs操作
May 12 Python
Python列表嵌套常见坑点及解决方案
Sep 30 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递归调用的小技巧讲解
2013/02/19 PHP
php unset全局变量运用问题的深入解析
2013/06/17 PHP
php中convert_uuencode()与convert_uuencode函数用法实例
2014/11/22 PHP
浅析PHP中call user func()函数及如何使用call user func调用自定义函数
2015/11/05 PHP
WordPress中用于获取文章信息以及分类链接的函数用法
2015/12/18 PHP
JS操作图片(增,删,改) 例子
2013/04/17 Javascript
ie8下修改input的type属性报错的解决方法
2014/09/16 Javascript
js实现进度条的方法
2015/02/13 Javascript
Javascript实现计算个人所得税
2015/05/10 Javascript
浅析C/C++,Java,PHP,JavaScript,Json数组、对象赋值时最后一个元素后面是否可以带逗号
2016/03/22 Javascript
Jquery Easyui对话框组件Dialog使用详解(14)
2016/12/19 Javascript
js中document.referrer实现移动端返回上一页
2017/02/22 Javascript
JavaScript中EventLoop介绍
2018/01/22 Javascript
JS抛物线动画实例制作
2018/02/24 Javascript
原生JS实现的放大镜特效示例【测试可用】
2018/12/08 Javascript
ES6 Generator函数的应用实例分析
2019/06/26 Javascript
[03:42]2014DOTA2西雅图国际邀请赛 Navi战队巡礼
2014/07/07 DOTA
python实现的阳历转阴历(农历)算法
2014/04/25 Python
Python实现的数据结构与算法之快速排序详解
2015/04/22 Python
python2.7的编码问题与解决方法
2016/10/04 Python
Python面向对象程序设计之私有属性及私有方法示例
2019/04/08 Python
Opencv实现抠图背景图替换功能
2019/05/21 Python
如何使用python自带IDLE的几种方法
2020/10/10 Python
英国拳击装备购物网站:RDX Sports
2018/01/23 全球购物
聚网科技C++面试笔试题
2015/09/01 面试题
学前教育专业毕业生自荐信
2013/10/03 职场文书
教师求职信范文分享
2013/12/27 职场文书
幼儿教育感言
2014/02/05 职场文书
贷款委托书
2014/08/01 职场文书
人大调研汇报材料
2014/08/14 职场文书
防溺水主题班会教案
2015/08/12 职场文书
《玩出了名堂》教学反思
2016/02/17 职场文书
公文写作指导之倡议书!
2019/07/03 职场文书
python爬取企查查企业信息之selenium自动模拟登录企查查
2021/04/08 Python
java objectUtils 使用可能会出现的问题
2022/02/28 Java/Android
分享很少见很有用的SQL功能CORRESPONDING
2022/08/05 MySQL