在tornado中使用celery实现异步任务处理之二

来源:互联网 发布:samorost mac 编辑:程序博客网 时间:2024/06/06 01:31

三、tornado结合RabbitMQ实现异步任务处理

3.1 安装环境

1. 安装tornado
见文章《CentOS6.4安装python2.7.3环境和Tornado》

2. 安装 tornoda-celery
tornado-celery的安装很简单:
$ pip install tornado-celery
Downloading/unpacking tornado-celery
  Downloading tornado-celery-0.3.4.tar.gz
  Running setup.py egg_info for package tornado-celery 
... 
Successfully installed tornado-celery celery pika pytz billiard kombu anyjson amqp
Cleaning up...


3. 安装 RabbitMQ
使用celery需要选择一种broker(中间人)进行消息的接受和发送,中间人通常作为一种独立的服务,
常用的broker又RabbitMQ、Redis以及MongoDB等。
RabbitMQ 是AMPQ高级消息队列协议的实现,是使用最广泛的消息系统,
因为tornado-celery中使用redis无法使用callback,建议使用RabbitMQ作为broker。


安装并启动RabbitMQ
MAC上使用brew安装该服务程序
$ brew install rabbitmq


启动rabbitmq-server
$ sudo rabbitmq-server -detached


准备工作完成后就可以编码了

3.2. 示例程序

1. 创建并运行tasks.py
celery = Celery('tasks', broker='amqp://')
celery.conf.CELERY_RESULT_BACKEND = os.environ.get('CELERY_RESULT_BACKEND', 'amqp')


@celery.task(name='task.query_users')
def query_users(admin_id):
    # 耗时的数据库操作
    return db.query_all_users(admin_id)


2. 运行tasks.py
$ python tasks.py worker --loglevel=info


3. 创建tornado的 handler
    import tcelery
    tcelery.setup_nonblocking_producer()


    from tasks import query_users
    
    calss Users(RequestHandler):
        @asynchronous
        def get():
            # 参数通过args的list传递,回调通过callback指定
            query_users.apply_async(args=[admin_id], callback=self.on_success)
        def on_success(self, response):
            # 获取返回的结果
            users = response.result
            self.write(users)
            self.finish()
这样,query_users的请求就变成异步非阻塞的了,
同理,其他的耗时操作可以放到task中供tornado的请求调用。


四、使用AMQP和tornado实现异步任务处理

1. 安装AMQP


2. 创建 tasks.py


3. 运行 tasks.py


4. 创建Handler
在Tornado的RequestHandler中调用celery的任务:


from tornado import gen, web
import tcelery, tasks


tcelery.setup_nonblocking_producer()


class AsyncHandler(web.RequestHandler):
    @asynchronous
    def get(self):
        tasks.echo.apply_async(args=['Hello world!'], callback=self.on_result)


    def on_result(self, response):
        self.write(str(response.result))
        self.finish()


使用generator-based 接口调用任务:
class GenAsyncHandler(web.RequestHandler):
    @asynchronous
    @gen.coroutine
    def get(self):
        response = yield gen.Task(tasks.sleep.apply_async, args=[3])
        self.write(str(response.result))
        self.finish()




NOTE: 当前的回调函数只能在 AMQP和 Redis后台下工作,
如果要使用Redis后台,必须安装 tornado-redis.


5. 运行测试用例
上面的测试用例要在AMQP后台下运行:
$ python examples/tasks.py worker
$ cd examples && python -m tcelery -A tasks
$ python tests/functests.py


要让上面的测试用例在Redis后台下运行,需要首先确认redis已经在运行,
然后:
$ CELERY_RESULT_BACKEND=redis:// python examples/tasks.py worker
$ cd examples && CELERY_RESULT_BACKEND=redis:// python -m tcelery -A tasks
$ python tests/functests.py


五、以web server的方式加载tornado-celery
$ cd tornado-celery
$ python -m tcelery --port=8888 --app=examples.tasks --address=0.0.0.0


异步的方式执行一个任务:
$ curl -X POST -d '{"args":["hello"]}' http://localhost:8888/apply-async/examples.tasks.echo/
{"task-id": "a24c9e38-4976-426a-83d6-6b10b4de7ab1", "state": "PENDING"}


获得上面任务执行的结果:
$ curl http://localhost:8888/tasks/result/a24c9e38-4976-426a-83d6-6b10b4de7ab1/
{"task-id": "a24c9e38-4976-426a-83d6-6b10b4de7ab1", "state": "SUCCESS", "result": "hello"}


执行一个任务并获得它的结果:
$ curl -X POST -d '{"args":[1,2]}' http://localhost:8888/apply/examples.tasks.add/
{"task-id": "fe3cc5a5-d11b-4b17-a6e2-e7fd2fba7ec6", "state": "SUCCESS", "result": 3}


执行一个任务并设置它的超时:
$ curl -X POST -d '{"args":[5],"timeout":1}' http://localhost:8888/apply/examples.tasks.sleep/
{"task-id": "9ca78e26-bbb2-404c-b3bb-bc1c63cbdf41", "state": "REVOKED"}

