白话rabbitmq(一): HelloWorld

推广

RabbitMQ专题讲座

https://segmentfault.com/l/15...

CoolMQ开源项目

我们利用消息队列实现了分布式事务的最终一致性解决方案,请大家围观。可以参考源码:https://github.com/vvsuperman…,项目支持网站: http://rabbitmq.org.cn,最新文章或实现会更新在上面

前言

消息队列想必大家都有一定了解:用来解耦,上级模块不用关心下级模块是否执行成功,最常见的比如说日志,核心系统并不关心日志是否成功,日志什么时候记录。这种情形就可以用消息队列来解耦。

RabbitMQ作为消息队列的一个典型实践,完全实现了AMQ标准,与Kafka的快快快不同,它追求的稳定、可靠。下面就来几篇文章来详细介绍下,均翻译至RabbitMQ的官方文档。

RabbitMQ是一个消息的中介(用来接受以及转发消息),就像是一个非常可靠的邮局,当信件放到邮局时,信件就确保能到达,所以,RabbitMQ可以看成是邮箱、邮局、以及邮递员的合体

RabbitMQ的一些重要概念

produceing(生产者):生产数据

clipboard.png

queue(队列):

类似于邮箱,存在于RabbitMQ服务器的内部,用来存储消息,并且消息只能存储在队列里面。队列的大小只受RabbitMQ主机内存和硬盘的影响。同一个队列不仅可以绑定多个生产者,而且能够发送消息到多个消费者。

clipboard.png

Consuming(消费者):接受并消费消息。

clipboard.png

Hello World

下面我们来写我们的第一个“Hello World”,我们会使用Java的API来编写一个生产者来生产消息,以及一个消费者来消费消息

P是我们的生产者,而C是我们的消费者。中间的box是我们的queue:作为消息缓冲,是RabbitMQ用来存储转发消息给消费者的。

clipboard.png

Java客户端库

RabbitMQ支持多重协议,这里我们会用AMQP 0-9-1来说明,它是一个消息队列的通用协议。RabbitMQ同时也有多种语言的客户端,我们在这里用Java来做说明。

首先请下载Java客户端包以及它所依赖的SLF4JSLF4J SIMPLE,将它们拷贝到自己的工作区。

引入RabbitMQ同样也可以使用Maven来做依赖管理, groupId是com.rabbitmq 以及artifactId amqp-client

发送请求

clipboard.png

生产者会发送消息到MQ,然后退出
在Send.java中,首先我们import一些类

import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.Channel;

设置我们的主类

public class Send {
  private final static String QUEUE_NAME = "hello";

  public static void main(String[] argv)
      throws java.io.IOException {
      ...
  }
}   

创建Connection

ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();

这里我们连接的是本地,你当然也可以连接到另一个服务器上,只需要指明服务器的名称和ip地址。

下面我们要创建一个Channel,大家可以想象一些,消息的产生和发送都是通过这个Channel完成的。

当然,我们还需要顶一个一个Queue来接受消息
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
String message = "Hello World!";
channel.basicPublish("", QUEUE_NAME, null, message.getBytes());
System.out.println(" [x] Sent '" + message + "'");

对于Queue的定义是冥等的,如果不存在才会创建,如果存在则不会再建新的。消息会被格式化成byte的数组,方便进行任意的转换。

最后,我们关闭通道

channel.close();
connection.close();

完整的代码可以看这个地方:send.java

接受请求

消费者会从RabbitMQ接收到请求,消息是被到消费者,而且消费者会一直监听着消息队列,一旦有有新的消息就会打印出来。

Recv.java几乎于Send完全类似

import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Consumer;
import com.rabbitmq.client.DefaultConsumer;

Defaultconsumer是一个继承了Consumer接口的类,方便我们来存储消息队列来的消息。建立消费者与我们建立生产者非常类似:

public class Recv {
  private final static String QUEUE_NAME = "hello";

  public static void main(String[] argv)
      throws java.io.IOException,
             java.lang.InterruptedException {

    ConnectionFactory factory = new ConnectionFactory();
    factory.setHost("localhost");
    Connection connection = factory.newConnection();
    Channel channel = connection.createChannel();

    channel.queueDeclare(QUEUE_NAME, false, false, false, null);
    System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
    ...
    }
}

你可以注意到我们在消费者定义了一个Queue,因此我们是需要在生产者之前启动消费者的,我们要确保我们在消费消息之前这个队列是已经存在的。

