这里有一篇写的不错的:http://www.jianshu.com/p/1840035cb510

自己的“格式化”后的内容备忘下:

  我们总在说c10k的问题, 也做了不少优化, 然后优化总是不够的。

  其中的一个瓶颈就是一些耗时的操作(网络请求/文件操作--含耗时的数据库操作)。

  如果我们不关心他们的返回值,则可以将其做成异步任务,保证执行成功即可。

  

  开始阐述之前约定一些概念:

    1. web请求处理进程(简称:消息生产者,记做P), 这是我们c10k问题注意的焦点

    2. 消息的处理者(简称:消费者,记做C), 在成功“男人”后面默默无闻工作的“女人”  

    3. 消息存放的地方(简称: 消息队列, 记做Q)

    4. 消息/任务, 记做T

基本处理过程:

    1. P将T保存到Q

    2. C从Q中取出一个T实例, 处理, 若处理失败则将T示例退回到Q(务必保证T得到成功处理)。

  

  最简单的实现方案:

    redis 消息队列(利用redis list类型)的lpush/rpop(brpop)来处理。python代码如下:

    TaskServer.py

# -*- coding:utf-8 -*-
import traceback
import simplejson
import redis
import uuid
from functools import wraps class TaskExecutor(object):
def __init__(self, task_name , *args, **kwargs):
self.queue = redis.StrictRedis()#host='localhost', port=6378, db=0, password='xxx_tasks')
self.task_name = task_name def _publish_task(self, task_id , func, *args, **kwargs):
self.queue.lpush(self.task_name,
simplejson.dumps({'id':task_id, 'func':func, 'args':args, 'kwargs':kwargs})
) def task(self, func):#decorator
setattr(func,'delay',lambda *args, **kwargs:self._publish_task(uuid.uuid4().hex, func.__name__, *args, **kwargs))
@wraps(func)
def _w(*args, **kwargs):
return func(*args, **kwargs)
return _w def run(self):
print 'waiting for tasks...'
while True:
if self.queue.llen(self.task_name):
msg_data = simplejson.loads( self.queue.rpop(self.task_name))#这里可以用StrictRedis实例的brpop改善,去掉llen轮询。 print 'handling task(id:{0})...'.format(msg_data['id'])
try:
if msg_data.get('func',None):
func = eval(msg_data.get('func'))
if callable(func):
#print msg_data['args'], msg_data['kwargs']
ret = func(*msg_data['args'], **msg_data['kwargs'])
msg_data.update({'result':ret})
self.queue.lpush(self.task_name+'.response.success', simplejson.dumps(msg_data) )
except:
msg_data.update({'failed_times':msg_data.get('failed_times',0)+1, 'failed_reason':traceback.format_exc()})
if msg_data.get('failed_times',0)<10:#最多失败10次,避免死循环
self.queue.rpush(self.task_name,simplejson.dumps(msg_data))
else:
self.queue.lpush(self.task_name+'.response.failure', simplejson.dumps(msg_data) )
print traceback.format_exc() PingTask = TaskExecutor('PingTask') @PingTask.task
def ping_url(url):
import os
os.system('ping -c 2 '+url) if __name__=='__main__':
PingTask.run()

运行服务:python TaskServer.py  