六、API文档

1. POST /apply-async/(.*)/
通过发送消息来应用异步任务


请求示例:
POST /apply-async/examples.tasks.add/ HTTP/1.1
Accept: application/json
Accept-Encoding: gzip, deflate, compress
Content-Length: 16
Content-Type: application/json; charset=utf-8
Host: localhost:8888
User-Agent: HTTPie/0.8.0


{
    "args": [
        1,
        2
    ]
}


响应示例:
HTTP/1.1 200 OK
Content-Length: 71
Content-Type: application/json; charset=UTF-8
Server: TornadoServer/3.2


{
    "state": "PENDING",
    "task-id": "1c9be31f-3094-4319-8895-ad2f0654c699"
}
Status Codes: 
200 – no error
400 – invalid request
404 – unknown task


2. GET /tasks/result/(.*)/
通过task-id获得任务结果 


请求示例:
GET /tasks/result/9ec42ba0-be59-488f-a445-4a007d83b954/ HTTP/1.1
Accept: application/json
Accept-Encoding: gzip, deflate, compress
Content-Type: application/json; charset=utf-8
Host: localhost:8888
User-Agent: HTTPie/0.8.0


响应示例:
HTTP/1.1 200 OK
Content-Length: 84
Content-Type: application/json; charset=UTF-8
Etag: "0aef8448588cf040f1daa7a0244c0a7b93abfd71"
Server: TornadoServer/3.2


{
    "result": 3,
    "state": "SUCCESS",
    "task-id": "9ec42ba0-be59-488f-a445-4a007d83b954"
}
Status Codes: 
200 – no error
400 – invalid request


3. DELETE /tasks/revoke/(.*)/
移除一个任务


请求示例:
DELETE /tasks/revoke/d776e835-33ac-447f-b27d-bb8529718ae6/ HTTP/1.1
Accept: application/json
Accept-Encoding: gzip, deflate, compress
Content-Length: 0
Content-Type: application/json; charset=utf-8
Host: localhost:8888
User-Agent: HTTPie/0.8.0


响应示例:
HTTP/1.1 200 OK
Content-Length: 51
Content-Type: application/json; charset=UTF-8
Server: TornadoServer/3.2


{
    "task-id": "d776e835-33ac-447f-b27d-bb8529718ae6"
}
Status Codes: 
200 – no error
400 – invalid request


4. POST /apply/(.*)/
同步方式调用任务,当任务结束时函数返回


请求示例:
POST /apply/examples.tasks.add/ HTTP/1.1
Accept: application/json
Accept-Encoding: gzip, deflate, compress
Content-Length: 16
Content-Type: application/json; charset=utf-8
Host: localhost:8888
User-Agent: HTTPie/0.8.0


{
    "args": [
        1,
        2
    ]
}


响应示例:
HTTP/1.1 200 OK
Content-Length: 84
Content-Type: application/json; charset=UTF-8
Server: TornadoServer/3.2


{
    "result": 3,
    "state": "SUCCESS",
    "task-id": "2ce70595-a028-4e0d-b906-be2183fc6821"
}
Status Codes: 
200 – no error
400 – invalid request
404 – unknown task

1 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 三星s6的通知栏拉不下来怎么办 电脑记住密码打不开了怎么办 联想手机升级系统失败了怎么办 日本语言学校申请研究生签证怎么办 在埃塞俄比亚签证过期了怎么办 看完的小说想要卖掉该怎么办 在俄罗斯脸干了痛怎么办 苹果手表电池放亏了怎么办 平板电脑电池不耐用怎么办 计算机电池放入后没反应怎么办 笔记本电脑玩游戏花屏怎么办 笔记本玩游戏花屏怎么办 笔记本电脑充电插口坏了怎么办 车蓄电池没电了怎么办 汤浅q85电瓶亏电怎么办 富士康自离行李怎么办 微店红酒食品认证怎么办 yy频道提示禁止游客进入怎么办 口红颜色太艳了怎么办 我在菲律宾想走怎么办 当国家流通货币不够用怎么办 苹果5s账号密码忘记怎么办 钢铁雄心3补给不足怎么办 灯外观颜色太难看了怎么办 被移民公司骗了怎么办 文明5大包锁区怎么办 鸭子被黄鼠狼叼走了怎么办 黄鼠狼再店了拉屎怎么办 我只有信用卡但是又想去嫖怎么办 瑞士退税单掉了怎么办 装了新风噪音大怎么办 意大利 护照被偷了怎么办 请问去意大利要怎么办护照 在意大利护照丢了怎么办 考研二战档案打回原籍怎么办 脸上的肉往下掉怎么办 眼镜带了往下掉怎么办 孩子捅别的孩子眼睛了怎么办 眼睛不小心捅伤怎么办 我的爸爸是小偷怎么办 违停罚款忘记交怎么办