05_RabbitMQ 的CLI管理工具 rabbitmqadmin

原文地址 http://soft.dog/2016/04/20/RabbitMQ-cli-rabbitmqadmin/

一、前言

RabbitMQ 是一个使用 Erlang 编写的开源消息队列中间件,被广泛使用在各种应用场景中

一般对于它的监控和管理可以通过web来完成,详细可以参考 RabbitMQ 监控

但生产环境中经常没有访问web管理界面的条件,只提供了CLI界面,或者有些自动化的需求通过web界面无法完成,这时有没有一种直接在CLI环境下进行管理的方法呢,官方提供的 rabbitmqadmin 命令正好可以满足这类需求

对于运维来说,个人感觉更倾向使用CLI的方式,因为虽然web的界面更友好,但是明显不如CLI快捷,CLI也可以结合其它命令进行更进一步的处理,比如将关键信息查出来后提供给集中的监控系统以触发报警

目前 rabbitmqadmin 可以完成以下任务:

  • 列出 exchanges, queues, bindings, vhosts, users, permissions, connections and channels
  • 看到汇总信息
  • 申明和清除 exchanges, queues, bindings, vhosts, users and permissions
  • 发布和获取消息
  • 关闭连接和清空队列
  • 导入导出配置

这里分享一下 rabbitmqadmin 的基本操作,详细可以参考 http://www.rabbitmq.com/management-cli.html

二、RabbitMQ的安装

RabbitMQ的安装请参考我的另一篇总结01_RabbitMQ的安装

三、rabbitmqadmin

在web UI管理界面中,的 /cli/ 下可以下载此脚本:

1.png

点击【here】会呈现脚本内容:

2.png

右键另存为下载即可。默认名称为rabbitmqadmin。

但是有些情况下,并没条件使用Web UI,使用下面的方法一样可以获取这个脚本:

[root@h102 rabbitmq]# wget http://localhost:15672/cli/rabbitmqadmin
--2016-04-18 19:47:50--  http://localhost:15672/cli/rabbitmqadmin
Resolving localhost... ::1, 127.0.0.1
Connecting to localhost|::1|:15672... failed: Connection refused.
Connecting to localhost|127.0.0.1|:15672... connected.
HTTP request sent, awaiting response... 200 OK
Length: 34504 (34K) [text/plain]
Saving to: “rabbitmqadmin”

100%[===================================================================================================>] 34,504      --.-K/s   in 0s      

2016-04-18 19:47:50 (155 MB/s) - “rabbitmqadmin” saved [34504/34504]

[root@h102 rabbitmq]# ll rabbitmqadmin 
-rw-r--r-- 1 root root 34504 Apr 18 19:29 rabbitmqadmin
[root@h102 rabbitmq]# file rabbitmqadmin 
rabbitmqadmin: a /usr/bin/env python script text executable
[root@h102 rabbitmq]# 
[root@h102 rabbitmq]# chmod  +x rabbitmqadmin 
[root@h102 rabbitmq]# ./rabbitmqadmin --help 
Usage
=====
  rabbitmqadmin [options] subcommand

Options
=======
--help, -h              show this help message and exit
--config=CONFIG, -c CONFIG
                        configuration file [default: ~/.rabbitmqadmin.conf]
--node=NODE, -N NODE    node described in the configuration file [default:
                        'default' only if configuration file is specified]
--host=HOST, -H HOST    connect to host HOST [default: localhost]
--port=PORT, -P PORT    connect to port PORT [default: 15672]
--path-prefix=PATH_PREFIX
                        use specific URI path prefix for the RabbitMQ HTTP API
                        (default: blank string) [default: ]
--vhost=VHOST, -V VHOST
                        connect to vhost VHOST [default: all vhosts for list,
                        '/' for declare]
--username=USERNAME, -u USERNAME
                        connect using username USERNAME [default: guest]
--password=PASSWORD, -p PASSWORD
                        connect using password PASSWORD [default: guest]
--quiet, -q             suppress status messages [default: True]
--ssl, -s               connect with ssl [default: False]
--ssl-key-file=SSL_KEY_FILE
                        PEM format key file for SSL
--ssl-cert-file=SSL_CERT_FILE
                        PEM format certificate file for SSL
--format=FORMAT, -f FORMAT
                        format for listing commands - one of [raw_json, long,
                        pretty_json, kvp, tsv, table, bash] [default: table]
--sort=SORT, -S SORT    sort key for listing queries
--sort-reverse, -R      reverse the sort order
--depth=DEPTH, -d DEPTH
                        maximum depth to recurse for listing tables [default:
                        1]
--bash-completion       Print bash completion script [default: False]
--version               Display version and exit

More Help
=========

For more help use the help subcommand:

  rabbitmqadmin help subcommands  # For a list of available subcommands
  rabbitmqadmin help config       # For help with the configuration file
[root@h102 rabbitmq]# 

以上已经拿到了rabbitmqadmin这个python脚本并设置为可执行,接下来设置为全局可执行命令。

[root@h102 rabbitmq]# vim /etc/profile

将该脚本所在目录,其添加到/etc/profile中即可。

PATH后面是所在目录:
export PATH=$PATH:/usr/local/server/rabbitmq/

保存退出,让该设置立即生效:

[root@h102 rabbitmq]# source /etc/profile 

四、基础概念

4.1 架构

Producer、Exchange、Binding、Queue、Consumer 之间的关系:

3.png

Routing Key、Binding Key、Exchange Type 的关系:

4.png

4.2 概念

5.png

4.3 投递过程

消息队列的使用过程大概如下:

  1. 客户端连接到消息队列服务器,打开一个channel
  2. 客户端声明一个exchange,并设置相关属性
  3. 客户端声明一个queue,并设置相关属性
  4. 客户端使用routing key,在exchange和queue之间建立好绑定关系
  5. 客户端投递消息到exchange
  6. 客户端从指定的queue中消费信息

五、rabbitmqadmin 用法

[root@h102 rabbitmq]# rabbitmqadmin --help 
Usage
=====
  rabbitmqadmin [options] subcommand

Options
=======
--help, -h              show this help message and exit
--config=CONFIG, -c CONFIG
                        configuration file [default: ~/.rabbitmqadmin.conf]