ps:

    1. TaskExecutor类是一个轻量级的celery.Celery实现。提供了 task修饰器。对被修饰的函数添加delay 方法(将原任务方法名/参数保存到redis的list中--FIFO--实际上celery也是类似的处理

    2. 客户端只要定义自己的TaskExecutor实例以及用此实例的task修饰对应的任务处理函数func。并在代码中待用 func.delay(...)实现异步调用(为了保证成功,最多调用10次); 成功的记录会保存在 redis的 "任务名.response.success" 队列中, 超过10次仍然失败的保存在 “任务名.response.failure"队列中。

    3. 待改进的地方是很多的, 比如多线程, 负载均衡。(尚未阅读celery源码)

  TaskClient.py

# -*- coding:utf-8 -*-
import sys
sys.path.append('./')
from my_tasks import ping_url
ping_url.delay('www.baidu.com')

ps: 客户端和服务器文件在统一linux目录下。

 celery

  试验证明, celery目测大体上跟上面的“基本处理过程”基本一致。即:

  P将T保存在Q中。

  C从Q中取出T处理(保证成功--会不会死循环?执行一个注定失败的任务--就没有验证了)。

  celery的运用比较简单:

    1.安装celery   

    2.编写需要异步执行的任务函数,并用celery实例的task修饰器修饰

    3.调用异步任务时, 用函数名.delay(参数)形式调用为异步调用。 函数名(参数)方式为同步调用。

    4.执行celery监听服务

demo 这里有:http://www.jianshu.com/p/1840035cb510。 再来一个极简的:

    tasks.py   

# -*- coding:utf-8 -*-
from celery import Celery
brokers = 'redis://127.0.0.1:6379/5'
backend = 'redis://127.0.0.1:6379/6' import time app = Celery('tasks', backend=backend, broker=brokers) @app.task
def add(x,y):
time.sleep(10)
return x+y

运行celery监听服务:celery -A tasks worker -l error

    

顺便附上测试代码:tasks_test.py(跟tasks.py同一路径,linux环境)

# -*- coding:utf-8 -*-
import sys
sys.path.append('./')
def test():
from tasks import add
for i in range(1000):
add.delay(i,i+1) if __name__=='__main__':
test()

执行之 : python tasks_test.py

(可以1秒内跑完, 证明的确异步处理了)

顺便查看了下进程,发现celery自动开了一个主进程, 与cpu核数相同的子线程。看了下官方文档,有web监控用的插件(flower)。

安装: sudo pip install flower

运行之(跟tasks.py先同目录): celery -A tasks flower --port=5555

效果图如下(木有发现失败任务--"Failed tasks"---很遗憾):

 flower的基本原理推测是直接查询Q, 并基于结果输出图表等。

ref: https://abhishek-tiwari.com/post/amqp-rabbitmq-and-celery-a-visual-guide-for-dummies

  转载请注明来源:http://www.cnblogs.com/Tommy-Yu/p/5955294.html

  谢谢!

  

celery 原理理解的更多相关文章

  1. JUC回顾之-ConcurrentHashMap源码解读及原理理解

    ConcurrentHashMap结构图如下: ConcurrentHashMap实现类图如下: segment的结构图如下: package concurrentMy.juc_collections ...

  2. POJ1523(割点所确定的连用分量数目,tarjan算法原理理解)

    SPF Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 7406   Accepted: 3363 Description C ...

  3. java的classLoader原理理解和分析

    java的classLoader原理理解和分析 学习了:http://blog.csdn.net/tangkund3218/article/details/50088249 ClassNotFound ...

  4. js 闭包原理理解

    问题?什么是js(JavaScript)的闭包原理,有什么作用? 一.定义 官方解释:闭包是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分. 很显然 ...

  5. kalman filter卡尔曼滤波器- 数学推导和原理理解-----网上讲的比较好的kalman filter和整理、将预测值和观测值融和

    = 参考/转自: 1 ---https://blog.csdn.net/u010720661/article/details/63253509 2----http://www.bzarg.com/p/ ...

  6. debug 调试原理理解

    引言: 昨天,看了一篇文章,很受启发,记得之前听别的人远程调试过代码,觉得很神奇,在自己程序里打断点,连接远程服务器,开启调试后可以调用远程方法来看数据的输入和输出,不需要查找问题,重新部署,测试问题 ...

  7. shiro的原理理解

    1.shiro原理图如下: 框架解释: subject:主体,可以是用户也可以是程序,主体要访问系统,系统需要对主体进行认证.授权. securityManager:安全管理器,主体进行认证和授权都 ...

  8. celery简单理解和使用

    解决同步阻塞的问题 将耗时任务放到后台异步执行,不影响用户其他操作. 实现原理 任务队列是一种跨线程,跨机器的机制. 任务队列中包含称作任务的工作单元.有专门的进程持续不断的监视任务队列,并从中得到新 ...

  9. JAVA 1.7并发之LinkedTransferQueue原理理解

    昨天刚看完BlockingQueue觉得好高级啊,今天扫到1.7就发现了升级版.... 如果对内容觉得不够充分,可以去看http://www.cs.rochester.edu/u/scott/pape ...

随机推荐

  1. test.cpp:(.text+0xc0): undefined reference to `cv::imread(std::string const&, int)'

    opencv报错: test.cpp:(.text+0xc0): undefined reference to `cv::imread(std::string const&, int)' te ...

  2. 在数据库繁忙时如何快速有效的关闭MySQL服务

    如果InnoDB_buffer_size参数很大,缓冲区内的脏数据太多,那么关闭MySQL的时候必须把脏数据刷新到磁盘,这个过程有可能是很漫长的,从而导致关闭MySQL服务的时间过长.可以临时设置in ...

  3. 反向代理WebSocket连接自动断掉的问题

    Nginx可能设置了超时时间,导致WebSocket一会儿就断了 解决方法: 1.增加Nginx配置 proxy_read_timeout 500s; 注:三种超时时间,参见 https://www. ...

  4. XMR恶意挖矿脚本处理笔记

    一.登录 攻击者如何登录系统未能查出,所有日志已被清除.为防万一,把系统中没用的用户都删掉并修改其他用户密码. 二.被攻击后的表象 1.服务器资源被大量占用,资源占用率飙升: 2.服务器所有JS文件被 ...

  5. BCD码干什么用的?

    二进制编码的十进制(Binary Coded Decimal,BCD)数据类型在计算机系统中已经存在很久了.BCD格式经常用于简化对使用十进制数字的设备(比如必须向人显示数字的设备,如时钟和计时器)的 ...

  6. 手把手教你用CAB发布OCX的简单办法

    CAB是一种文件压缩格式,把OCX文件(ActiveX插件)压缩成CAB文件是为了发布它,这种发布方式给人感觉“浏览器会自动安装该插件”,很多朋友钟情于此.目前流行很多压缩工具,但WINRAR这类工具 ...

  7. 〖Android〗我的ADT Eclipse定制

    1. 配置自动补全: Windows -> preferences -> 搜索assist,修改 java xml自动触发补全:.abcdefghijklmnopqrstuvwxyzABC ...

  8. JVM的7种垃圾收集器:主要特点 应用场景 设置参数 基本运行原理

    原文地址:https://blog.csdn.net/tjiyu/article/details/53983650 下面先来了解HotSpot虚拟机中的7种垃圾收集器:Serial.ParNew.Pa ...

  9. PHP 通过带SSL的SMTP 发送邮件的处理

    客户端与SMTP服务器的通讯, 是通过固定的命令以及返回编号完成的. 发送Email, 需要经过的步骤有创建socket (区分带ssl, 还是不带ssl)执行命令, 并检查返回值是否与预期一致, 不 ...

  10. 【阿里巴巴Java开发手册——集合处理】13.集合的稳定性(order)和有序性(sort)

    有序性(sort):指遍历的结果是按照某种比较规则依次排列的. 稳定性(order):指集合每次遍历的元素的次序是一定的. 如:ArrayList是order/unsort HashMap是unord ...