通过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 12 Python
Python KMeans聚类问题分析
Feb 23 Python
python字典值排序并取出前n个key值的方法
Oct 17 Python
python 列表递归求和、计数、求最大元素的实例
Nov 28 Python
python利用requests库模拟post请求时json的使用教程
Dec 07 Python
详解Django-restframework 之频率源码分析
Feb 27 Python
详解Python中正则匹配TAB及空格的小技巧
Jul 26 Python
Python Django中间件,中间件函数,全局异常处理操作示例
Nov 08 Python
在OpenCV里使用Camshift算法的实现
Nov 22 Python
TensorFlow2.0矩阵与向量的加减乘实例
Feb 07 Python
Python使用Paramiko控制liunx第三方库
May 20 Python
python 基于PYMYSQL使用MYSQL数据库
Dec 24 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.MVC的模板标签系统(三)
2006/09/05 PHP
上传多个文件的PHP脚本
2006/11/26 PHP
PHP列出MySQL中所有数据库的方法
2015/03/12 PHP
php使用Jpgraph创建柱状图展示年度收支表效果示例
2017/02/15 PHP
加速IE的Javascript document输出的方法
2010/12/02 Javascript
javascript温习的一些笔记 基础常用知识小结
2011/06/22 Javascript
js 得到文件后缀(通过正则实现)
2013/07/08 Javascript
鼠标悬浮停留三秒后自动显示大图js代码
2014/09/09 Javascript
JavaScript中Cookie操作实例
2015/01/09 Javascript
jQuery中选择器的基础使用教程
2016/05/23 Javascript
jQuery实用小技巧_输入框文字获取和失去焦点的简单实例
2016/08/25 Javascript
详解处理bootstrap4不支持远程静态框问题
2018/07/20 Javascript
详解微信小程序自定义组件的实现及数据交互
2019/07/22 Javascript
微信小程序之侧边栏滑动实现过程解析(附完整源码)
2019/08/23 Javascript
vue实现虚拟列表功能的代码
2020/07/28 Javascript
Vue 使用iframe引用html页面实现vue和html页面方法的调用操作
2020/11/16 Javascript
nodejs处理tcp连接的核心流程
2021/02/26 NodeJs
在Django的视图中使用数据库查询的方法
2015/07/16 Python
python爬虫入门教程--利用requests构建知乎API(三)
2017/05/25 Python
Python实现的朴素贝叶斯算法经典示例【测试可用】
2018/06/13 Python
python保存数据到本地文件的方法
2018/06/23 Python
python ftp 按目录结构上传下载的实现代码
2018/09/12 Python
DRF跨域后端解决之django-cors-headers的使用
2019/01/27 Python
pthon贪吃蛇游戏详细代码
2019/01/27 Python
python elasticsearch环境搭建详解
2019/09/02 Python
python 实现矩阵按对角线打印
2019/11/29 Python
python字符串替换re.sub()实例解析
2020/02/09 Python
scrapy中如何设置应用cookies的方法(3种)
2020/09/22 Python
奥地利汽车配件店:Pkwteile.at
2017/03/10 全球购物
LORAC官网:美国彩妆品牌
2019/08/27 全球购物
护理自荐信范文
2013/10/05 职场文书
2014年财政所工作总结
2014/11/22 职场文书
校本培训个人总结
2015/02/28 职场文书
幼儿园重阳节活动总结
2015/05/05 职场文书
周一给客户的问候语
2015/11/10 职场文书
Springboot-cli 开发脚手架,权限认证,附demo演示
2022/04/28 Java/Android