--node=NODE, -N NODE    node described in the configuration file [default:
                        'default' only if configuration file is specified]
--host=HOST, -H HOST    connect to host HOST [default: localhost]
--port=PORT, -P PORT    connect to port PORT [default: 15672]
--path-prefix=PATH_PREFIX
                        use specific URI path prefix for the RabbitMQ HTTP API
                        (default: blank string) [default: ]
--vhost=VHOST, -V VHOST
                        connect to vhost VHOST [default: all vhosts for list,
                        '/' for declare]
--username=USERNAME, -u USERNAME
                        connect using username USERNAME [default: guest]
--password=PASSWORD, -p PASSWORD
                        connect using password PASSWORD [default: guest]
--quiet, -q             suppress status messages [default: True]
--ssl, -s               connect with ssl [default: False]
--ssl-key-file=SSL_KEY_FILE
                        PEM format key file for SSL
--ssl-cert-file=SSL_CERT_FILE
                        PEM format certificate file for SSL
--format=FORMAT, -f FORMAT
                        format for listing commands - one of [raw_json, long,
                        pretty_json, kvp, tsv, table, bash] [default: table]
--sort=SORT, -S SORT    sort key for listing queries
--sort-reverse, -R      reverse the sort order
--depth=DEPTH, -d DEPTH
                        maximum depth to recurse for listing tables [default:
                        1]
--bash-completion       Print bash completion script [default: False]
--version               Display version and exit

More Help
=========

For more help use the help subcommand:

  rabbitmqadmin help subcommands  # For a list of available subcommands
  rabbitmqadmin help config       # For help with the configuration file
[root@h102 rabbitmq]# rabbitmqadmin help subcommands
Usage
=====
  rabbitmqadmin [options] subcommand

  where subcommand is one of:

Display
=======

  list users [<column>...]
  list vhosts [<column>...]
  list connections [<column>...]
  list exchanges [<column>...]
  list bindings [<column>...]
  list permissions [<column>...]
  list channels [<column>...]
  list parameters [<column>...]
  list consumers [<column>...]
  list queues [<column>...]
  list policies [<column>...]
  list nodes [<column>...]
  show overview [<column>...]

Object Manipulation
===================

  declare queue name=... [node=... auto_delete=... durable=... arguments=...]
  declare vhost name=... [tracing=...]
  declare user name=... password=... tags=...
  declare exchange name=... type=... [auto_delete=... internal=... durable=... arguments=...]
  declare policy name=... pattern=... definition=... [priority=... apply-to=...]
  declare parameter component=... name=... value=...
  declare permission vhost=... user=... configure=... write=... read=...
  declare binding source=... destination=... [arguments=... routing_key=... destination_type=...]
  delete queue name=...
  delete vhost name=...
  delete user name=...
  delete exchange name=...
  delete policy name=...
  delete parameter component=... name=...
  delete permission vhost=... user=...
  delete binding source=... destination_type=... destination=... properties_key=...
  close connection name=...
  purge queue name=...

Broker Definitions
==================

  export <file>
  import <file>

Publishing and Consuming
========================

  publish routing_key=... [exchange=... payload=... payload_encoding=... properties=...]
  get queue=... [count=... requeue=... payload_file=... encoding=...]

  * If payload is not specified on publish, standard input is used

  * If payload_file is not specified on get, the payload will be shown on
    standard output along with the message metadata

  * If payload_file is specified on get, count must not be set

[root@h102 rabbitmq]# rabbitmqadmin help config
Usage
=====
rabbitmqadmin [options] subcommand

Configuration File
==================

  It is possible to specify a configuration file from the command line.
  Hosts can be configured easily in a configuration file and called
  from the command line.

Example
=======

  # rabbitmqadmin.conf.example START

  [host_normal]
  hostname = localhost
  port = 15672
  username = guest
  password = guest
  declare_vhost = / # Used as default for declare / delete only
  vhost = /         # Used as default for declare / delete / list

  [host_ssl]
  hostname = otherhost
  port = 15672
  username = guest
  password = guest
  ssl = True
  ssl_key_file = /path/to/key.pem
  ssl_cert_file = /path/to/cert.pem

  # rabbitmqadmin.conf.example END

Use
===

  rabbitmqadmin -c rabbitmqadmin.conf.example -N host_normal ...

5.1 查询

5.1.1 查看 users
[root@h102 rabbitmq]# rabbitmqadmin list users
+-------+-----------------------------+------------------------------+---------------+
| name  |      hashing_algorithm      |        password_hash         |     tags      |
+-------+-----------------------------+------------------------------+---------------+
| guest | rabbit_password_hashing_md5 | 7jG486YR6/F0hVLWYfCnqRyxKe4= | administrator |
| test  | rabbit_password_hashing_md5 | /iSnvCNZ5m3kvqoqqH4U3dSEqTM= | administrator |
+-------+-----------------------------+------------------------------+---------------+
[root@h102 rabbitmq]# rabbitmqadmin list users name
+-------+
| name  |
+-------+
| guest |
| test  |
+-------+
[root@h102 rabbitmq]# rabbitmqadmin list users tags
+---------------+
|     tags      |
+---------------+
| administrator |
| administrator |
+---------------+
[root@h102 rabbitmq]#
5.1.2 查看 vhosts
[root@h102 rabbitmq]# rabbitmqadmin list vhosts
+------+----------+
| name | messages |
+------+----------+
| /    | 13       |
+------+----------+
5.1.3 查看 connections
[root@h102 rabbitmq]# rabbitmqadmin list connections
No items
5.1.4 查看 exchanges
[root@h102 rabbitmq]# rabbitmqadmin list exchanges
+--------------------+---------+
|        name        |  type   |
+--------------------+---------+
|                    | direct  |
| amq.direct         | direct  |
| amq.fanout         | fanout  |
| amq.headers        | headers |
| amq.match          | headers |
| amq.rabbitmq.log   | topic   |
| amq.rabbitmq.trace | topic   |
| amq.topic          | topic   |
| kk                 | fanout  |
| test               | fanout  |
+--------------------+---------+
5.1.5 查看 bindings
[root@h102 rabbitmq]# rabbitmqadmin list bindings
+--------+-------------+-------------+
| source | destination | routing_key |
+--------+-------------+-------------+
|        | hello       | hello       |
|        | test        | test        |
| kk     | hello       | hello       |
| kk     | test        | test        |
+--------+-------------+-------------+
5.1.6 查看 permissions
[root@h102 rabbitmq]# rabbitmqadmin list permissions
+-------+-----------+------+-------+-------+
| vhost | configure | read | user  | write |
+-------+-----------+------+-------+-------+
| /     | .*        | .*   | guest | .*    |
+-------+-----------+------+-------+-------+
[root@h102 rabbitmq]# rabbitmqadmin list permissions read
+------+
| read |
+------+
| .*   |
+------+
5.1.7 查看 channels
[root@h102 rabbitmq]# rabbitmqadmin list channels
No items
5.1.8 查看 consumers
[root@h102 rabbitmq]# rabbitmqadmin list consumers
No items
5.1.9 查看 queues
[root@h102 rabbitmq]# rabbitmqadmin list queues
+-------+----------+
| name  | messages |
+-------+----------+
| hello | 8        |
| test  | 5        |
+-------+----------+
5.1.10 查看 查看 policies
[root@h102 rabbitmq]# rabbitmqadmin list policies
No items
5.1.11 查看 nodes
[root@h102 rabbitmq]# rabbitmqadmin list nodes
+-------------+------+----------+
|    name     | type | mem_used |
+-------------+------+----------+
| rabbit@h102 | disc | 52274376 |

