2011 06-12-why do we need the rabbit
Upcoming SlideShare
Loading in...5
×
 

2011 06-12-why do we need the rabbit

on

  • 7,217 views

 

Statistics

Views

Total Views
7,217
Views on SlideShare
3,025
Embed Views
4,192

Actions

Likes
9
Downloads
126
Comments
0

18 Embeds 4,192

http://www.thinkinlamp.com 2165
http://blog.thinkinlamp.com 1020
http://simple-is-better.com 300
http://thinkinlamp.com 281
http://www.webguo.com 216
http://blog.haohtml.com 123
http://blog.bypat.com 34
url_unknown 20
http://cache.baidu.com 19
http://www.simple-is-better.com 3
http://pythontip.sinaapp.com 3
http://www.slideshare.net 2
http://ctc.qzs.qq.com 1
http://xianguo.com 1
http://www.thinkinlamp.com HTTP 1
http://blog.thinkinlamp.com HTTP 1
http://www.tuicool.com 1
http://www.pythontip.com 1
More...

Accessibility

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

2011 06-12-why do we need the rabbit 2011 06-12-why do we need the rabbit Presentation Transcript

  • 消息队列服务在虎扑的应用 --- 使用异步和队列解决 web 开发中的问题
    • 关于虎扑
      • 可能是国内最棒的体育社区
      • 旗下有虎扑 ( 篮球 ), goalhi( 足球 ), 亮乐 ( 综合体育 ),HelloF1, 卡路里 ( 商城 ) 等网站
      • alexa 中国前百强
      • PV 8 千万 / 天
    • 关于我
      • ID: 轩痕
      • mail: wpcworkstation@gmail.com
      • 后端开发 , 最近正纠结于 twisted
      • 喜欢 python,linux
    • 话题预览 :
    • 1 我们为什么需要消息队列 ?
    • 2 理想的消息队列需要具有哪些特性 ?
    • 3 高级消息队列的模型
  • 我们为什么需要消息队列
    • 虎扑微博的业务情况
      • 如果一个体育明星用户有一万个人关注
      • 每条状态 会产生 一万条数据库 插入需求
      • 世纪大战
      • 高峰时每秒成千上万条插入任务
  •  
    • 遇到的问题 :
    • 状态丢失
    • 502 错误
    • mysql 服务器压力很大
    • 解决方案 :
    • 1 加入新的 mysql 服务器 , 一个库 , 一张表 , 简易队列化
        • 表结构 id server_id sql_statement
      • 2 去掉插入速度的约束
      • 3 不在这个数据库上进行不必要的查询和修改操作
  • 优化的结果
    • 状态不丢了
    • 502 也没有了
    • 但这样做有没有弊端呢 ?
    • 弊端 :
      • 入队速度还不理想 , 因为要写硬盘
      • 数据必须持久化 , 无法选择
      • 后端的处理线程需要一直去取数据 , 取的频率不好确定
  • SMS
    • 线下约战
      • 队长要通过我们的 web 系统以短信的方式通知队员约定的比赛时间 , 场地信息
      • 队长发起约战请求的时候可不希望页面卡在那里半天没反应
      • 但是发送短信却需要一定时间的阻塞
  • 这里会有什么问题 ?
    • 弊端 :
    • 1 多线程时会出现一条消息被多次取的问题
    • 2 需要线程定时到队列查询
    • 期望的特性 :
    • 1 消息一旦被取走 , 就不能被别的线程再获取
    • 2 如果那些消费线程能够在有消息到来的时候再来取 , 或许是个不错的事情
  • Google 分析
  • 假如 假如有这样一个服务器放在我面前 .... 它有非常快的消息进出速度 可以从容地处理成千上万的并发 还能很容易地控制数据是否持久化 有消息来的时候会主动推送给消费线程 消息一旦被某消费者取走 , 其他消费者 就无法再取这条消息 ...
  •  
    • 这个理想中的消息队列服务器叫什么名字
    • 1 rabbitmq 是 AMQP 的一个实现
    • 2 完全开源
    • 3 开发语言是 erlang
    • 4 非常高的可靠性
  • 关于 erlang
    • Erlang 是一门被设计用于编写高并发、软实时、分布式系统的语言。
  • AMQP
    • 高级消息队列协议 (Advanced Message Queuing Protocol)
    • 完全的开放协议
    • 给力的互操作性
    • AMQP 模型
  • AMQP 模型
    • Exchanges( 交换机 )
    • Message Queues( 消息队列 )
    • Bindings ( 交换机 和 队列 的绑定 )
    • message( 消息 )
  • http://docs.redhat.com/docs/en-US/Red_Hat_Enterprise_MRG/1.1/html/Messaging_User_Guide/sect-Messaging_User_Guide-Introduction_to_RHM-The_AMQP_0_10_Model.html
  • (exchange) 交换机的分发机制
    • Direct( 直接传递 )
    • Fanout( 广播 )
    • Topic( 话题的形式 , 依赖于通配符 )
  • Direct Exchange
  • Fanout Exchange
  • Topic Exchange
    • 当消息都进入了队列 , 接下来让我们讲讲队列吧
  • 传统的队列末端消费模式
  • AMQP 模式下的消息处理模式
  • 队列本身的特性
    • 可以被设置为持久化
    • 队列需要与交换机绑定 , 然后从交换机接受消息 , 并且和交换机的持久性保持一致 , 不能一个持久 , 一个非持久
    • 如果被设置为私有的 , 只有声明它的消费者才可以从这个队列拿走消息
  • 消息
    • 分为两类 :
      • 消息量很大 , 而且并不怎么重要的 , 可以只放在内存中 , 不做持久化 , 不开启 ack
      • 消息量不大 , 很重要的 , 可以设置为持久化 , 开启 ack
  • AMQP 的其他实现
    • OpenAMQ
    • Apache ActiveMQ
    • ZeroMQ
    • AMQP Infrastructure
  • 使用客户端同 rabbitmq 交流 1 支持很多语言的客户端 . c,c++,php, java, ruby,python,erlang 等 2 基于 Python 的库 . pika, txamqp,celery 等等 ..
    • 连接
    • 1 阻塞式的连接
    • from pika.adapters import BlockingConnection
    • connection = BlockingConnection()
    • 2 非阻塞式的连接
    • import select_connection
    • select_connection.POLLER_TYPE = 'epoll'
    • connection = select_connection.SelectConnection()
  • 创建 队列 , 交换机 , 绑定
    • 在物理连接的基础上创建一个逻辑通道
    • channel = connection.channel()
    • 由逻辑通道来声明交换机和队列
    • channel. exchange _declare(exchange='direct_logs', type='direct')
    • result = channel. queue _declare(exclusive=True)
    • 创建交换机和队列的绑定
    • channel. queue _ bind ( exchange ='direct_logs', queue =queue_name,
    • routing_key= severity )
    • 准备工作做好了 , 我在哪里处理消息呢 ?
  • 按照业务进行消费
    • def callback (ch, method, properties, body):
    • print " [x] %r:%r" % (method.routing_key, body,)
    • print ' 我这里可以处理一些业务 '
    • 另一个绑定 :
      • 在队列的尾端绑定一个业务回调
    • channel.basic_ consume ( callback ,
    • queue =queue_name,
    • no_ack =True)
    • 如果处理消息时除了差错 , 而我又不想让这条消息丢失 .
    • 怎么办 ?
  • 处理消息时的分支
    • 1 设置 no_ack = False
    • channel. basic_consume (callback,queue=queue_name, no_ack = False )
    • 告诉兔子我处理完消息会给你反馈的
    • 2 如果消息被成功处理 , 使用
    • channel.basic_ack(method. delivery_tag )
    • 3 如果处理消息发生了异常 , 在异常处理的代码里面使用
    • channel.basic_reject(method. delivery_tag )
    • 让消息重回队列 , 避免丢失
    • 消息的处理速度不够快怎么办 ?
            • 多线程
    • 猜想 :
    • 假如队列里面有一万条消息 , 我们开启了一百个线程进行处理 , 每个线程能分配到多少条消息 ?
    • 控制每个消费者最大被分配的消息量
      • channel.basic_qos( prefetch_count =1)
    • 处理任务的时间过长 , 会被兔子认为执行超时 , 并把任务分给别的消费者吗 ?
    • 消费者挂了怎么办 ? 消息还在吗 ?