• RabbitMQ 概念


    本文适有一定消息队列基础的,但没有接触过RabbitMQ的快速理解RabbitMQ.



    如果从来没接触过RabbitMQ,那么让我们来设想一个基础的消息队列是怎样的呢?

    //发送方,给一个队列名,就可以将消息发出
    发送(QueueName,msg)


    //接收方,给一个队列名就可以收到消息
    while(true)
    msg=接收(QueueName)


    当然这是基础的点对点的队列,一个消息只被一个接收方消费一次。

    还可以引入订阅机制,每个订阅者将收到一个订阅的完整内容。

    //接收方
    订阅(QueueName)

    //订阅之后,系统会为这个订阅者保留一份消息副本,直到他消费。
    //然后就可以象上面一样开始消息消息
    while(true)
    msg=接收(QueueName)

    每个消息被所有订阅者都消费一次。



    而RabbitMQ则比较复杂,多了大量概念,比如Exchange,Queue,Binding,
    Connection,Channel,broker,virtual host...

    初次接触会觉得很乱,我只是发个消息,为什么要了解这么多呢?

    其实简单梳理一下,就会发现rabbitMQ并没有想象的那么复杂。
    为了快速理解rabbitMQ的基本概念,你只需要关注Exchange,Queue,Binding。
    其它概念都是具体编程时的细节,都可以放一放。

    Exchange主要有三种类型direct,fanout,topic。也只要关注topic就可以了,
    因为另外两类其实是topic的特例。

    Queue,有一个唯一的名字,是一个标准的先进先出队列,而且每个队列中的消息只会被消费一次。

    Binding则是描述exchange和queue之间的关系,之所以消息不直接发送到queue而是通过
    exchange中转,并再由exchange和queue之间关系来决定最终消息投放到一个或多个队列,
    甚至包括直接丢弃消息,仅仅是为了更方便的适合各种使用场景而已。

    exchange和queue可以Bingding一个key,也就是首先连接了两者并且再定义了连接的类型(关系)。
    而每个消息发送时也可以指定一个消息的routing_key。

    比如我们可以让一个exchange和如下三个queue绑定
    1.queue1,绑定key=#,所有exchange收到的消息都将转发给这个queue
    2.queue2,绑定key=abc.def,只有routing_key=abc.def的消息才会转发到此queue。
    3.queue3,绑定key=abc.*,转发所有routing_key为abc开头,且有两个字的消息。

    可以想象,如果没有这样的绑定机制,要实现这三个队列,
    就要求消息发送方根据情况多次发送同一个消息到对应的队列。
    这正是RabbitMQ引入exchange来解决此类问题的方式。


    关于绑定key通配符的进一步说明:
    1.字是用.分隔的;a.b.c包含三个字,abc包含一个字
    2.*代表任意一个字;a.*匹配a.b和a.c和a.d但不匹配a和a.b.c
    3.#代表任意多个字;a.#匹配a和a.b和a.b.c。


    Exchange direct类型是topic的一种特例,绑定关系只能是明确的不包含通配符的key,
    而fanout类型则是忽略key,将所有消息转发给与他连接的queue。

    一般情况下,发送时要指定一个exchange和消息的routing_key,
    特例是,不指定exchange时,就用全局默认的direct类型exchange,
    这样消息就只通过routing_key来决定投递到那个队列
    (可以认为每个queue实际都是和全局direct exchage通过queue名字绑定的),
    这实际就是我们最开始假想的标准消息队列。

    通过增加更多其他exchange,在rabbitMQ内可以规划相互隔离或者相互交织的转发网络。
    并且还可通过增加vhost,让用户感觉面对多个独立的rabbitMQ,来实现强隔离。

    broker则指整个rabbitMQ,他可以包含多个vhost,客户端首先通过Connection连接到其中一个vhost,
    比如IP+端口,为了复用连接,rabbitMQ再增加了Channel概念,在一个连接上可以同时并发多个Channel(类似会话),
    channel仅仅是实现细节并不涉及具体概念,比如没有channel的话,rabbitMQ大可直接用连接与客户端交互
    (这样可能要打开大量连接),类似mysql这种方式。


    所以即便你从来没接触过rabbitMQ,现在也能大概知道如何用了。
    伪码如下:

    //发送

    //打开连接
    con=rabbitMQ.getConn(ip=,port=)

    //打开channel
    ch=con.getChannel()

    //delivery_mode=2消息需要持久,不持久的话性能高,但是一旦崩溃会丢消息
    ch.send(exchange=,routing_key=,msg=,delivery_mode=)

    //关闭连接,实际可以只关闭channel而始终保持长连接
    con.close()


    //接收
    con=rabbitMQ.getConn(ip=,port=)
    ch=con.getChannel()

    //接收时只需要指定queue,可选的是是否需要明确确认消息,
    //不需要确认的话,消息一读,rabbitMQ就删除了,处理错误也不会再有机会了,
    //当然这样性能更高
    msg=ch.recive(queue=,no_ack=)

    //处理消息
    ...

    //确认处理完消息,确认后rabbitMQ就会删除对应消息
    ch.ack(msg.id)
    con.close()


    好了,增加了消息是否需要持久,以及消息的确认,
    每种语言有不同的API客户端,总体处理方式都是类似的。

    上述代码没有包括建立exchange和queue,以及他们之间绑定的代码,
    我们可以简单认为,这部分是通过其他方式另外定义的,对于收发客户端,
    实际就只要提供上面这些参数就足够了。


    这样看来RabbitMQ是不是很清晰简单?


    当然rabbitMQ还包括一些其他的功能,比如RPC等,这类无非就是发送时指定更多参数罢了。

  • 相关阅读:
    Ext JS 6学习文档-第5章-表格组件(grid)
    Ext JS 6学习文档-第4章-数据包
    Ext JS 6学习文档-第3章-基础组件
    Ext JS 6学习文档–第2章–核心概念
    Ext JS 6学习文档–第1章–ExtJS入门指南
    Console命令详解,让调试js代码变得更简单
    使用Node.js+Socket.IO搭建WebSocket实时应用
    node.js应用--转载
    Node.js 究竟是什么?
    Hello, Unity!
  • 原文地址:https://www.cnblogs.com/xmanblue/p/5910171.html
Copyright © 2020-2023  润新知