+-------------+------+----------+

5.1.12 查看 overview
[root@h102 rabbitmq]# rabbitmqadmin show overview
+------------------+------------------+-----------------------+----------------------+
| rabbitmq_version |   cluster_name   | queue_totals.messages | object_totals.queues |
+------------------+------------------+-----------------------+----------------------+
| 3.6.1            | rabbit@h101.temp | 13                    | 2                    |
+------------------+------------------+-----------------------+----------------------+

5.2 删除

5.2.1 删除 queue
[root@h102 rabbitmq]# rabbitmqadmin list queues
+-------+----------+
| name  | messages |
+-------+----------+
| hello | 8        |
| test  | 5        |
+-------+----------+
[root@h102 rabbitmq]# rabbitmqadmin delete queue name=hello
queue deleted
[root@h102 rabbitmq]# rabbitmqadmin list queues
+------+----------+
| name | messages |
+------+----------+
| test | 5        |
+------+----------+
5.2.2 删除 user
[root@h102 rabbitmq]# rabbitmqadmin list users
+-------+-----------------------------+------------------------------+---------------+
| name  |      hashing_algorithm      |        password_hash         |     tags      |
+-------+-----------------------------+------------------------------+---------------+
| guest | rabbit_password_hashing_md5 | 7jG486YR6/F0hVLWYfCnqRyxKe4= | administrator |
| test  | rabbit_password_hashing_md5 | /iSnvCNZ5m3kvqoqqH4U3dSEqTM= | administrator |
+-------+-----------------------------+------------------------------+---------------+
[root@h102 rabbitmq]# rabbitmqadmin delete user name=test
user deleted
[root@h102 rabbitmq]# rabbitmqadmin list users
+-------+-----------------------------+------------------------------+---------------+
| name  |      hashing_algorithm      |        password_hash         |     tags      |
+-------+-----------------------------+------------------------------+---------------+
| guest | rabbit_password_hashing_md5 | 7jG486YR6/F0hVLWYfCnqRyxKe4= | administrator |
+-------+-----------------------------+------------------------------+---------------+
5.2.3 删除 exchange
[root@h102 rabbitmq]# rabbitmqadmin list exchanges
+--------------------+---------+
|        name        |  type   |
+--------------------+---------+
|                    | direct  |
| amq.direct         | direct  |
| amq.fanout         | fanout  |
| amq.headers        | headers |
| amq.match          | headers |
| amq.rabbitmq.log   | topic   |
| amq.rabbitmq.trace | topic   |
| amq.topic          | topic   |
| kk                 | fanout  |
| test               | fanout  |
+--------------------+---------+
[root@h102 rabbitmq]# rabbitmqadmin delete exchange name=test
exchange deleted
[root@h102 rabbitmq]# rabbitmqadmin list exchanges
+--------------------+---------+
|        name        |  type   |
+--------------------+---------+
|                    | direct  |
| amq.direct         | direct  |
| amq.fanout         | fanout  |
| amq.headers        | headers |
| amq.match          | headers |
| amq.rabbitmq.log   | topic   |
| amq.rabbitmq.trace | topic   |
| amq.topic          | topic   |
| kk                 | fanout  |
+--------------------+---------+
5.2.4 删除 binding
[root@h102 rabbitmq]# rabbitmqadmin list bindings  source destination_type destination properties_key
+--------+------------------+-------------+----------------+
| source | destination_type | destination | properties_key |
+--------+------------------+-------------+----------------+
|        | queue            | test        | test           |
| kk     | queue            | test        | test           |
+--------+------------------+-------------+----------------+
[root@h102 rabbitmq]# rabbitmqadmin delete binding source='kk'  destination_type=queue  destination=test  properties_key=test
binding deleted
[root@h102 rabbitmq]# rabbitmqadmin list bindings source destination_type destination properties_key
+--------+------------------+-------------+----------------+
| source | destination_type | destination | properties_key |
+--------+------------------+-------------+----------------+
|        | queue            | test        | test           |
+--------+------------------+-------------+----------------+

Note: source、 destination_type、destination、properties_key 缺一不可,否则会报错
Tip: vhost、policy、parameter、permission 的删除方法类似 ,connection 的关闭方法也类似
5.2.5 清空队列
[root@h102 rabbitmq]# rabbitmqadmin list queues
+------+----------+
| name | messages |
+------+----------+
| test | 5        |
+------+----------+
[root@h102 rabbitmq]# rabbitmqadmin purge queue name=test
queue purged
[root@h102 rabbitmq]# rabbitmqadmin list queues
+------+----------+
| name | messages |
+------+----------+
| test | 0        |
+------+----------+
5.2.6 格式化输出
使用 -f 可以指定格式

