rabbitmq_01中间件简介

1.中间件

中间件(Middleware)是处于操作系统和应用程序之间的软件,也有人认为它应该属于操作系统中的一部分。人们在使用中间件时,往往是一组中间件集成在一起,构成一个平台(包括开发平台和运行平台),但在这组中间件中必须要有一个通信中间件,即中间件+平台+通信,这个定义也限定了只有用于分布式系统中才能称为中间件,同时还可以把它与支撑软件和使用软件区分开来

上面copy的 挺难定义的也挺难理解的。。。
相对与我们接触到的中间简单点来说:
在我们的应用程序和应用程序之间,应用程序和硬件之间,支持标准协议和接口用于分布式系统中的称为中间件。
在这里插入图片描述
也很难给中间件一个严格的定义,但中间件应具有如下的一些特点:
(1)满足大量应用的需要
(2)运行于多种硬件和 OS平台
(3)支持分布计算,提供跨网络、硬件和 OS平台的透明性的应用或服务的交互
(4)支持标准的协议
(5)支持标准的接口
由于标准接口对于可移植

2.AMQP协议

AMQP:(全称:Advanced Message Queuing Protocol)是高级消息队列协议。由摩根大通集团联合其他公司共同设计。是一个提供统一消息服务的应用层标准高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计。基于此协议的客户端与消息中间件可传递消息,并不受客户端/中间件不同产品,不同的开发语言等条件的限制。Erlang中的实现由 RabbitMQ等

在这里插入图片描述
工作过程
发布者(Publisher)发布消息(Message),经由交换机(Exchange)。
交换机根据路由规则将收到的消息分发给与该交换机绑定的队列(Queue)。
最后 AMQP 代理会将消息投递给订阅了此队列的消费者,或者消费者按照需求自行获取。