然后我们需要告诉mq服务可以推送消息给我们。因为这个推送是异步的,因此我们可以提供一个回调方法,DefaultConsumer会暂时存储这个消息,直到消费者以及准备好来处理接受到的消息了(消息会存储在消费者中直到消费者有能力来消费它,可以想象一下数据库等高IO操作)

Consumer consumer = new DefaultConsumer(channel) {
  @Override
  public void handleDelivery(String consumerTag, Envelope envelope,
                             AMQP.BasicProperties properties, byte[] body)
      throws IOException {
    String message = new String(body, "UTF-8");
    System.out.println(" [x] Received '" + message + "'");
  }
};
channel.basicConsume(QUEUE_NAME, true, consumer);

完整的Recv.java地址

跑起来

我们可以先用javac来编译程序

javac -cp amqp-client-4.0.2.jar Send.java Recv.java

而后来运行它,这需要我们在路径加上它的依赖包,我们首先启动的是消费者

java -cp .:amqp-client-4.0.2.jar:slf4j-api-1.7.21.jar:slf4j-simple-1.7.22.jar Recv

而后启动发送者

java -cp .:amqp-client-4.0.2.jar:slf4j-api-1.7.21.jar:slf4j-simple-1.7.22.jar Send

消费者会持续等待,并打印从生产者哪里来的消息,你可以用(Ctrl-C)来停止它。所以你要另外开启一个命令行窗口来运行生产者。

查看队列

也许你想知道RabbitMQ中到底有多少个消息,你可以使用rabbitmqctl工具:

sudo rabbitmqctl list_queues

在Windows中:

rabbitmqctl.bat list_queues





大杂烩
所学甚杂

教育皆祸害,[链接]

2k 声望
221 粉丝
0 条评论
推荐阅读
人工智能/大数据就业前景及优劣势分析
总述 职位少,要求高,人工智能落地困难,决定了就业可能会是一个大问题 全国范围内的人工智能的职位是183 而Java是10000+ (因lagou并不展示总数,因此该数据从请求分析而来) 因此岗位数量与Java大概是60倍的差距...

方老司1阅读 5.6k

一文搞懂秒杀系统,欢迎参与开源,提交PR,提高竞争力。早日上岸,升职加薪。
前言秒杀和高并发是面试的高频考点,也是我们做电商项目必知必会的场景。欢迎大家参与我们的开源项目,提交PR,提高竞争力。早日上岸,升职加薪。知识点详解秒杀系统架构图秒杀流程图秒杀系统设计这篇文章一万多...

王中阳Go33阅读 2.5k评论 1

封面图
计算机网络连环炮40问
本文已经收录到Github仓库,该仓库包含计算机基础、Java基础、多线程、JVM、数据库、Redis、Spring、Mybatis、SpringMVC、SpringBoot、分布式、微服务、设计模式、架构、校招社招分享等核心知识点,欢迎star~

程序员大彬14阅读 1.8k

万字详解,吃透 MongoDB!
MongoDB 是一个基于 分布式文件存储 的开源 NoSQL 数据库系统,由 C++ 编写的。MongoDB 提供了 面向文档 的存储方式,操作起来比较简单和容易,支持“无模式”的数据建模,可以存储比较复杂的数据类型,是一款非常...

JavaGuide8阅读 1.7k

封面图
花了半个小时基于 ChatGPT 搭建了一个微信机器人
相信大家最近被 ChatGPT 刷屏了,其实在差不多一个月前就火过一次,不会那会好像只在程序员的圈子里面火起来了,并没有被大众认知到,不知道最近是因为什么又火起来了,而且这次搞的人尽皆知。

Java极客技术12阅读 3.2k评论 3

封面图
数据结构与算法:二分查找
一、常见数据结构简单数据结构(必须理解和掌握)有序数据结构:栈、队列、链表。有序数据结构省空间(储存空间小)无序数据结构:集合、字典、散列表,无序数据结构省时间(读取时间快)复杂数据结构树、 堆图二...

白鲸鱼9阅读 5.3k

PHP转Go实践:xjson解析神器「开源工具集」
我和劲仔都是PHP转Go,身边越来越多做PHP的朋友也逐渐在用Go进行重构,重构过程中,会发现php的json解析操作(系列化与反序列化)是真的香,弱类型语言的各种隐式类型转换,很大程度的减低了程序的复杂度。

王中阳Go11阅读 2.7k评论 4

封面图

教育皆祸害,[链接]

2k 声望
221 粉丝
宣传栏