有如下几种格式 raw_json, long, pretty_json, kvp, tsv, table, bash

默认为 table

[root@h102 rabbitmq]# rabbitmqadmin list users
+-------+-----------------------------+------------------------------+---------------+
| name  |      hashing_algorithm      |        password_hash         |     tags      |
+-------+-----------------------------+------------------------------+---------------+
| guest | rabbit_password_hashing_md5 | 7jG486YR6/F0hVLWYfCnqRyxKe4= | administrator |
+-------+-----------------------------+------------------------------+---------------+
[root@h102 rabbitmq]# rabbitmqadmin -f raw_json list users
[{"name":"guest","password_hash":"7jG486YR6/F0hVLWYfCnqRyxKe4=","hashing_algorithm":"rabbit_password_hashing_md5","tags":"administrator"}]
[root@h102 rabbitmq]# rabbitmqadmin -f long list users

--------------------------------------------------------------------------------

             name: guest
hashing_algorithm: rabbit_password_hashing_md5
    password_hash: 7jG486YR6/F0hVLWYfCnqRyxKe4=
             tags: administrator

--------------------------------------------------------------------------------

[root@h102 rabbitmq]# rabbitmqadmin -f pretty_json list users
[
  {
    "hashing_algorithm": "rabbit_password_hashing_md5", 
    "name": "guest", 
    "password_hash": "7jG486YR6/F0hVLWYfCnqRyxKe4=", 
    "tags": "administrator"
  }
]
[root@h102 rabbitmq]# rabbitmqadmin -f kvp list users
name="guest" hashing_algorithm="rabbit_password_hashing_md5" password_hash="7jG486YR6/F0hVLWYfCnqRyxKe4=" tags="administrator"
[root@h102 rabbitmq]# rabbitmqadmin -f tsv list users
name    hashing_algorithm   password_hash   tags
guest   rabbit_password_hashing_md5 7jG486YR6/F0hVLWYfCnqRyxKe4=    administrator
[root@h102 rabbitmq]# rabbitmqadmin -f table list users
+-------+-----------------------------+------------------------------+---------------+
| name  |      hashing_algorithm      |        password_hash         |     tags      |
+-------+-----------------------------+------------------------------+---------------+
| guest | rabbit_password_hashing_md5 | 7jG486YR6/F0hVLWYfCnqRyxKe4= | administrator |
+-------+-----------------------------+------------------------------+---------------+
[root@h102 rabbitmq]# rabbitmqadmin -f bash list users
guest

5.3 声明定义

5.3.1 定义一个 queue
[root@h102 rabbitmq]# rabbitmqadmin list bindings
No items
[root@h102 rabbitmq]# rabbitmqadmin list queues
No items
[root@h102 rabbitmq]# rabbitmqadmin declare queue name=test  durable=true
queue declared
[root@h102 rabbitmq]# rabbitmqadmin list queues
+------+----------+
| name | messages |
+------+----------+
| test | 0        |
+------+----------+
[root@h102 rabbitmq]# rabbitmqadmin list bindings
+--------+-------------+-------------+
| source | destination | routing_key |
+--------+-------------+-------------+
|        | test        | test        |
+--------+-------------+-------------+

PS :
durable=true 代表持久化打开

发现定义一个新的queue后,RabbitMQ会自动为之创建一个 binding
5.3.2 发布一条消息
[root@h102 rabbitmq]# rabbitmqadmin list queues
+------+----------+
| name | messages |
+------+----------+
| test | 0        |
+------+----------+
[root@h102 rabbitmq]# rabbitmqadmin publish routing_key=test payload="just for test"
Message published
[root@h102 rabbitmq]# rabbitmqadmin list queues
+------+----------+
| name | messages |
+------+----------+
| test | 1        |
+------+----------+

Tip: 这里有一个细节,我们并未指定任何 exchange ,依旧可以成功发送消息,
    是不是不需要 exchange 参与整个消息的派送过程呢,这和前面说的信息处理流程貌似有冲突呀,先卖个关子,后面再解释
5.3.3 消费一条信息
[root@h102 rabbitmq]# rabbitmqadmin get queue=test requeue=true
+-------------+----------+---------------+---------------+---------------+------------------+------------+-------------+
| routing_key | exchange | message_count |    payload    | payload_bytes | payload_encoding | properties | redelivered |
+-------------+----------+---------------+---------------+---------------+------------------+------------+-------------+
| test        |          | 0             | just for test | 13            | string           |            | False       |
+-------------+----------+---------------+---------------+---------------+------------------+------------+-------------+
[root@h102 rabbitmq]# rabbitmqadmin list queues
+------+----------+
| name | messages |
+------+----------+
| test | 1        |
+------+----------+
[root@h102 rabbitmq]# rabbitmqadmin get queue=test requeue=false
+-------------+----------+---------------+---------------+---------------+------------------+------------+-------------+
| routing_key | exchange | message_count |    payload    | payload_bytes | payload_encoding | properties | redelivered |
+-------------+----------+---------------+---------------+---------------+------------------+------------+-------------+
| test        |          | 0             | just for test | 13            | string           |            | True        |
+-------------+----------+---------------+---------------+---------------+------------------+------------+-------------+
[root@h102 rabbitmq]# rabbitmqadmin list queues
+------+----------+
| name | messages |
+------+----------+
| test | 0        |
+------+----------+
5.3.4 定义一个 exchange

我们前面发布消息的过程中并未指定exchange,依旧成功发布了,事实上只是未明确指出,系统还是帮我们指了,RabbitMQ 的逻辑中是没法绕过 exchange 而直接给queue发送消息的

exchange 有以下几种类型:

direct,topic,headers,fanout

Fanout、Direct、Topic 三种 Exchange Type 的区别:

6.png

系统中默认就有如下 exchange:

[root@h102 rabbitmq]# rabbitmqadmin list exchanges
+--------------------+---------+
|        name        |  type   |
+--------------------+---------+
|                    | direct  |
| amq.direct         | direct  |
| amq.fanout         | fanout  |
| amq.headers        | headers |
| amq.match          | headers |
| amq.rabbitmq.log   | topic   |
| amq.rabbitmq.trace | topic   |
| amq.topic          | topic   |
+--------------------+---------+
[root@h102 rabbitmq]#