RabbitMQ的主要角色
Broker:接受消费者和生产者的连接,实现AMQP实体服务。
Connection:连接,实现消费者和生产者与Broker之间的TCP/IP连接。
Channel:通道,Channel使进行消息读写的通道一个Connection可以包含多个Channel。之所以需要Channel,是因为TCP连接的建立和释放都是十分昂贵的,如果一个客户端每一个线程都需要与Broker交互,如果每一个线程都建立一个TCP连接,暂且不考虑TCP连接是否浪费,就算操作系统也无法承受每秒建立如此多的TCP连接。RabbitMQ建议客户端线程之间不要共用Channel,至少要保证共用Channel的线程发送消息必须是串行的,但是建议尽量共用Connection。
Exchange:交换机,接受消息,不具备消息存储的功能只负责,根据路由键分发消息,(交换机是一定存在的,在direct模式中用到的就是默认交换机 Exchange: (AMQP default)
Virtual Host : 虚拟地址,用于消息的逻辑隔离,相当于迷你的RabbitMq。
Bindings: 绑定Exchange和queue自己哦考吗的虚拟连接规则。
Routing Key: Exchange和queue之间匹配的路由规则

3. 搭建环境

Linux :RabbitMQ环境

> yum update
> yum install -y yum-utils device-mapper-persistent-data lvm2  #软件包
> yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo  #设置yum源
> yum install docker-ce -y  #安装docker
> docker -v   #检测版本
> sudo mkdir -p /etc/docker   #加速镜像
> sudo tee  /etc/docker/daemon.json <<'EOF'
{
 "registry-mirrors": ["https://0wrdwnn6.mirror.aliyuncs.com"]
}
EOF
>sudo systemctl daemon-reload
>sudo systemctl restart docker #重启
>systemctl enable docker     #开机自启

>创建带有web界面的RabbitMQ  创建用户名密码为:admin admin的容器
>docker run -di --name myrabitt -e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=admin -p 15672:15672 -p 25672:25672 -p 61613:61613 -p 1883:1883 rabbitmq:management

http://IP:15672 即可登陆WEB界面

4.RabbitMQ的设计模式

模式:简单模式
特点:一个生产者一个消费者
在这里插入图片描述
模式:work模式
特点:一个生产者多个消费者,生产则发送一条消息,只能被一个消费者拿到。
轮询模式(默认): 平均分配,每个消费者分配到的消息一致
公平分发(必须使用手动应答): 能者多劳 ,根据消费者的处理速度决定,消息的分配
公平分发:

              //qos  设置 每次从队列中取出多少条数据 根据自己的 内存和disk space 决定
                channel.basicQos(1);
                Channel finalChannel = channel;
                //@param 2  false 开启手动改应答
                channel.basicConsume(queue, false, new DeliverCallback() {
                    @Override
                    public void handle(String s, Delivery delivery) throws IOException {
                        System.out.println("收到消息:" + new String(delivery.getBody(), "UTF-8"));
                        finalChannel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
                    }
                }, new CancelCallback() {
                    @Override
                    public void handle(String s) throws IOException {
                        System.out.println("消息接收失败");
                    }
                });

在这里插入图片描述
类型:订阅模式
特点:和work模式类似,一个生产者多个消费者,但是中间多了个交换机(exchange),一条消息可以被多个消费者获取。
在这里插入图片描述
类型:路由模式
特点:一条消息可以被多个消费者获取。但是他在传递消息的时候多设置了一个key,消费者拿消息的时候也设置一个或多个key,key匹配才能拿消息
在这里插入图片描述
类型:主题模式
特点:带有模糊匹配的路由模式
在这里插入图片描述

4. 纯Java案例操交换机和队列的关系的路由模式

生产者

package com.hdh.rabbitmq.all;

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


/**
 * @description:手动创建生产者
 * @author:hdh
 * @date:2021-07-19 16:22
 **/
public class Producer {
    public static void main(String[] args) {

        //1.创建连接工厂
        ConnectionFactory connectionFactory = new ConnectionFactory();
        connectionFactory.setHost("192.168.204.128");
        connectionFactory.setPort(5672);
        connectionFactory.setUsername("admin");
        connectionFactory.setPassword("admin");
        connectionFactory.setVirtualHost("/");
        Connection connection = null;
        Channel channel = null;
        try {
            //2.创建连接connection
            connection = connectionFactory.newConnection("生产者");
            //3.获取通道channel
            channel = connection.createChannel();
            //4.通过创建交换机,声明队列,绑定关系,路由key,发送消息和接收消息
            String exchangeName = "direct_message_exchange";
            //交换机类型 direct/fanout/topic/headrs
            String exchangeType="direct";
            String routeKey = "sms";
            String message = "hello message!!!";
            //传递的信息必定会 先经过交换机,然后投递给队列

            //声明交换机 @param3 是否持久化 交换机会不会随着夫妻的重启而丢失 ,true不丢失
            channel.exchangeDeclare(exchangeName,exchangeType,true);
            //声明队列
            channel.queueDeclare("queue4",true,false,false,null);
            channel.queueDeclare("queue5",true,false,false,null);
            channel.queueDeclare("queue6",true,false,false,null);
             //绑定队列 和交换机的关系

            channel.queueBind("queue4",exchangeName,"order");
            channel.queueBind("queue5",exchangeName,"order");
            channel.queueBind("queue6",exchangeName,"course");


            channel.basicPublish(exchangeName, "order", null, message.getBytes());
            System.out.println("消息推送成功");
        } catch (Exception e) {
            System.out.println("消息推送失败");
            e.printStackTrace();
        } finally {
            //5关闭连接 通道
            if (channel != null && channel.isOpen()) {
                try {
                    channel.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            if (connection != null && connection.isOpen()) {
                try {
                    connection.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

消费者

package com.hdh.rabbitmq.all;

import com.rabbitmq.client.*;

import java.io.IOException;


/**
 * @description:手动创建消费者
 * @author:hdh
 * @date:2021-07-19 16:22
 **/
public class Consumer {
    private static Runnable runnable = new Runnable() {
        @Override
        public void run() {

            //1.创建连接工厂
            ConnectionFactory connectionFactory = new ConnectionFactory();
            connectionFactory.setHost("192.168.204.128");
            connectionFactory.setPort(5672);
            connectionFactory.setUsername("admin");
            connectionFactory.setPassword("admin");
            connectionFactory.setVirtualHost("/");
            Connection connection = null;
            Channel channel = null;

            String queue = Thread.currentThread().getName();
            try {
                //2.创建连接connection
                connection = connectionFactory.newConnection("生产者");
                //3.获取通道channel
                channel = connection.createChannel();
                //4.通过创建交换机,声明队列,绑定关系,路由key,发送消息和接收消息
                channel.basicConsume(queue, true, new DeliverCallback() {
                    @Override
                    public void handle(String s, Delivery delivery) throws IOException {
                        System.out.println("收到消息:" + new String(delivery.getBody(), "UTF-8"));
                    }
                }, new CancelCallback() {
                    @Override
                    public void handle(String s) throws IOException {
                        System.out.println("消息接收失败");
                    }
                });
                System.in.read();
            } catch (
                    Exception e) {
                e.printStackTrace();
            } finally {
                //5关闭连接 通道
                if (channel != null && channel.isOpen()) {
                    try {
                        channel.close();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
                if (connection != null && connection.isOpen()) {
                    try {
                        connection.close();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    };

    public static void main(String[] args) {
        new Thread(runnable, "queue4").start();
        new Thread(runnable, "queue5").start();
        new Thread(runnable, "queue6").start();

    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C语言是一种广泛使用的编程语言,它具有高效、灵活、可移植性强等特点,被广泛应用于操作系统、嵌入式系统、数据库、编译器等领域的开发。C语言的基本语法包括变量、数据类型、运算符、控制结构(如if语句、循环语句等)、函数、指针等。在编写C程序时,需要注意变量的声明和定义、指针的使用、内存的分配与释放等问题。C语言中常用的数据结构包括: 1. 数组:一种存储同类型数据的结构,可以进行索引访问和修改。 2. 链表:一种存储不同类型数据的结构,每个节点包含数据和指向下一个节点的指针。 3. 栈:一种后进先出(LIFO)的数据结构,可以通过压入(push)和弹出(pop)操作进行数据的存储和取出。 4. 队列:一种先进先出(FIFO)的数据结构,可以通过入队(enqueue)和出队(dequeue)操作进行数据的存储和取出。 5. 树:一种存储具有父子关系的数据结构,可以通过中序遍历、前序遍历和后序遍历等方式进行数据的访问和修改。 6. 图:一种存储具有节点和边关系的数据结构,可以通过广度优先搜索、深度优先搜索等方式进行数据的访问和修改。 这些数据结构在C语言中都有相应的实现方式,可以应用于各种不同的场景。C语言中的各种数据结构都有其优缺点,下面列举一些常见的数据结构的优缺点: 数组: 优点:访问和修改元素的速度非常快,适用于需要频繁读取和修改数据的场合。 缺点:数组的长度是固定的,不适合存储大小不固定的动态数据,另外数组在内存中是连续分配的,当数组较大时可能会导致内存碎片化。 链表: 优点:可以方便地插入和删除元素,适用于需要频繁插入和删除数据的场合。 缺点:访问和修改元素的速度相对较慢,因为需要遍历链表找到指定的节点。 栈: 优点:后进先出(LIFO)的特性使得栈在处理递归和括号匹配等问题时非常方便。 缺点:栈的空间有限,当数据量较大时可能会导致栈溢出。 队列: 优点:先进先出(FIFO)的特性使得

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值