通过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的*args和**kwargs用法
Nov 01 Python
python标准日志模块logging的使用方法
Nov 01 Python
Python判断列表是否已排序的各种方法及其性能分析
Jun 20 Python
NetworkX之Prim算法(实例讲解)
Dec 22 Python
如何用Python实现简单的Markdown转换器
Jul 16 Python
Python基于SMTP协议实现发送邮件功能详解
Aug 14 Python
python导入不同目录下的自定义模块过程解析
Nov 18 Python
python无序链表删除重复项的方法
Jan 17 Python
解决Jupyter因卸载重装导致的问题修复
Apr 10 Python
关于PyCharm安装后修改路径名称使其可重新打开的问题
Oct 20 Python
python 基于DDT实现数据驱动测试
Feb 18 Python
用 Python 元类的特性实现 ORM 框架
May 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
php设计模式 Singleton(单例模式)
2011/06/26 PHP
php警告Creating default object from empty value 问题的解决方法
2014/04/02 PHP
PHP生成随机数的方法实例分析
2015/01/22 PHP
PHP SPL标准库之接口(Interface)详解
2015/05/11 PHP
php解析xml方法实例详解
2015/05/12 PHP
[原创]php使用strpos判断字符串中数字类型子字符串出错的解决方法
2017/04/01 PHP
prototype与jquery下Ajax实现的差别
2009/09/13 Javascript
JS清除IE浏览器缓存的方法
2013/07/26 Javascript
JavaScript定时器详解及实例
2013/08/01 Javascript
jQuery打印指定区域Html页面并自动分页
2014/07/04 Javascript
使用nodejs、Python写的一个简易HTTP静态文件服务器
2014/07/18 NodeJs
JS中实现简单Formatter函数示例代码
2014/08/19 Javascript
Node.js中使用Log.io在浏览器中实时监控日志(等同tail -f命令)
2014/09/17 Javascript
使用phantomjs进行网页抓取的实现代码
2014/09/29 Javascript
Jquery uploadify上传插件使用详解
2016/01/13 Javascript
分类解析jQuery选择器
2016/11/23 Javascript
vue中Element-ui 输入银行账号每四位加一个空格的实现代码
2018/09/14 Javascript
vue百度地图 + 定位的详解
2019/05/13 Javascript
Node.js API详解之 zlib模块用法分析
2020/05/19 Javascript
python读写ini文件示例(python读写文件)
2014/03/25 Python
Python安装Imaging报错:The _imaging C module is not installed问题解决方法
2014/08/22 Python
python数据抓取分析的示例代码(python + mongodb)
2017/12/25 Python
Python爬取视频(其实是一篇福利)过程解析
2019/08/01 Python
python 给图像添加透明度(alpha通道)
2020/04/09 Python
Python 下载Bing壁纸的示例
2020/09/29 Python
让IE支持CSS3的不完全兼容方案
2014/09/19 HTML / CSS
Linux不知道文件后缀名怎么判断文件类型
2012/04/26 面试题
新闻网站实习自我鉴定
2013/09/25 职场文书
向国旗敬礼活动小结
2014/09/27 职场文书
自荐信格式模板
2015/03/27 职场文书
2015年会计工作总结范文
2015/05/26 职场文书
教育教学读书笔记
2015/07/02 职场文书
导游词之江南园林狮子林
2019/09/16 职场文书
导游词之晋城蟒河
2019/12/12 职场文书
MySQL里面的子查询的基本使用
2021/08/02 MySQL
MySQL索引失效场景及解决方案
2022/07/23 MySQL