我们创建了一个 queue 后,系统自动为它定义了一个 binding:

[root@h102 rabbitmq]# rabbitmqadmin list bindings
+--------+-------------+-------------+
| source | destination | routing_key |
+--------+-------------+-------------+
|        | test        | test        |
+--------+-------------+-------------+

从中我们看出了一些端倪,我们不手动指定 exchange时,使用的默认 exchange是空字符串(系统中的第一个exchange,binding中的source部分),并且这个默认的exchange是 direct 类型,这种隐式调用确保了我的消息准确投递。

这里再定义三个exchange 分属三种类型:

[root@h102 rabbitmq]# rabbitmqadmin list exchanges
+--------------------+---------+
|        name        |  type   |
+--------------------+---------+
|                    | direct  |
| amq.direct         | direct  |
| amq.fanout         | fanout  |
| amq.headers        | headers |
| amq.match          | headers |
| amq.rabbitmq.log   | topic   |
| amq.rabbitmq.trace | topic   |
| amq.topic          | topic   |
+--------------------+---------+
[root@h102 rabbitmq]# rabbitmqadmin declare exchange name=my.fanout type=fanout
exchange declared
[root@h102 rabbitmq]# rabbitmqadmin declare exchange name=my.direct type=direct
exchange declared
[root@h102 rabbitmq]# rabbitmqadmin declare exchange name=my.topic type=topic
exchange declared
[root@h102 rabbitmq]# rabbitmqadmin list exchanges
+--------------------+---------+
|        name        |  type   |
+--------------------+---------+
|                    | direct  |
| amq.direct         | direct  |
| amq.fanout         | fanout  |
| amq.headers        | headers |
| amq.match          | headers |
| amq.rabbitmq.log   | topic   |
| amq.rabbitmq.trace | topic   |
| amq.topic          | topic   |
| my.direct          | direct  |
| my.fanout          | fanout  |
| my.topic           | topic   |
+--------------------+---------+
[root@h102 rabbitmq]#
[root@h102 rabbitmq]# rabbitmqadmin list bindings
+--------+-------------+-------------+
| source | destination | routing_key |
+--------+-------------+-------------+
|        | test        | test        |
+--------+-------------+-------------+
5.3.5 定义 binding

上面申明了几个 exchange ,尝试发布一条信息:

[root@h102 rabbitmq]# rabbitmqadmin list queues
+------+----------+
| name | messages |
+------+----------+
| test | 0        |
+------+----------+
[root@h102 rabbitmq]# rabbitmqadmin publish routing_key=test exchange=my.fanout  payload="just for test"
Message published but NOT routed
[root@h102 rabbitmq]# rabbitmqadmin list queues
+------+----------+
| name | messages |
+------+----------+
| test | 0        |
+------+----------+
[root@h102 rabbitmq]# rabbitmqadmin publish routing_key=test payload="just for test2"
Message published
[root@h102 rabbitmq]# rabbitmqadmin list queues
+------+----------+
| name | messages |
+------+----------+
| test | 1        |
+------+----------+
[root@h102 rabbitmq]# rabbitmqadmin list bindings
+--------+-------------+-------------+
| source | destination | routing_key |
+--------+-------------+-------------+
|        | test        | test        |
+--------+-------------+-------------+

指定 exchange=my.fanout 后,报 Message published but NOT routed ,然后检查queue 发现并产生新消息,而直接不指定却成功发布了,原因是没有binding,exchange 并不知道将数据转发给谁

binding 定义了 exchange 与 queue 的关系,并且限定了路由的部分规则

信息路由规则一部分由 exchange的类型决定 ,一部分由 binding 关系决定,binding 的 key 还能起到甄选信息的作用。

我们创建一个 binding:

[root@h102 rabbitmq]# rabbitmqadmin list bindings
+--------+-------------+-------------+
| source | destination | routing_key |
+--------+-------------+-------------+
|        | test        | test        |
+--------+-------------+-------------+
[root@h102 rabbitmq]# rabbitmqadmin declare binding source=my.fanout destination=test routing_key=first
binding declared
[root@h102 rabbitmq]# rabbitmqadmin list bindings
+-----------+-------------+-------------+
|  source   | destination | routing_key |
+-----------+-------------+-------------+
|           | test        | test        |
| my.fanout | test        | first       |
+-----------+-------------+-------------+

再次尝试发布信息:

[root@h102 rabbitmq]# rabbitmqadmin list queues
+------+----------+
| name | messages |
+------+----------+
| test | 0        |
+------+----------+
[root@h102 rabbitmq]# rabbitmqadmin get queue=test requeue=true
No items
[root@h102 rabbitmq]# rabbitmqadmin publish routing_key=first exchange=my.fanout  payload="just for test1"
Message published
[root@h102 rabbitmq]# rabbitmqadmin list queues
+------+----------+
| name | messages |
+------+----------+
| test | 1        |
+------+----------+
[root@h102 rabbitmq]# rabbitmqadmin publish routing_key=first payload="just for test2"
Message published but NOT routed
[root@h102 rabbitmq]# rabbitmqadmin list queues
+------+----------+
| name | messages |
+------+----------+
| test | 1        |
+------+----------+
[root@h102 rabbitmq]# rabbitmqadmin get queue=test requeue=true
+-------------+-----------+---------------+----------------+---------------+------------------+------------+-------------+
| routing_key | exchange  | message_count |    payload     | payload_bytes | payload_encoding | properties | redelivered |
+-------------+-----------+---------------+----------------+---------------+------------------+------------+-------------+
| first       | my.fanout | 0             | just for test1 | 14            | string           |            | False       |
+-------------+-----------+---------------+----------------+---------------+------------------+------------+
5.3.6 fanout 的特性

定义第二个queue ,也使用 my.fanout binding 起来,取 routing_key 为 second:

[root@h102 rabbitmq]# rabbitmqadmin list queues
+------+----------+
| name | messages |
+------+----------+
| test | 1        |
+------+----------+
[root@h102 rabbitmq]# rabbitmqadmin declare queue name=test.fanout durable=true
queue declared
[root@h102 rabbitmq]# rabbitmqadmin list queues
+-------------+----------+
|    name     | messages |
+-------------+----------+
| test        | 1        |
| test.fanout | 0        |
+-------------+----------+
[root@h102 rabbitmq]# rabbitmqadmin list bindings
+-----------+-------------+-------------+
|  source   | destination | routing_key |
+-----------+-------------+-------------+
|           | test        | test        |
|           | test.fanout | test.fanout |
| my.fanout | test        | first       |
+-----------+-------------+-------------+
[root@h102 rabbitmq]# 
[root@h102 rabbitmq]# rabbitmqadmin declare binding source=my.fanout destination=test.fanout routing_key=second
binding declared
[root@h102 rabbitmq]# rabbitmqadmin list bindings
+-----------+-------------+-------------+
|  source   | destination | routing_key |
+-----------+-------------+-------------+
|           | test        | test        |
|           | test.fanout | test.fanout |
| my.fanout | test        | first       |
| my.fanout | test.fanout | second      |
+-----------+-------------+-------------+

尝试再发一条数据到 my.fanout 中:

[root@h102 rabbitmq]# rabbitmqadmin list queues
+-------------+----------+
|    name     | messages |
+-------------+----------+
| test        | 1        |
| test.fanout | 0        |
+-------------+----------+
[root@h102 rabbitmq]# rabbitmqadmin publish routing_key=second exchange=my.fanout payload="just for test3"
Message published
[root@h102 rabbitmq]# rabbitmqadmin list queues
+-------------+----------+
|    name     | messages |
+-------------+----------+
| test        | 2        |
| test.fanout | 1        |
+-------------+----------+
[root@h102 rabbitmq]# rabbitmqadmin get queue=test requeue=true
+-------------+-----------+---------------+----------------+---------------+------------------+------------+-------------+
| routing_key | exchange  | message_count |    payload     | payload_bytes | payload_encoding | properties | redelivered |
+-------------+-----------+---------------+----------------+---------------+------------------+------------+-------------+
| first       | my.fanout | 1             | just for test1 | 14            | string           |            | True        |
+-------------+-----------+---------------+----------------+---------------+------------------+------------+-------------+
[root@h102 rabbitmq]# rabbitmqadmin get queue=test.fanout requeue=true
+-------------+-----------+---------------+----------------+---------------+------------------+------------+-------------+
| routing_key | exchange  | message_count |    payload     | payload_bytes | payload_encoding | properties | redelivered |
+-------------+-----------+---------------+----------------+---------------+------------------+------------+-------------+
| second      | my.fanout | 0             | just for test3 | 14            | string           |            | False       |
+-------------+-----------+---------------+----------------+---------------+------------------+------------+-------------+
[root@h102 rabbitmq]# rabbitmqadmin list queues
+-------------+----------+
|    name     | messages |
+-------------+----------+
| test        | 2        |
| test.fanout | 1        |
+-------------+----------+

这次我们使用 routing_key=first 来投递消息:

[root@h102 rabbitmq]# rabbitmqadmin list queues
+-------------+----------+
|    name     | messages |
+-------------+----------+
| test        | 2        |
| test.fanout | 1        |
+-------------+----------+
[root@h102 rabbitmq]# rabbitmqadmin purge queue name=test
queue purged
[root@h102 rabbitmq]# rabbitmqadmin purge queue name=test.fanout
queue purged
[root@h102 rabbitmq]# rabbitmqadmin list queues
+-------------+----------+
|    name     | messages |
+-------------+----------+
| test        | 0        |
| test.fanout | 0        |
+-------------+----------+
[root@h102 rabbitmq]# rabbitmqadmin publish routing_key=first exchange=my.fanout payload="just for test4"
Message published
[root@h102 rabbitmq]# rabbitmqadmin list queues
+-------------+----------+
|    name     | messages |
+-------------+----------+
| test        | 1        |
| test.fanout | 1        |
+-------------+----------+
[root@h102 rabbitmq]# rabbitmqadmin get queue=test requeue=true
+-------------+-----------+---------------+----------------+---------------+------------------+------------+-------------+
| routing_key | exchange  | message_count |    payload     | payload_bytes | payload_encoding | properties | redelivered |
+-------------+-----------+---------------+----------------+---------------+------------------+------------+-------------+
| first       | my.fanout | 0             | just for test4 | 14            | string           |            | False       |
+-------------+-----------+---------------+----------------+---------------+------------------+------------+-------------+
[root@h102 rabbitmq]# rabbitmqadmin get queue=test.fanout requeue=true
+-------------+-----------+---------------+----------------+---------------+------------------+------------+-------------+
| routing_key | exchange  | message_count |    payload     | payload_bytes | payload_encoding | properties | redelivered |
+-------------+-----------+---------------+----------------+---------------+------------------+------------+-------------+
| first       | my.fanout | 0             | just for test4 | 14            | string           |            | False       |
+-------------+-----------+---------------+----------------+---------------+------------------+------------

发现结果一样,应证了前面说的 routing_key 会被忽略的说法,但是不能不指定,否则会报错:

[root@h102 rabbitmq]# rabbitmqadmin publish exchange=my.fanout payload="just for test5"

ERROR: mandatory argument "routing_key" required

rabbitmqadmin --help for help

[root@h102 rabbitmq]#
5.3.7 direct 的特性

定义第三个queue ,使用 my.direct binding 起来:

[root@h102 rabbitmq]# rabbitmqadmin list queues
+-------------+----------+
|    name     | messages |
+-------------+----------+
| test        | 0        |
| test.fanout | 0        |
+-------------+----------+
[root@h102 rabbitmq]# rabbitmqadmin declare queue name=test.direct durable=true
queue declared
[root@h102 rabbitmq]# rabbitmqadmin list queues
+-------------+----------+
|    name     | messages |
+-------------+----------+
| test        | 0        |
| test.direct | 0        |
| test.fanout | 0        |
+-------------+----------+
[root@h102 rabbitmq]# rabbitmqadmin declare binding source=my.direct destination=test routing_key=third
binding declared
[root@h102 rabbitmq]# rabbitmqadmin declare binding source=my.direct destination=test.direct routing_key=fourth
binding declared
[root@h102 rabbitmq]# rabbitmqadmin list bindings
+-----------+-------------+-------------+
|  source   | destination | routing_key |
+-----------+-------------+-------------+
|           | test        | test        |
|           | test.direct | test.direct |
|           | test.fanout | test.fanout |
| my.direct | test        | third       |
| my.direct | test.direct | fourth      |
| my.fanout | test        | first       |
| my.fanout | test.fanout | second      |
+-----------+-------------+-------------+
[root@h102 rabbitmq]# 

尝试分别使用 third 和 fourth 的 routing_key 来发布消息:

[root@h102 rabbitmq]# rabbitmqadmin list queues
+-------------+----------+
|    name     | messages |
+-------------+----------+
| test        | 0        |
| test.direct | 0        |
| test.fanout | 0        |
+-------------+----------+
[root@h102 rabbitmq]# rabbitmqadmin publish routing_key=third exchange=my.direct payload="just for test6"
Message published
[root@h102 rabbitmq]# rabbitmqadmin list queues
+-------------+----------+
|    name     | messages |
+-------------+----------+
| test        | 1        |
| test.direct | 0        |
| test.fanout | 0        |
+-------------+----------+
[root@h102 rabbitmq]# rabbitmqadmin get queue=test requeue=true
+-------------+-----------+---------------+----------------+---------------+------------------+------------+-------------+
| routing_key | exchange  | message_count |    payload     | payload_bytes | payload_encoding | properties | redelivered |
+-------------+-----------+---------------+----------------+---------------+------------------+------------+-------------+
| third       | my.direct | 0             | just for test6 | 14            | string           |            | False       |
+-------------+-----------+---------------+----------------+---------------+------------------+------------+-------------+
[root@h102 rabbitmq]# rabbitmqadmin publish routing_key=fourth exchange=my.direct payload="just for test7"
Message published
[root@h102 rabbitmq]# rabbitmqadmin list queues
+-------------+----------+
|    name     | messages |
+-------------+----------+
| test        | 1        |
| test.direct | 1        |
| test.fanout | 0        |
+-------------+----------+
[root@h102 rabbitmq]# rabbitmqadmin get queue=test.direct requeue=true
+-------------+-----------+---------------+----------------+---------------+------------------+------------+-------------+
| routing_key | exchange  | message_count |    payload     | payload_bytes | payload_encoding | properties | redelivered |
+-------------+-----------+---------------+----------------+---------------+------------------+------------+-------------+
| fourth      | my.direct | 0             | just for test7 | 14            | string           |            | False       |
+-------------+-----------+---------------+----------------+---------------+------------------+------------+-------------+
[root@h102 rabbitmq]# 

从反馈结果来看,direct 的 exchange 就像点对点通信,fanout 的 exchange 就像是广播

5.3.4 topic 的特性

定义第四个queue ,使用 my.topic binding 起来

[root@h102 rabbitmq]# rabbitmqadmin purge queue name=test
queue purged
[root@h102 rabbitmq]# rabbitmqadmin purge queue name=test.direct
queue purged
[root@h102 rabbitmq]# rabbitmqadmin list queues
+-------------+----------+
|    name     | messages |
+-------------+----------+
| test        | 0        |
| test.direct | 0        |
| test.fanout | 0        |
+-------------+----------+
[root@h102 rabbitmq]# rabbitmqadmin declare queue name=test.topic durable=true
queue declared
[root@h102 rabbitmq]# rabbitmqadmin list queues
+-------------+----------+
|    name     | messages |
+-------------+----------+
| test        | 0        |
| test.direct | 0        |
| test.fanout | 0        |
| test.topic  | 0        |
+-------------+----------+
[root@h102 rabbitmq]# rabbitmqadmin declare binding source=my.topic destination=test routing_key=*.hard.* 
binding declared
[root@h102 rabbitmq]# rabbitmqadmin declare binding source=my.topic destination=test.topic routing_key=cheap.# 
binding declared
[root@h102 rabbitmq]# rabbitmqadmin declare binding source=my.topic destination=test.direct routing_key=*.*.food 
binding declared
[root@h102 rabbitmq]# rabbitmqadmin declare binding source=my.topic destination=test.fanout routing_key=*.*.food
binding declared
[root@h102 rabbitmq]# rabbitmqadmin list bindings
+-----------+-------------+-------------+
|  source   | destination | routing_key |
+-----------+-------------+-------------+
|           | test        | test        |
|           | test.direct | test.direct |
|           | test.fanout | test.fanout |
|           | test.topic  | test.topic  |
| my.direct | test        | third       |
| my.direct | test.direct | fourth      |
| my.fanout | test        | first       |
| my.fanout | test.fanout | second      |
| my.topic  | test        | *.hard.*    |
| my.topic  | test.direct | *.*.food    |
| my.topic  | test.fanout | *.*.food    |
| my.topic  | test.topic  | cheap.#     |
+-----------+-------------+-------------+

如果不使用 * 和 # ,那么 topic 的特性就和 direct 一样了:

[root@h102 rabbitmq]# rabbitmqadmin declare binding source=my.topic destination=test.fanout routing_key=xtest
binding declared
[root@h102 rabbitmq]# rabbitmqadmin list bindings
+-----------+-------------+-------------+
|  source   | destination | routing_key |
+-----------+-------------+-------------+
|           | test        | test        |
|           | test.direct | test.direct |
|           | test.fanout | test.fanout |
|           | test.topic  | test.topic  |
| my.direct | test        | third       |
| my.direct | test.direct | fourth      |
| my.fanout | test        | first       |
| my.fanout | test.fanout | second      |
| my.topic  | test        | *.hard.*    |
| my.topic  | test.direct | *.*.food    |
| my.topic  | test.fanout | *.*.food    |
| my.topic  | test.fanout | xtest       |
| my.topic  | test.topic  | cheap.#     |
+-----------+-------------+-------------+
[root@h102 rabbitmq]#

尝试使用以上 routing_key 发送消息:

[root@h102 rabbitmq]# rabbitmqadmin list queues
+-------------+----------+
|    name     | messages |
+-------------+----------+
| test        | 0        |
| test.direct | 0        |
| test.fanout | 0        |
| test.topic  | 0        |
+-------------+----------+
[root@h102 rabbitmq]# rabbitmqadmin publish routing_key=a.hard.b  exchange=my.topic payload="just for test8"
Message published
[root@h102 rabbitmq]# rabbitmqadmin list queues
+-------------+----------+
|    name     | messages |
+-------------+----------+
| test        | 1        |
| test.direct | 0        |
| test.fanout | 0        |
| test.topic  | 0        |
+-------------+----------+
[root@h102 rabbitmq]# rabbitmqadmin publish routing_key=a.hard.food  exchange=my.topic payload="just for test9"
Message published
[root@h102 rabbitmq]# rabbitmqadmin list queues
+-------------+----------+
|    name     | messages |
+-------------+----------+
| test        | 2        |
| test.direct | 1        |
| test.fanout | 1        |
| test.topic  | 0        |
+-------------+----------+
[root@h102 rabbitmq]# rabbitmqadmin publish routing_key=cheap.soft.food  exchange=my.topic payload="just for test10"
Message published
[root@h102 rabbitmq]# rabbitmqadmin list queues
+-------------+----------+
|    name     | messages |
+-------------+----------+
| test        | 2        |
| test.direct | 2        |
| test.fanout | 2        |
| test.topic  | 1        |
+-------------+----------+
[root@h102 rabbitmq]# rabbitmqadmin publish routing_key=cheap.hard.drink  exchange=my.topic payload="just for test11"
Message published
[root@h102 rabbitmq]# rabbitmqadmin list queues
+-------------+----------+
|    name     | messages |
+-------------+----------+
| test        | 3        |
| test.direct | 2        |
| test.fanout | 2        |
| test.topic  | 2        |
+-------------+----------+
[root@h102 rabbitmq]# rabbitmqadmin publish routing_key=xtest exchange=my.topic payload="just for test12"
Message published
[root@h102 rabbitmq]# rabbitmqadmin list queues
+-------------+----------+
|    name     | messages |
+-------------+----------+
| test        | 3        |
| test.direct | 2        |
| test.fanout | 3        |
| test.topic  | 2        |
+-------------+----------+
[root@h102 rabbitmq]# rabbitmqadmin publish routing_key=cheap.hard.food  exchange=my.topic payload="just for test13"
Message published
[root@h102 rabbitmq]# rabbitmqadmin list queues
+-------------+----------+
|    name     | messages |
+-------------+----------+
| test        | 4        |
| test.direct | 2        |
| test.fanout | 4        |
| test.topic  | 3        |
+-------------+----------+
[root@h102 rabbitmq]# rabbitmqadmin list queues
+-------------+----------+
|    name     | messages |
+-------------+----------+
| test        | 4        |
| test.direct | 3        |
| test.fanout | 4        |
| test.topic  | 3        |
+-------------+----------+
[root@h102 rabbitmq]# 

到此为止,我们看到了 topic 的组播,异步特性

六、rabbitmqadmin命令汇总

wget http://localhost:15672/cli/rabbitmqadmin
rabbitmqadmin --help
rabbitmqadmin help subcommands
rabbitmqadmin help config
rabbitmqadmin list users        查看所有用户 User
rabbitmqadmin list users name       查看所有用户名 Username
rabbitmqadmin list users tags       查看所有用户角色
rabbitmqadmin list vhosts       查看所有虚拟主机
rabbitmqadmin list connections      查看所有连接
rabbitmqadmin list exchanges        查看所有路由 Exchange
rabbitmqadmin list bindings     查看所有路由与队列的关系绑定binding
rabbitmqadmin list permissions      查看所有角色的权限 Permission
rabbitmqadmin list channels     查看所有通道 Channel
rabbitmqadmin list consumers        查看所有消费者 Consumer
rabbitmqadmin list queues       查看所有消息队列 Queue
rabbitmqadmin list nodes        查看所有节点 Node
rabbitmqadmin show overview     概览 Overview
rabbitmqadmin list bindings source destination_type destination properties_key      查看所有路由与队列的关系绑定的详细信息 Binding
rabbitmqadmin purge queue name=test     清空队列
rabbitmqadmin -f raw_json list users        格式化输出
rabbitmqadmin -f long list users        格式化输出
rabbitmqadmin -f pretty_json list users
rabbitmqadmin -f kvp list users
rabbitmqadmin -f tsv list users
rabbitmqadmin -f table list users
rabbitmqadmin -f bash list users
rabbitmqadmin declare queue name=test durable=true      定义一个队列queue,durable=true 代表持久化打开。
rabbitmqadmin publish routing_key=test payload="just for test"      发布一条消息
rabbitmqadmin get queue=test requeue=true       消费一条信息
rabbitmqadmin get queue=test requeue=false
rabbitmqadmin declare exchange name=my.fanout type=fanout       定义一个Fanout路由
rabbitmqadmin declare exchange name=my.direct type=direct       定义一个Direct路由
rabbitmqadmin declare exchange name=my.topic type=topic         定义一个Topic路由
rabbitmqadmin declare binding source=my.fanout destination=test routing_key=first       定义 binding
rabbitmqadmin delete queue name=hello       删除消息队列 Queue
rabbitmqadmin delete user name=test     删除用户 User
rabbitmqadmin delete exchange name=test     删除路由器 Exchange
rabbitmqadmin delete binding source='kk' destination_type=queue destination=test properties_key=test        删除路由器与消息队列的关系绑定 Binding
rabbitmqadmin publish routing_key=first exchange=my.fanout payload="just for test1"     使用路由转发消息
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 162,547评论 4 374
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,787评论 2 308
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 112,175评论 0 254
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,752评论 0 223
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,169评论 3 297
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 41,056评论 1 226
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,195评论 2 321
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,980评论 0 214
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,724评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,872评论 2 254
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,344评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,667评论 3 264
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,379评论 3 245
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,202评论 0 9
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,992评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,189评论 2 286
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,987评论 2 279