关于rabbitmq:PHPRabbitmq复习笔记

前言相干概念音讯(Message)是指在利用间传送的数据。音讯能够非常简单,比方只蕴含文本字符串,也能够更简单,可能蕴含嵌入对象。 音讯队列(Message Queue)是一种利用间的通信形式,音讯发送后能够立刻返回,由音讯零碎来确保音讯的牢靠传递。音讯发布者只管把音讯公布到 MQ 中而不必管谁来取,音讯使用者只管从 MQ 中取音讯而不管是谁公布的。这样发布者和使用者都不必晓得对方的存在。 RabbitMQRabbitMQ 是一个由 Erlang 语言开发的 AMQP 的开源实现。 AMQPAdvanced Message Queue,高级音讯队列协定。 Erlang面向并发的编程语言。 RabbitMQ特点1.可靠性(Reliability) RabbitMQ 应用一些机制来保障可靠性,如长久化、传输确认、公布确认。 2.灵便的路由(Flexible Routing) 在音讯进入队列之前,通过 Exchange 来路由音讯的。对于典型的路由性能,RabbitMQ曾经提供了一些内置的 Exchange 来实现。针对更简单的路由性能,能够将多个Exchange 绑定在一起,也通过插件机制实现本人的 Exchange 。 3.音讯集群(Clustering) 多个 RabbitMQ 服务器能够组成一个集群,造成一个逻辑 Broker 4.高可用(Highly Available Queues) 队列能够在集群中的机器上进行镜像,使得在局部节点出问题的状况下队列依然可用。 5.多种协定(Multi-protocol) RabbitMQ 反对多种音讯队列协定,比方 STOMP、MQTT 等等。 6.多语言客户端(Many Clients) RabbitMQ 简直反对所有罕用语言,比方 Java、.NET、Ruby 等等。 7.治理界面(Management UI) RabbitMQ 提供了一个易用的用户界面,使得用户能够监控和治理音讯 Broker 的许多方面。 8.跟踪机制(Tracing) 如果音讯异样,RabbitMQ 提供了音讯跟踪机制,使用者能够找出产生了什么。 9.插件机制(Plugin System) RabbitMQ 提供了许多插件,来从多方面进行扩大,也能够编写本人的插件。 概念模型 Message音讯,音讯是不具名的,它由音讯头和音讯体组成。音讯体是不通明的,而音讯头则由一系列的可选属性组成,这些属性包含routing-key(路由键)、priority(绝对于其余音讯的优先权)、delivery-mode(指出该音讯可能须要持久性存储)等。Publisher音讯的生产者,也是一个向交换器公布音讯的客户端应用程序。Exchange交换器,用来接管生产者发送的音讯并将这些音讯路由给服务器中的队列。 Direct Exchange:直连交换机,依据Routing Key(路由键)进行投递到不同队列。Fanout Exchange:扇形交换机,采纳播送模式,依据绑定的交换机,路由到与之对应的所有队列。Topic Exchange:主题交换机,对路由键进行模式匹配后进行投递,符号#示意一个或多个词,*示意一个词。Header Exchange:头交换机,不解决路由键。而是依据发送的音讯内容中的headers属性进行匹配。Binding绑定,用于音讯队列和交换器之间的关联。一个绑定就是基于路由键将交换器和音讯队列连接起来的路由规定,所以能够将交换器了解成一个由绑定形成的路由表。 ...

August 27, 2023 · 7 min · jiezi

关于rabbitmq:docker-搭建rabbitmq

应用docker查问rabbitmq的镜像 docker search rabbitmq装置指定版本的rabbitmq docker run -it --rm --name rabbitmq -p 5672:5672 -p 15672:15672 rabbitmq:3.12-management查看是否胜利启动 docker ps 云服务器增加 15672 端口拜访权限 下载提早队列插件 https://github.com/rabbitmq/rabbitmq-delayed-message-exchange/releases将下载的文件复制到容器内 docker cp /home/www/rabbitmq_delayed_message_exchange-3.12.0.ez mq:/plugins 装置插件rabbitmq-plugins enable rabbitmq_delayed_message_exchange 装置胜利

August 18, 2023 · 1 min · jiezi

关于rabbitmq:rabbitmq初始化命令

囧前两天在配置rabbitmq环境的时候,遇到一个难堪的问题。居然不会用命令行创立vhost,用户,以前总是通过治理端间接创立。在此记录下命令行操作,以便后续应用。 vhost操作#查看vhostrabbitmqctl list_vhosts#增加vhostrabbitmqctl add_vhost {vhost}#删除vhostrabbitmqctl delete_vhost {vhost}用户操作#查看用户rabbitmqctl list_users#增加用户rabbitmqctl add_user {用户名} {明码}#批改明码rabbitmqctl change_password {用户名} {明码}#设置权限rabbitmqctl set_user_tags {用户名} {权限}#删除用户rabbitmqctl delete_user {用户名}#验证用户rabbitmqctl authenticate_user {用户名} {明码}用户vhost权限#给用户赋予vhost权限rabbitmqctl set_permissions -p {用户名} {vhost} '.*' '.*' '.*'#革除权限rabbitmqctl clear_permissions -p {vhost} {用户名}#vhost的权限rabbitmqctl list_permissions -p {vhost}#用户权限rabbitmqctl list_user_permissions {用户名}

July 1, 2023 · 1 min · jiezi

关于rabbitmq:如何在宝塔上使用RabbitMQ

前言:有些人为了让我的项目疾速上线,服务器往往装置宝塔面板,而后再极速装置LNMP。只管环境搭建的工夫省了,然而宝塔上PHP中扩大包没有提供AMQP。这时候只是为了应用音讯队列而对PHP大动干戈, 不如应用一个PHP AMQP的库,即用即装,不对环境造成影响。  简介:php-amqplib 客户端库,通过composer装置,不须要在PHP中装置扩大,以下为两种不同的装置形式。 我的项目中新建composer.json,增加如下代码,而后composer install{ "require": { "php-amqplib/php-amqplib": " 2.6.*" }}命令进入到我的项目,而后 composer require php-amqplib/php-amqplib 2.6.* RabbitMQ设置:进入web管控台,增加新用户,角色管理员,任何IP上都能够登录,受权指定虚拟机。 增加交换机 增加队列并与交互机绑定。 编码:1. 封装rabbitMQ类。<?phpuse PhpAmqpLib\Connection\AMQPStreamConnection;use PhpAmqpLib\Message\AMQPMessage;/** * Class RabbitMQ. */class RabbitMQ{ const READ_LINE_NUMBER = 0; const READ_LENGTH = 1; const READ_DATA = 2; public $config; public static $prefix = 'autoinc_key:'; protected $exchangeName = 'flow'; protected $queueName = 'flow_queue'; /** * @var \PhpAmqpLib\Connection\AMQPStreamConnection */ protected $connection; /** * @var \PhpAmqpLib\Channel\AMQPChannel */ protected $channel; protected $queue; //配置项 private $host; private $port; private $user; private $pass; private $vhost; public function __construct($config = []) { //$this->config = $config; //设置rabbitmq配置值 $this->host = '192.168.1.101'; $this->port = 5672; $this->user = 'beiqiaosu'; $this->pass = 'beiqiaosu'; $this->vhost = 'report'; $this->connect(); } public function __call($method, $args = []) { $reConnect = false; while (1) { try { $this->initChannel(); $result = call_user_func_array([$this->channel, $method], $args); } catch (\Exception $e) { //已重连过,依然报错 if ($reConnect) { throw $e; } \Swoole::$php->log->error(__CLASS__ . ' [' . posix_getpid() . "] Swoole RabbitMQ[{$this->config['host']}:{$this->config['port']}] Exception(Msg=" . $e->getMessage() . ', Code=' . $e->getCode() . "), RabbitMQ->{$method}, Params=" . var_export($args, 1)); if ($this->connection) { $this->close(); } $this->connect(); $reConnect = true; continue; } return $result; } //不可能到这里 return false; } /** * 连贯rabbitmq音讯队列. * * @return bool */ public function connect() { try { if ($this->connection) { unset($this->connection); } $this->connection = new AMQPStreamConnection($this->host, $this->port, $this->user, $this->pass, $this->vhost); } catch (\Exception $e) { echo __CLASS__ ."Swoole RabbitMQ Exception'".$e->getMessage(); return false; } } /** * 敞开连贯. */ public function close() { $this->channel->close(); $this->connection->close(); } /** * 设置交换机名称. * * @param string $exchangeName */ public function setExchangeName($exchangeName = '') { $exchangeName && $this->exchangeName = $exchangeName; } /** * 设置队列名称. * * @param string $queueName */ public function setQueueName($queueName = '') { $queueName && $this->queueName = $queueName; } /** * 设置频道. */ public function initChannel() { if (!$this->channel) { //通道 $this->channel = $this->connection->channel(); $this->channel->queue_declare($this->queueName, false, true, false, false); $this->channel->exchange_declare($this->exchangeName, 'direct', false, true, false); $this->channel->queue_bind($this->queueName, $this->exchangeName); } } /** * 获取队列数据. * * @return mixed */ public function pop() { while (1) { try { $this->connect(); $this->initChannel(); $message = $this->channel->basic_get($this->queueName); if ($message) { $this->channel->basic_ack($message->delivery_info['delivery_tag']); $result = $message->body; } else { throw new \Exception('Empty Queue Data'); } } catch (\Exception $e) { //\Swoole::$php->log->error(__CLASS__ . " [" . posix_getpid() . "] Swoole RabbitMQ[{$this->config['host']}:{$this->config['port']}] Exception(Msg=" . $e->getMessage() . ", Code=" . $e->getCode() . ")"); sleep(1); continue; } return $result; } //不可能到这里 return false; } /** * 插入队列数据. * * @param $data * * @return bool */ public function push($data) { while (1) { try { $this->connect(); $this->initChannel(); $message = new AMQPMessage($data, ['content_type'=>'text/plain', 'devlivery_mode' => AMQPMessage::DELIVERY_MODE_PERSISTENT]); $this->channel->basic_publish($message, $this->exchangeName); } catch (\Exception $e) { echo "$e->getMessage()"; continue; } return true; } //不可能到这里 return false; }}2. 操作mq,出队,入队。<?phprequire_once "vendor/autoload.php";require_once "component/RabbitMQ.php";$mq = new RabbitMQ();// 音讯生产测试/*try { $res = $mq->pop(); }catch(\Exception $e) { var_dump($e->getMessage());die;}*/// 音讯生产测试try { $res = $mq->push(json_encode(['name'=>'beiqiaosu','order_id'=>'2020070115261425155'])); }catch(\Exception $e) { var_dump($e->getMessage());die;}var_dump($res);die;测试:先通过生产音讯(入队)办法运行一下,而后进入队列中get message查看音讯总数。 ...

May 27, 2023 · 3 min · jiezi

关于rabbitmq:RabbitMQ死信队列实战

前言:之前有写过死信队列的应用场景以及通过管控台创立死信。这次就通过代码实现死信队列的创立,同时也分享一下RabbitMQ封装的类。  筹备:先筹备一个死信队列(最初用来生产)的参数配置,包含虚拟机,交换机,队列,无效工夫等,如下。 依照下面在RabbitMQ中创立虚拟机和交换机,死信队列。并让交换机与死信队列绑定,操作方法后面有介绍。 这里就间接提供rabbitMQ操作的根本封装的类,包含一个基类,生产者类,消费者类。3.1. 基类。3.2. 生产者类。 3.3. 消费者。 <?phpnamespace rabbitmq;class ConsumerMQ extends BaseMQ{ /** 承受音讯 如果终止 重连时会有音讯 * @throws \AMQPChannelException * @throws \AMQPConnectionException * @throws \AMQPExchangeException * @throws \AMQPQueueException */ public function run($processMessage) { // 创立交换机 $ex = $this->exchange(); // direct类型 $ex->setType(AMQP_EX_TYPE_DIRECT); // 长久化 $ex->setFlags(AMQP_DURABLE); // 不存在就公布 $ex->declareExchange(); // 创立队列 $q = $this->queue(); // 设置队列名称 $q->setName($this->queue); // 长久化 $q->setFlags(AMQP_DURABLE); // 队列参数 is_array($this->queueArgs) && $q->setArguments($this->queueArgs); //echo "Message Total:".$q->declareQueue()."\n"; $q->declareQueue(); //绑定交换机与队列,并指定路由键 // echo 'Queue Bind: '.$q->bind($this->exchange, $this->route)."\n"; $q->bind($this->exchange, $this->route); //阻塞模式接管音讯 // echo "Message:\n"; if (!is_null($processMessage)) { while (True) { $q->consume($processMessage); } } $this->close(); }}编码:下面的死信队列曾经创立好了,接下来次要就是通过代码创立一个用于间接生产音讯的一般队列,然而这个队列须要设置三个参数。 ...

May 27, 2023 · 2 min · jiezi

关于rabbitmq:RabbitMQ死信队列的场景应用

前言:之前也通过文章介绍过rabbitMQ的搭建以及在PHP开发场景下的一些应用。这个次要从rabbitMQ的web控制台介绍死信队列的操作,以及代码层面的小利用等。对于死信的原理,rabbitMQ的个性等能够在其余文章中找到,这里就不具体介绍了。  场景:死信的场景次要是用于来实现提早队列,比方之前介绍的redis订阅的过期事件。都是用于在将来某个时间段须要对某些数据进行操作(删除/更新),就比方某些订单创立胜利后增加到一个队列中。程序生产掉一部分曾经领取过的订单,而那些未领取状态并且超过30分钟(举例的超时工夫)就将其放入到提早队列进行批量解决。  死信队列概述:能够把死信队列了解为过滤后的水池,后面的队列就像负责接水的大水池,只有当大水池满了或者过滤筛选过的水才会流入小水池。最初小水池的水再进行饮用或者应用。  流程:创立1个死信交换机(失常创立即可)和一个死信队列(失常创立),二者通过路由键绑定。2. 创立1个业务交换机, 创立一个业务队列,队列关联一个死信交换机及与交换机绑定的一个死信队列路由键。 最初将业务交换机与业务队列绑定。代码只须要对生产音讯到业务队列,生产死信队列的音讯就能够。 步骤:1. 通过搭建的地址xxx.xxx.xxx.xxx:15672进入rabbitMQ的web控制台,新建虚拟机并进入。 新建死信交换机和死信队列,如下的ex_dlx,queue_dlx。 新建业务交换机,和业务队列,队列关联死信交换机。 用代码生产一条音讯,而后查看业务队列是否有新音讯。 两分钟后(创立队列时设置)查看死信队列是否有音讯进来,以下示意死信队列曾经有新音讯。 最初对死信队列的音讯用代码进行生产了,示意曾经过期的数据。

May 27, 2023 · 1 min · jiezi

关于rabbitmq:RabbitMQ业务解耦实战

前言:上次介绍了RabbitMQ在windows下的装置,以及PHP的AMQP扩大的增加。这里将本地测试的代码放到了服务,所以也就是在Linux上再装一遍。然而这里就省掉间接进入应用。次要是RabbitMQ装置结束后,管控台的应用以及在PHP中如何调用其接口实现音讯的生产和生产。  步骤:1. Linux装置完rabbitMQ后,没有配置文件,须要将rabbitmq.conf.example复制下载下来改为rabbitmq.conf。 2. 能够批改默认Vhost和管理员默认账号密码,最重要的是要将管理员凋谢给所有IP都能够登录(默认是只能是本地能够登录),批改形式如下。 3. 进入到管控台后,先创立vhost,点击admin,侧栏框点击Virtual Hosts。 4. 增加Exchanges,先抉择对应的Vhost 5. 增加队列,抉择Queues,抉择对应的Vhost 6. 队列增加结束后抉择其中一个增加的名称进入。 7. 绑定之前的Exchanges中其中一个,输出exchanges名字和自定义一个路由Key。  8. 胜利后就能够通过PHP代码生产音讯到该虚拟机,而后通过交换机路由到该队列中。  <?phpnamespace rabbitmq;class Amq{ /** * @var object 对象实例 */ protected static $instance; protected $exchange='router_visit'; // 交换机(须要在队列中绑定) protected $queue ='visit_log'; // 队列 protected $route ='router_visit'; // 路由key(须要在队列中绑定) protected $consumer_tag='consumer'; protected $config = [ 'host' => '146.53.206.264', 'port' => 5672, 'login' => 'guest', //guest 'password' => 'guest', //Na18gR@9tf 'vhost' => 'log', 'amqp_debug' => true ]; protected $exchange_index = 0; protected $exchange_type = [ 'direct', 'fanout', 'topic', 'headers' ]; /** * @note 实例化 * @author: beiqiaosu * @since: 2019/11/13 16:10 */ public static function getInstance() { if (!(self::$instance instanceof self)) { self::$instance = new self(); } return self::$instance; } /** * @Notes: 音讯生产 */ public function publisher($message,$config=[]) { //如果有配置就用新配置 $this->config ['vhost'] = $config['vhost']?? $this->config ['vhost']; $this->exchange = $config['exchange']?? $this->exchange; $this->queue = $config['queue']?? $this->queue; $this->consumer_tag = $config['consumer_tag']?? $this->consumer_tag; $this->route = $config['route']?? $this->route; $this->exchange_index = $config['exchange_index']?? $this->exchange_index; $cnn = new \AMQPConnection($this->config); if (!$cnn->connect()) { echo "Cannot connect to the broker"; exit(); } $channel = new \AMQPChannel($cnn); $ex = new \AMQPExchange($channel); $ex->setName($this->exchange); $ex->setType(AMQP_EX_TYPE_DIRECT); //direct类型 $ex->setFlags(AMQP_DURABLE); //长久化 $ex->declareExchange(); return "Send Message:".$ex->publish($message, $this->route, AMQP_NOPARAM, array('delivery_mode' => 2))."\n"; } /** * @note 生产 * @author: tata * @since: 2019/11/13 16:10 */ public function consumer() { $exchange='router_visit'; //交换机 $queue ='visit_log'; //队列 $route ='router_visit'; //路由 //连贯broker $cnn = new \AMQPConnection($this->config); if (!$cnn->connect()) { echo "Cannot connect to the broker"; exit(); } $channel = new \AMQPChannel($cnn); $ex = new \AMQPExchange($channel); //设置交换机名称 $ex->setName($exchange); //设置交换机类型 //AMQP_EX_TYPE_DIRECT:直连交换机 //AMQP_EX_TYPE_FANOUT:扇形交换机 //AMQP_EX_TYPE_HEADERS:头交换机 //AMQP_EX_TYPE_TOPIC:主题交换机 $ex->setType(AMQP_EX_TYPE_DIRECT); //设置交换机长久 $ex->setFlags(AMQP_DURABLE); //申明交换机 $ex->declareExchange(); //创立一个音讯队列 $q = new \AMQPQueue($channel); //设置队列名称 $q->setName($queue); //设置队列长久 $q->setFlags(AMQP_DURABLE); //申明音讯队列 //$q->declareQueue(); //交换机和队列通过$route进行绑定 $q->bind($exchange, $route); $ret = $q->consume(function($envelope, $queue) { // 取出音讯主题转为数组// $origin_data = json_decode($envelope->getBody(),true);// dump($envelope->getBody());die; /**对音讯主题执行业务**/ $res = true; /**对音讯主题执行业务**/ // 业务处理完毕发送给MQ生产掉该音讯 if ($res) $queue->ack($envelope->getDeliveryTag()); //手动发送ACK应答 }); dump($ret);die; $cnn->disconnect(); }} 9. 每执行一次生产或生产代码,能够在Queue中的统计或图表中看到,测试代码是否胜利。  ...

May 27, 2023 · 2 min · jiezi

关于rabbitmq:Windows下RabbitMQ环境搭建

前言:最近的PHP我的项目中有应用AMQP,解耦一些业务性的功能模块。因为工作应用的是线上Linux搭建,为了不便测试所以我决定本地搭建一个MQ服务。  RabbitMQ简介:MQ全称为Message Queue, 音讯队列(MQ)是一种应用程序对应用程序的通信办法。应用程序通过读写出入队列的音讯(针对应用程序的数据)来通信,而无需专用连贯来链接它们。 RabbitMQ是一个在AMQP根底上实现的,是生产-生产者模型的一个典型的代表,一端往音讯队列中一直写入音讯,而另一端则能够读取或者订阅队列中的音讯。  装置过程:下载并装置Erlang,举荐版本otp_win64_22.2。下载安装RabbitMQ Server,举荐rabbitmq-server-3.8.3。下载安装LAMP环境,举荐PhpSudy v8.1。4.  下载并配置PHP的AMQP扩大。一. 下载安装Erlang1. 进入erlang官网抉择downloads而后抉择版本点击下载。 2. 下载完后间接装置,而后点击电脑属性配置环境变量,如下图。 3. 查看是否装置胜利,进入cmd,输出erl看到版本就能够。 二. 下载安装RabbitMQ Server1. 进入官网,点击download。 2. 下载结束后,通过cmd进入装置目录的sbin。 3. 进入cmd面板,输出“rabbitmq-plugins enable rabbitmq_management”,启动插件。 4. 开启RabbitMQ Server,而后浏览器中输出127.0.0.1:15672 5. 看到下图界面就胜利了,默认账号密码都是guest,而后登陆即可。 三. 下载并装置PHP的AMQP扩大1. 下载安装好phpstudy v8.1,这里只是举荐也能够是其余的。2. 进入PHP扩大网站找到AMQP及与以后PHP对应版本的包下载。 3. php版本,X86和X64依据本人状况 NTS和TS就是那个thread safty的状态。 4. php_amqp.dll放在php的ext中rabbitmq.4.dll放在PHP同级目录下。 5. php.ini外面增加    extension=php_amqp.dll 6. apache 批改http.conf文件 增加   LoadFile  "D:/XAMPP/php/rabbitmq.4.dll" (目录门路自行批改)。 7. 重启Apache进入phpinfo查看是否有AMQP模块  

May 27, 2023 · 1 min · jiezi

关于rabbitmq:用-dockercompose-搭建一个-rabbitmq-集群

当您应用Docker Compose时,能够应用RabbitMQ的官网Docker镜像来构建RabbitMQ集群。上面是一个简略的docker-compose.yml文件示例,用于启动一个由3个RabbitMQ节点组成的集群: version: '3'services: rabbitmq-node1: image: rabbitmq:3.9.5-management-alpine environment: - RABBITMQ_ERLANG_COOKIE=cookie - RABBITMQ_NODENAME=rabbit@rabbitmq-node1 - RABBITMQ_USE_LONGNAME=true ports: - 5672:5672 - 15672:15672 volumes: - rabbitmq-node1-data:/var/lib/rabbitmq networks: rabbitmq-network: aliases: - rabbitmq-node1 rabbitmq-node2: image: rabbitmq:3.9.5-management-alpine environment: - RABBITMQ_ERLANG_COOKIE=cookie - RABBITMQ_NODENAME=rabbit@rabbitmq-node2 - RABBITMQ_USE_LONGNAME=true - RABBITMQ_CLUSTER_NODE_TYPE=disc - RABBITMQ_CLUSTER_DISC_RAM_NODE_NAME=rabbit@rabbitmq-node1 volumes: - rabbitmq-node2-data:/var/lib/rabbitmq networks: rabbitmq-network: aliases: - rabbitmq-node2 rabbitmq-node3: image: rabbitmq:3.9.5-management-alpine environment: - RABBITMQ_ERLANG_COOKIE=cookie - RABBITMQ_NODENAME=rabbit@rabbitmq-node3 - RABBITMQ_USE_LONGNAME=true - RABBITMQ_CLUSTER_NODE_TYPE=disc - RABBITMQ_CLUSTER_DISC_RAM_NODE_NAME=rabbit@rabbitmq-node1 volumes: - rabbitmq-node3-data:/var/lib/rabbitmq networks: rabbitmq-network: aliases: - rabbitmq-node3volumes: rabbitmq-node1-data: rabbitmq-node2-data: rabbitmq-node3-data:networks: rabbitmq-network:在这个示例中,咱们定义了三个RabbitMQ节点:rabbitmq-node1,rabbitmq-node2和rabbitmq-node3,它们都运行RabbitMQ官网Docker镜像(带有RabbitMQ治理插件)。咱们应用了Docker Compose的networks配置项,将所有节点连贯到同一个网络中,并指定了每个节点的别名。咱们还应用了volumes配置项,为每个节点挂载了一个数据卷,用于长久化RabbitMQ数据。 ...

May 7, 2023 · 1 min · jiezi

关于rabbitmq:RabbitMQ源码安装

RabbitMQ官网:https://www.rabbitmq.com/ 1.环境阐明root@xjr-pc:/etc/init.d# lsb_release -aNo LSB modules are available.Distributor ID: UbuntuDescription: Ubuntu 18.04.1 LTSRelease: 18.04Codename: bioniclinux版本:Ubuntu 18.04.1 LTSerlang版本:erlang-24.0rabbitmq版本:rabbitmq_server-3.9.192. 源码装置Erlang,RabbitMQRabbitmq采纳erlang语言开发,所以在装置rabbitmq之前,须要装置erlang。2.1. 下载Erlang 和 RabbitMQ源码包Erlang官网下载地址:http://www.erlang.org/download 抉择opt_src_版本号.tar.gz(这里我抉择的是 otp_src_24.0.tar.gz) Linux服务器上应用 wget http://www.erlang.org/download/otp_src_24.0.tar.gz 进行下载 wget http://www.erlang.org/download/otp_src_24.0.tar.gzRabbitMQ官网下载:https://www.rabbitmq.com/download.html Linux 服务器上通过 wget 下载: wget https://github.com/rabbitmq/rabbitmq-server/releases/download/v3.9.19/rabbitmq-server-generic-unix-3.9.19.tar.xz2.2. 装置Erlang上传并解压 Erlang 安装包root@xjr-pc:/www/server/src# pwd/www/server/srcroot@xjr-pc:/www/server/src# tar -zxvf otp_src_24.0.tar.gzroot@xjr-pc:/www/server/src# lltotal 102300drwxr-xr-x 3 root root 4096 May 4 04:07 ./drwxr-xr-x 12 root root 4096 May 4 03:45 ../drwxr-xr-x 12 2004 uucp 4096 May 11 2021 otp_src_24.0/-rw-r--r-- 1 root root 101193664 May 12 2021 otp_src_24.0.tar.gz编译装置Erlang#创立Erlang装置目录root@xjr-pc:/www/server# mkdir -p /www/server/erlang#进入otp_src_24目录(解压目录)root@xjr-pc:/www/server/src/otp_src_24.0# pwd/www/server/src/otp_src_24.0root@xjr-pc:/www/server/src/otp_src_24.0# ./configure prefix=/www/server/erlangroot@xjr-pc:/www/server/src/otp_src_24.0# make && make install#装置实现后进入装置门路目录root@xjr-pc:/www/server/erlang# pwd/www/server/erlangroot@xjr-pc:/www/server/erlang# lltotal 16drwxr-xr-x 4 root root 4096 May 4 04:18 ./drwxr-xr-x 13 root root 4096 May 4 04:10 ../drwxr-xr-x 2 root root 4096 May 4 04:19 bin/drwxr-xr-x 3 root root 4096 May 4 04:18 lib/配置环境变量 和 查看 Erlang 是否装置胜利#将Erlang装置门路/bin 增加到环境变量root@xjr-pc:/etc/profile.d# pwd/etc/profile.droot@xjr-pc:/etc/profile.d# cat erlang.shERLANG_HOME=/www/server/erlangPATH=$PATH:$ERLANG_HOME/binexport PATHroot@xjr-pc:/etc/profile.d# source /etc/profile# 运行erl root@xjr-pc:/etc/profile.d# erlErlang/OTP 24 [erts-12.0] [source] [64-bit] [smp:16:16] [ds:16:16:10] [async-threads:1] [jit]Eshell V12.0 (abort with ^G)1> halt().root@xjr-pc:/etc/profile.d#2.3. 装置RabbitMQ装置RabbitMQ前须要确认erlang装置胜利# 解压 rabbitmq-server-generic-unix-3.9.19.tar.xzroot@xjr-pc:/www/server/src# xz -d rabbitmq-server-generic-unix-3.9.19.tar.xzroot@xjr-pc:/www/server/src# tar -xvf rabbitmq-server-generic-unix-3.9.19.tarroot@xjr-pc:/www/server/src# mv rabbitmq-server-generic-unix-3.9.19 /www/server/rabbitmq# 配置 RabbitMQ 环境变量root@xjr-pc:/etc/profile.d# pwd/etc/profile.droot@xjr-pc:/etc/profile.d# cat rabbitmq.shRABBITMQ_HOME=/www/server/rabbitMQPATH=$PATH:$RABBITMQ_HOME/sbinexport PATHroot@xjr-pc:/etc/profile.d# source /etc/profile# 后盾启动RabbitMQroot@xjr-pc:/www/server# rabbitmq-server -detached# 查看端口 5672 存在示意启动胜利root@xjr-pc:/www/server# ss -tnlp|grep 5672LISTEN 0 128 0.0.0.0:25672 0.0.0.0:* users:(("beam.smp",pid=11688,fd=19))LISTEN 0 128 *:5672 *:* users:(("beam.smp",pid=11688,fd=34))# 增加rabbitmq浏览器治理插件root@xjr-pc:/www/server# rabbitmq-plugins enable rabbitmq_management# RabbitMQ有默认用户名明码 guest/guest,该用户名明码只能在本地登陆# 如若在浏览器中登陆,须新创建用户名明码# 增加用户名明码root@xjr-pc:/www/server# rabbitmqctl add_user root P@ssw0rd# 检查用户列表root@xjr-pc:/www/server# rabbitmqctl list_usersListing users ...user tagsguest [administrator]rabbitmq_user []# 为 root 用户增加administrator角色root@xjr-pc:/www/server# rabbitmqctl set_user_tags root administrator# 设置 root 用户权限,容许拜访vhost及read/writeroot@xjr-pc:/www/server# rabbitmqctl set_permissions -p / root# 查看权限列表root@xjr-pc:/www/server# rabbitmqctl list_permissions -p /Listing permissions for vhost "/" ...user configure write readguest .* .* .*root .* .* .*# 启动音讯队列服务rabbitmqctl start_app# 验证15672端口存在示意音讯队列服务启动胜利ss -tnlp | grep 156722.4. Rabbitmq 配置systemctl启动1. 编辑service文件 ...

May 4, 2023 · 2 min · jiezi

关于rabbitmq:如何保证-RabbitMQ-的消息可靠性

前言我的项目开发中常常会应用音讯队列来实现异步解决、利用解耦、流量管制等性能。尽管音讯队列的呈现解决了一些场景下的问题,然而同时也引出了一些问题,其中应用音讯队列时如何保障音讯的可靠性就是一个常见的问题。如果在我的项目中遇到须要保障音讯肯定被生产的场景时,如何保障音讯不失落,如何保障音讯的可靠性? 最近在写我的项目时应用 RabbitMQ 音讯队列中间件时也遇到了须要保障音讯可靠性的场景,所以将如何放弃音讯可靠性的计划记录下来,上面将解说一下如何保障 RabbitMQ 的音讯可靠性。 如何保障 RabbitMQ 的音讯可靠性先放一张 RabbitMQ 是如何消息传递的图: 生产者Producer 将音讯发送到指定的 交换机Exchange,交换机依据路由规定路由到绑定的 队列Queue 中,最初和消费者建设连贯后,将音讯推送给 消费者Consumer。 那么音讯会在哪些环节失落呢,列出可能呈现音讯失落的场景有: 生产者将音讯发送到 RabbitMQ Server 异样:可能因为网络问题造成 RabbitMQ 服务端无奈收到音讯,造成生产者发送音讯失落场景。RabbitMQ Server 中音讯在交换机中无奈路由到指定队列:可能因为代码层面或配置层面谬误导致音讯路由到指定队列失败,造成生产者发送音讯失落场景。RabbitMQ Server 中存储的音讯失落:可能因为 RabbitMQ Server 宕机导致音讯未齐全长久化或队列失落导致音讯失落等长久化问题,造成 RabbitMQ Server 存储的音讯失落场景。消费者生产音讯异样:可能在消费者接管到音讯后,还没来得及生产音讯,消费者宕机或故障等问题,造成消费者无奈生产音讯导致音讯失落的场景。以上就是 RabbitMQ 可能呈现音讯失落的场景,接下来将顺次解说如何防止这些音讯失落的场景问题。 因为在我的项目开发中应用的是 RabbitMQ,所以应用 Spring Boot 集成的 AMQP 依赖即可应用 RabbitMQ。 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId></dependency>1. 保障生产者发送音讯到 RabbitMQ Server为了防止因为网络故障或闪断问题导致音讯无奈失常发送到 RabbitMQ Server 的状况,RabbitMQ 提供了两种计划让生产者能够感知到音讯是否正确无误的发送到 RabbitMQ Server中,这两种计划别离是 事务机制 和 发送方确认机制。上面别离介绍一下这两种机制如何实现。 事务机制先说配置和应用: 配置类中配置事务管理器 /** * 音讯队列配置类 * * @author 单程车票 */@Configurationpublic class RabbitMQConfig { /** * 配置事务管理器 */ @Bean public RabbitTransactionManager transactionManager(ConnectionFactory connectionFactory) { return new RabbitTransactionManager(connectionFactory); }}通过增加事务注解 + 开启事务实现事务机制 ...

May 4, 2023 · 4 min · jiezi

关于rabbitmq:分布式系统的心跳方向性

kafka server 集群Q:kafka server 集群的心跳包是谁发给谁? A:在 Kafka 集群中,Kafka broker 会周期性地向 ZooKeeper 发送心跳申请,以表明本人依然处于运行状态,并更新它在 ZooKeeper 上的元数据。同时,Kafka producer 和 consumer 也会向 broker 发送心跳申请,以确保它们与 broker 之间的连贯放弃沉闷,同时通知 broker 它们仍在运行。 Q:kafka server 和 client 之间有心跳吗? A:是的,在 Kafka 中,Kafka broker 与 Kafka producer 和 consumer 之间都会有心跳。Kafka producer 和 consumer 会周期性地向 broker 发送心跳申请,以通知 broker 它们仍在运行,并须要继续地发送或接管音讯。如果 broker 在肯定工夫内没有收到来自 producer 或 consumer 的心跳,它将认为该 producer 或 consumer 曾经宕机,并将其标记为不可用,而后将其负责的 partition 调配给其余的 producer 或 consumer 进行解决。这个心跳机制的作用是放弃 producer 和 consumer 与 broker 之间的连贯沉闷,并且可能及时检测到它们的宕机,以便 broker 能够采取相应的措施,保障音讯的牢靠传输。 ...

March 12, 2023 · 2 min · jiezi

关于rabbitmq:Docker安装RabbitMQ

下载镜像docker pull rabbitmq:3.11-management 启动即可docker run -d --name rabbitmq -p 5672:5672 -p 15672:15672 -e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=123456 rabbitmq:3.11-management 拜访http://127.0.0.1:15672应用admin 123456登录

March 10, 2023 · 1 min · jiezi

关于rabbitmq:RabbitMQ-延迟消息实战

RabbitMQ 提早音讯实战RabbitMQ Assistant 是一款 RabbitMQ 可视化治理与监控——深刻理解您的队列、订阅与生产音讯,展现残缺的音讯流图以及压力测试。 现实生活中有一些场景须要提早或在特定工夫发送音讯,例如智能热水器须要 30 分钟后关上,未领取的订单或发送短信、电子邮件和推送告诉下午 2:00 开始的促销流动。 RabbitMQ 自身没有间接反对提早队列的性能,如果您搜寻“如何在 RabbitMQ 中应用提早音讯”,您很可能会遇到两种可能的解决方案。第一种解决方案是应用音讯 TTL 性能和死信性能的组合。第二种抉择是应用官网的 RabbitMQ 提早音讯插件。 本文具体介绍了 RabbitMQ 提早音讯。 [TOC] 什么是 RabbitMQ?RabbitMQ 是一个开源音讯代理(也称为面向音讯的中间件),创立它是为了反对高级音讯队列协定 (Advanced Message Queuing Protocol, AMQP)。尔后,它通过插件架构进行了扩大,以反对简略(或流式)面向文本的音讯协定 (Text Oriented Message Protocol, STOMP)、音讯查问遥测传输 (Message Query Telemetry Transport, MQTT) 等协定。 对于集群和故障转移,RabbitMQ 服务器是用 Erlang 编写的,并采纳了凋谢电信平台框架。用于与代理交互的客户端库可用于所有次要编程语言,源代码可在 Mozilla 公共许可证下取得。 简略来说,RabbitMQ是一个消息传递零碎,能够在本地或云端应用。并且反对多种消息传递协定。 RabbitMQ 的次要个性以下是 RabbitMQ 的一些个性: 集群:RabbitMQ 中的集群在设计时思考了两个指标。如果一个节点产生故障,事件的消费者和生产者能够持续运行,同时增加其余节点以横向扩大消息传递吞吐量。轻松路由:音讯通过交换器而后达到队列,这提供了灵便的路由形式。 对于更简单的路由,用户能够将交换器连贯在一起或将他们的交换器类型开发为插件。可靠性:持久性、交付反馈、公布确认和高可用性是 RabbitMQ 对性能有间接影响的要害个性。安全性:客户端证书检查和仅 SSL 通信能够帮忙爱护客户端连贯。虚拟主机能够调节用户拜访,确保高级音讯隔离。在 RabbitMQ 中启用提早音讯很长一段时间以来,人们始终在寻找应用 RabbitMQ 实现提早消息传递的办法。 迄今为止,公认的解决方案是应用音讯的组合——TTL 和死信交换器。 RabbitMQ 提早音讯插件向 RabbitMQ 增加了一种新的替换类型,如果用户违心,容许提早通过该替换路由的音讯。 让咱们看看如何应用这两种办法。 ...

February 23, 2023 · 2 min · jiezi

关于rabbitmq:为-RabbitMQ-服务器启用-SSLTLS

为 RabbitMQ 服务器启用 SSL/TLS[TOC] 为客户端和服务器生成自签名证书为了启用 TLS/SSL,咱们须要证书/密钥对。 这能够借助 OpenSSL 为客户端和服务器生成自签名证书。 生成自签名CA证书 咱们当初将应用 OpenSSL 创立所有必须的密钥和证书。 让咱们开始创立 CA 证书。 确保所有证书都放在以下目录中: cd /home/chen/rabbitmq_server-3.11.6/ssl第一步是制作根私钥: openssl genrsa -out RMQ-CA-Key.pem下一步是签订证书。 openssl req -new -key RMQ-CA-Key.pem -x509 -days 100 -out RMQ-CA-cert.pem运行上述命令后,交互式脚本将启动并询问各种信息。 咱们将在此处提供所有必须的详细信息。 输出Common-Name (CN) 时须要留神要应用服务器 IP 或 hostname。 实现后,这将生成根 CA 证书。 当初,咱们将创立服务器密钥和服务器证书。 生成服务器密钥 openssl genrsa -out RMQ-server-key.pem生成 CSR(证书签名申请): openssl req -new -key RMQ-server-key.pem -out RMQ-signingrequest.csr当咱们运行下面的命令时,它会询问各种参数(Country、State、ON、OU 等),咱们还须要抉择一个 common name (CN)。 这最好是服务器的 IP 或 hostname。 生成自签名证书 openssl x509 -req -days 100 -in RMQ-signingrequest.csr -CA RMQ-CA-cert.pem -CAkey RMQ-CA-Key.pem -CAcreateserial -out RMQ-server-cert.pem最初,咱们须要应用它们来设置 TLS/SSL。 ...

February 18, 2023 · 2 min · jiezi

关于rabbitmq:rabbitmq-重启之后无法登录

遇到一个问题 一个 rabbitmq server 的内存不够了,加了内存之后重启 重启后发现,账号登录不上了! 吓死我 钻研了一下,起因如下: rabbitmq sever 依赖 hostname。机器上的 hostname 没有长久化,重启之后,hostname 变了先来说说第一个问题。 rabbitmq server 的数据长久化存储在 /vobiledata/rabbitmq 目录上面: root@iZbp1ghi852mxfw5grbimsZ:/vobiledata/rabbitmq# lltotal 40Kdrwxr-xr-x 7 rabbitmq rabbitmq 4.0K Feb 17 21:44 .drwxr-xr-x 4 root root 4.0K Feb 24 2022 ..drwxr-x--- 2 rabbitmq rabbitmq 4.0K Feb 17 21:37 logdrwxr-x--- 5 rabbitmq rabbitmq 4.0K Feb 17 21:45 rabbit@iZbp1ghi852mxfw5grbimsZ-rw-r----- 1 rabbitmq rabbitmq 163 Feb 17 21:37 rabbit@iZbp1ghi852mxfw5grbimsZ-feature_flags-rw-r----- 1 rabbitmq rabbitmq 4 Feb 17 21:44 rabbit@iZbp1ghi852mxfw5grbimsZ.piddrwxr-x--- 2 rabbitmq rabbitmq 4.0K Feb 17 21:44 rabbit@iZbp1ghi852mxfw5grbimsZ-plugins-expanddrwxr-x--- 5 rabbitmq rabbitmq 4.0K Feb 17 21:35 rabbit@szbq-rabbitmq-52-rw-r----- 1 rabbitmq rabbitmq 137 Jul 15 2022 rabbit@szbq-rabbitmq-52-feature_flagsdrwxr-x--- 2 rabbitmq rabbitmq 4.0K Feb 17 19:39 rabbit@szbq-rabbitmq-52-plugins-expand重启之前,我的 hostname 是 szbq-rabbitmq-52,重启之后 hostname 变成了 iZbp1ghi852mxfw5grbimsZ,因为 hostname 变了,所以 rabbitmq sevrer 在 /vobiledata/rabbitmq 下又创立了一个对于 iZbp1ghi852mxfw5grbimsZ 的一堆目录,而我之前的数据,包含 excharge、queue、message甚至账号信息都是存储在 rabbit@szbq-rabbitmq-52 相干目录上面的 ...

February 17, 2023 · 1 min · jiezi

关于rabbitmq:rabbitMQ编译安装

rabbitMQ编译装置rpm形式装置rabbitmq依赖erlang环境yum -y install erlang #装置erlang环境erl -versionerlrabbitmq rpm 装置wget http://www.rabbitmq.com/releases/rabbitmq-server/v3.6.6/rabbitmq-server-3.6.6-1.el6.noarch.rpmrpm --nodeps -Uvh rabbitmq-server-3.6.6-1.el6.noarch.rpmservice rabbitmq-server start 启动service rabbitmq-server stop 进行rabbitmqctl status //查看状态rabbitmq-plugins list -e 查看插件装置Web治理界面插件rabbitmq-plugins enable rabbitmq_management编译装置erlangwget http://erlang.org/download/otp_src_19.1.tar.gz #下载erlang包tar -zxvf otp_src_19.1.tar.gzcd otp_src_19.1/./configure --prefix=/apps/erlang_19.1 --with-ssl -enable-threads -enable-smmp-support -enable-kernel-poll --enable-hipe --without-javac报错时装置: yum -y install gcc gcc-c++ ncurses-develmakemake installerl -versionerl编译装置rabbitmqwget http://www.rabbitmq.com/releases/rabbitmq-server/v3.6.6/rabbitmq-server-generic-unix-3.6.6.tar.xzxz -d rabbitmq-server-generic-unix-3.6.6.tar.xztar -xvf rabbitmq-server-generic-unix-3.6.6.tarcd rabbitmq_server-3.6.6/./rabbitmq-server 启动./rabbitmq-server -detached 后盾启动./rabbitmqctl stop 敞开./rabbitmqctl status //查看状态装置Web治理界面插件./rabbitmq-plugins enable rabbitmq_management./rabbitmq-plugins list -e凋谢端口vim /etc/sysconfig/iptables-A INPUT -p tcp -m multiport --dports 5672,15672 -j ACCEPTservice iptables restart浏览器拜访http://192.168.1.239:15672/ ...

December 30, 2022 · 1 min · jiezi

关于rabbitmq:rabbitmq-消费者为什么需要心跳

先明确几点: rabbitmq 的心跳和 amqp 协定有关系,你要是用 rabbitmq 的 http 协定,就没有心跳的概念。所以咱们议论 rabbitmq 的心跳的时候,其实讲的是 amqp 的心跳。因为应用 rabbitmq 的时候, 99%心跳针对的是 amqp 连贯,而不是 channel 哦

November 6, 2022 · 1 min · jiezi

关于rabbitmq:RabbitMQ用户命令策略日志

RabbitMQ创立管理员命令#查看以后用户命令:rabbitmqctl list_users#创立用户和明码rabbitmqctl add_user admin beyond_2021#将用户给于管理员权限 rabbitmqctl set_user_tags admin administrator#查看用户权限 rabbitmqctl list_user_permissions admin#设置用户权限(承受来自所有Host的所有操作) rabbitmqctl set_permissions -p "/" admin '.*' '.*' '.*'RabbitMQ插件#列出插件rabbitmq-plugins list#启用WEB治理界面 rabbitmq-plugins enable rabbitmq_management#启用mqtt插件rabbitmq-plugins enable rabbitmq_mqtt#启用mqtt的websocket插件rabbitmq-plugins enable rabbitmq_web_mqttRabbitMQ策略#TTL政策将删除指定的工夫到期后未应用的队列30分钟. beam.smp high cpu loadrabbitmqctl set_policy expiry ".*" '{"expires":1800000}' --apply-to queues#从队列维度设置音讯超时工夫 60秒:rabbitmqctl set_policy TTL ".*" '{"message-ttl":60000}' --apply-to queuesRabbitMQ日志find / -name rabbitmq-defaults #查看日志vim /var/log/rabbitmq/[email protected] node : [email protected] home dir : /var/lib/rabbitmq config file(s) : (none) (没有配置文件,默认配置) cookie hash : YbgbNbM4sDT9GDbGGGGJTg== log(s) : /var/log/rabbitmq/[email protected] : /var/log/rabbitmq/[email protected]_upgrade.log database dir : /var/lib/rabbitmq/mnesia/[email protected]#批改日志和数据保留目录vim /usr/lib/rabbitmq/lib/rabbitmq_server-3.8.2/sbin/rabbitmq-defaults CONFIG_FILE=${SYS_PREFIX}/etc/rabbitmq/rabbitmqLOG_BASE=/twiot/rabbitmq/var/log/rabbitmqMNESIA_BASE=/twiot/rabbitmq/var/lib/rabbitmq/mnesiaENABLED_PLUGINS_FILE=${SYS_PREFIX}/etc/rabbitmq/enabled_pluginsGENERATED_CONFIG_DIR=${SYS_PREFIX}/var/lib/rabbitmq/configADVANCED_CONFIG_FILE=${SYS_PREFIX}/etc/rabbitmq/advanced.configSCHEMA_DIR=${SYS_PREFIX}/var/lib/rabbitmq/schema也能够 依照模板创立一个rabbitmq.conf ...

October 27, 2022 · 1 min · jiezi

关于rabbitmq:RabbitMQ-MQTT集群方案官方说明

RabbitMQ MQTT 官方网阐明 官网地址: https://www.rabbitmq.com/mqtt... 从3.8开始,该MQTT插件要求存在肯定数量的群集节点。这意味着三分之二,五分之三,依此类推。该插件也能够在单个节点上应用,但不反对两个节点的集群。如果大多数群集节点都敞开,则其余群集节点将无奈承受新的MQTT客户端连贯 必须在所有群集节点上启用该插件。 spring boot mqtt集群配置spring: mqtt: username: guest password: guest #多节点配置 url: tcp://127.0.0.1:1883,tcp://127.0.0.1:1884,tcp://127.0.0.1:1885 client-id: data-clientId server-id: data-serverId data-topic: data/#

October 26, 2022 · 1 min · jiezi

关于rabbitmq:rabbitmq-docker-修改默认配置

留神,rabbitmq 有两个默认配置后缀:conf 和 config有几条事实: 在rabbitmq 3.7.0 之前,rabbitmq.conf 应用了Erlang语法配置格局,新的版本应用了sysctl 格局.conf 和 config 不能够乱用,因为代表的是不同格局,不然会报谬误, 比方把 rabbitmq.conf 命名为 rabbitmq.config 是不可取的:Failed to load advanced configuration file "/etc/rabbitmq/rabbitmq.config": unknown POSIX error参考文章: rabbitmq启动失败-报Failed to load advanced configuration file解决办法RabbitMQ 内存和磁盘正告RabbitMQ 配置文件因为我想批改的就是 vm_memory_high_watermark.relative 这个默认是 0.4,太低了,我想改成 vm_memory_high_watermark.relative = 0.8 所以 docker-compose 就这么写 version: "3"services: rabbitmq3-management: container_name: rabbitmq3-management image: rabbitmq:3-management hostname: rabbitmq3-management-standalone logging: driver: json-file options: max-size: "100m" max-file: "1" environment: - RABBITMQ_DEFAULT_USER=pon - RABBITMQ_DEFAULT_PASS=pon volumes: # - "./volumes:/var/lib/rabbitmq" - "./rabbitmq.conf:/etc/rabbitmq/rabbitmq.conf" ports: - "5672:5672" - "15672:15672" - "15692:15692"rabbitmq.conf 内容如下: ...

October 8, 2022 · 1 min · jiezi

关于rabbitmq:rabbitmq-amqp-协议-Properties-和-headers-的区别

刚刚去谷歌 search 了一下『rabbitmq Properties 和 headers 的区别』,进去的后果没有靠谱的,那就本人写一个吧 能够看到一个一般的 message 只有 Properties,没有 headers 那怎么能力有 headers 呢? with Connection(amqp_uri) as conn: with conn.channel() as channel: started_at = time.time() message = Message(channel=channel, body=data, headers={'retry_count': 1})所以,回到开始的问题:『rabbitmq Properties 和 headers 的区别?』 headers 是 Properties 的子集

September 25, 2022 · 1 min · jiezi

关于rabbitmq:RabbitMQ学习入门

1. 音讯队列1.1 什么是MQMQ(message queue),从字面意思上看实质是个队列,FIFO 先入先出,只不过队列中寄存的内容是 message 而已,还是一种跨过程的通信机制,用于上下游传递音讯。在互联网架构中,MQ 是一种十分常见的上下游“逻辑解耦+物了解耦”的音讯通信服务。应用了 MQ 之后,音讯发送上游只须要依赖 MQ,不必依赖其余服务。 1.2 为什么要用MQ1.2.1 流量消峰举个例子,如果订单零碎最多能解决一万次订单,这个解决能力应酬失常时段的下单时入不敷出,失常时段咱们下繁多秒后就能返回后果。然而在高峰期,如果有两万次下单操作系统是解决不了的,只能限度订单超过一万后不容许用户下单。应用音讯队列做缓冲,咱们能够勾销这个限度,把一秒内下的订单扩散成一段时间来解决,这时有些用户可能在下单十几秒后能力收到下单胜利的操作,然而比不能下单的体验要好。 1.2.2 利用解耦以电商利用为例,利用中有订单零碎、库存零碎、物流零碎、领取零碎。用户创立订单后,如果耦合调用库存零碎、物流零碎、领取零碎,任何一个子系统出了故障,都会造成下单操作异样。当转变成基于音讯队列的形式后,零碎间调用的问题会缩小很多,比方物流零碎因为产生故障,须要几分钟来修复。在这几分钟的工夫里,物流零碎要解决的内存被缓存在音讯队列中,用户的下单操作能够失常实现。当物流零碎复原后,持续解决订单信息即可,中单用户感触不到物流零碎的故障,晋升零碎的可用性。 1.2.3 异步解决有些服务间调用是异步的,例如 A 调用 B,B 须要破费很长时间执行,然而 A 须要晓得 B 什么时候能够执行完,以前个别有两种形式,A 过一段时间去调用 B 的查问 api 查问。或者 A 提供一个 callback api, B 执行完之后调用 api 告诉 A 服务。这两种形式都不是很优雅,应用音讯总线,能够很不便解决这个问题, A 调用 B 服务后,只须要监听 B 解决实现的音讯,当 B 解决实现后,会发送一条音讯给 MQ,MQ 会将此 音讯转发给 A 服务。这样 A 服务既不必循环调用 B 的查问 api,也不必提供 callback api。同样 B 服务也不 用做这些操作。A 服务还能及时的失去异步解决胜利的音讯。 1.3 MQ分类1.3.1 ActiveMQ长处:单机吞吐量万级,时效性 ms 级,可用性高,基于主从架构实现高可用性,音讯可靠性较毛病:官网社区当初对 ActiveMQ 5.x 保护越来越少,高吞吐量场景较少应用。1.3.2 Kafka大数据的杀手锏,谈到大数据畛域内的音讯传输,则绕不开 Kafka,这款为大数据而生的消息中间件, 以其百万级 TPS 的吞吐量名声大噪,迅速成为大数据畛域的宠儿,在数据采集、传输、存储的过程中施展着无足轻重的作用。目前曾经被 LinkedIn,Uber, Twitter, Netflix 等大公司所驳回。 ...

September 24, 2022 · 2 min · jiezi

关于rabbitmq:rabbitmq原理和应用

0.1、索引https://blog.waterflow.link/articles/1663772504649 RabbitMQ 是一个轻量级且易于部署的音讯队列。它反对开箱即用的多种消息传递协定。咱们将应用 AMQP(高级音讯队列协定) 1、概念 既然是音讯队列,顾名思义,必定会有生产者生产音讯,消费者生产音讯,还会有队列用来保留音讯,等等。 咱们先来看下这些概念: Producer: 将音讯推送到rabbitmq交换机的利用Consumer: 从队列读取音讯并解决他们的利用Exchange: 交换机负责在Binding和Routing key的帮忙下,将音讯路由到不同的队列。从上图能够看出rabbitmq有多种类型的交换机Binding: Binding是队列和交换机之间的链接Routing key: 交换机用来决定如何将音讯路由到队列的键。能够看做是音讯的地址Queue: 存储音讯的缓冲区Connection:生产者到Broker(rabbitmq服务),消费者到Broker的连贯Channel:为了复用一个连贯,一个connection下能够有多个channel,能够把connection了解成电线,channel就是电线外面的铜丝。消息传递的残缺流程是这样的: 生产者初始化一个到rabbitmq服务的连贯获取连贯的管道,通过管道申明一个交换机通过管道申明一个队列,通过绑定的路由键将队列和交换机绑定(发送音讯的时候申明一个队列并绑定交换机,音讯会进到队列里。如果不申明也能够放到消费者去申明队列和绑定交换机。须要留神的是生产者没有申明队列的话,此时曾经生产多条音讯,而后去开启消费者生产,是不会生产到之前的音讯的)通过管道发送音讯到指定的交换机消费者初始化一个到rabbitmq服务的连贯获取连贯的管道,通过管道申明一个队列通过绑定的路由键将队列和交换机绑定从队列中生产音讯交换机类型: direct:间接指定到某个队列topic:公布订阅模式,一个交换机能够对应多个队列,通过路由规定匹配fanout:顾名思义,无脑播送模式2、示例生产者: package mainimport ( "fmt" "time" "github.com/streadway/amqp")var ( conn *amqp.Connection channel *amqp.Channel queue amqp.Queue mymsg = "Hello HaiCoder" err error confirms chan amqp.Confirmation)func main() { // 建设连贯 conn, err = amqp.Dial("amqp://guest:[email protected]:5672/") if err != nil { fmt.Println(err) return } defer conn.Close() // 创立channel if channel, err = conn.Channel(); err != nil { fmt.Println(err) return } // 申明交换机 err = channel.ExchangeDeclare("liutest", amqp.ExchangeDirect, false, false, false, false, nil) if err != nil { fmt.Println("ExchangeDeclare Err =", err) return } // 创立队列 if queue, err = channel.QueueDeclare("liutest", false, false, false, false, nil); err != nil { fmt.Println("QueueDeclare Err =", err) return } // 队列和交换机绑定 err = channel.QueueBind(queue.Name, "queueroutekey", "liutest", false, nil) if err != nil { fmt.Println("QueueBind Err =", err) return } channel.Confirm(false) confirms = channel.NotifyPublish(make(chan amqp.Confirmation, 1)) //发送数据 go func() { for { if err = channel.Publish("liutest", "queueroutekey", false, false, amqp.Publishing{ ContentType: "text/plain", Body: []byte(mymsg), }); err != nil { fmt.Println("Publish Err =", err) return } fmt.Println("Send msg ok, msg =", mymsg) time.Sleep(time.Second * 5) } }() go func() { for confirm := range confirms { if confirm.Ack { fmt.Printf("confirmed delivery with delivery tag: %d \n", confirm.DeliveryTag) } else { fmt.Printf("confirmed delivery of delivery tag: %d \n", confirm.DeliveryTag) } } }() select {}}消费者: ...

September 22, 2022 · 4 min · jiezi

关于rabbitmq:Centos离线安装RabbitMQ并开启MQTT

RabbitMQ全离线装置安装包下载地址 下载链接: http://www.rpmfind.net/linux/... 参考文章:CentOS 7 下 RabbitMQ 3.7 离线装置与配置 罕用指令 #rpm顺次装置sudo rpm -ivh epel-release-7-11.noarch.rpmsudo rpm -ivh erlang-22.2.8-1.el7.x86_64.rpm sudo rpm -ivh socat-1.7.3.2-2.el7.x86_64.rpmsudo rpm -ivh rabbitmq-server-3.8.2-1.el7.noarch.rpm 配置RabbitMQ开机自启动服务# 启动rabbitmq服务sudo systemctl start rabbitmq-server.service # 查看rabbitmq启动状态sudo systemctl status rabbitmq-server.service# 进行rabbitmq服务sudo systemctl stop rabbitmq-server.service # 重启rabbitmq服务sudo systemctl restart rabbitmq-server.service # 开机自启动服务sudo systemctl enable rabbitmq-server.service# 查看rabbitmq开机启动状态 enabled:开启, disabled:敞开sudo systemctl is-enabled rabbitmq-server.service# 禁止开启启动sudo systemctl disable rabbitmq-server.service创立用户操作#查看以后用户命令:rabbitmqctl list_users#创立用户admin 明码: abcd_2021rabbitmqctl add_user admin abcd_2021#将用户给于管理员权限 rabbitmqctl set_user_tags admin administrator#查看用户权限 rabbitmqctl list_user_permissions admin#设置用户权限(承受来自所有Host的所有操作) rabbitmqctl set_permissions -p "/" admin '.*' '.*' '.*'开启MQTT,web治理界面等插件#查看插件 rabbitmq-plugins list#启用WEB治理界面插件,治理控制台的默认端口是:15672 #浏览器拜访:http://127.0.0.1:15672/ 输出用户名和明码rabbitmq-plugins enable rabbitmq_management#启用MQTT插件,默认端口mqtt是:1883 mqtt://127.0.0.1:1883#能够应用EMQ的MQTTX客户端工具连贯,或者MQTTLens工具 rabbitmq-plugins enable rabbitmq_mqtt#启用MQTT的websocket插件,默认端口websocket是:15675 ws://127.0.0.1:15675/ws #留神: path是 /wsrabbitmq-plugins enable rabbitmq_web_mqtt#查看启动的端口netstat -tpnl RabbitMQ过期策略#TTL政策将删除指定的工夫到期后未应用的队列30分钟. beam.smp high cpu loadrabbitmqctl set_policy expiry ".*" '{"expires":1800000}' --apply-to queues#从队列维度设置音讯超时工夫 60秒:rabbitmqctl set_policy TTL ".*" '{"message-ttl":60000}' --apply-to queues

August 19, 2022 · 1 min · jiezi

关于rabbitmq:nameko-投递信息不持久化

将 delivery_mode=NON_PERSISTENT 设为 0 就好了(NON_PERSISTENT 就是 0) from loguru import loggerimport settingsfrom nameko.standalone.events import event_dispatcherfrom nameko.constants import NON_PERSISTENTimport timeconfig = { 'AMQP_URI': f'amqp://{settings.RABBITMQ_CONFIG.username}:' f'{settings.RABBITMQ_CONFIG.password}@{settings.RABBITMQ_CONFIG.host}:' f'{settings.RABBITMQ_CONFIG.port}/{settings.RABBITMQ_CONFIG.vhost}'}dispatch = event_dispatcher(config,delivery_mode=NON_PERSISTENT)for _ in range(100000): dispatch( 'test_publishe', 'to_publish', '1234567890' )message 不长久化,push 速率就能够到 2.5k/s 上图是我在 macbook 上通过 wifi push 到服务器的,提早如下: PING 192.168.31.245 (192.168.31.245): 56 data bytes64 bytes from 192.168.31.245: icmp_seq=0 ttl=64 time=4.563 ms64 bytes from 192.168.31.245: icmp_seq=1 ttl=64 time=4.206 ms64 bytes from 192.168.31.245: icmp_seq=2 ttl=64 time=3.787 ms64 bytes from 192.168.31.245: icmp_seq=3 ttl=64 time=3.741 ms64 bytes from 192.168.31.245: icmp_seq=4 ttl=64 time=4.791 ms64 bytes from 192.168.31.245: icmp_seq=5 ttl=64 time=4.327 ms64 bytes from 192.168.31.245: icmp_seq=6 ttl=64 time=3.905 ms64 bytes from 192.168.31.245: icmp_seq=7 ttl=64 time=4.072 ms64 bytes from 192.168.31.245: icmp_seq=8 ttl=64 time=4.170 ms64 bytes from 192.168.31.245: icmp_seq=9 ttl=64 time=4.190 ms64 bytes from 192.168.31.245: icmp_seq=10 ttl=64 time=10.588 ms64 bytes from 192.168.31.245: icmp_seq=11 ttl=64 time=4.108 ms^C--- 192.168.31.245 ping statistics ---12 packets transmitted, 12 packets received, 0.0% packet lossround-trip min/avg/max/stddev = 3.741/4.704/10.588/1.797 ms那如果开启音讯长久化呢?速率能够到多少? ...

August 5, 2022 · 2 min · jiezi

关于rabbitmq:IPV6禁用导致-RabbitMQ-无法启动的问题

问题景象在开发的过程中遇到了 RabbitMQ 怎么也启动不起来的景象。查看 RabbitMQ 本身的启动日志,并没有发现有什么有用的报错信息,只是从某天开始就始终在打印重启的日志,尝试屡次重启也不行。 问题复现前面查看操作系统的日志发现日志外面始终在报 epmd failed to bind on ipaddr 0.0.0.0这个谬误。从这个报错剖析,可能跟操作系统的哪个配置项有关系,然而从日志中也没能找到更过有用的信息了。 依据这个报错信息在 google 上搜寻,找到了一个帖子 Red Hat Bugzilla – Bug 1872670 说可能跟操作系统禁用了 IPV6 配置有关系。 于是尝试找一个环境,而后将操作系统上的 /etc/sysctl.conf减少如下两行配置,而后执行命令 sysctl -p是配置失效,最初重启 RabbitMQ,果然发现启动不起来了,查看操作系统的日志和有问题的环境报的是同样的谬误。 问题解决问题复现之后,解决的办法也很简略,将 /etc/sysctl.conf文件中的两行配置正文掉或者将其值批改为 0,而后执行 sysctl -p是配置失效,最初重启 RabbitMQ 问题失去解决了。

July 31, 2022 · 1 min · jiezi

关于rabbitmq:Python对RabbitMQ的简单使用

(一) RabbitMQ的简介RabbitMq 是实现了高级音讯队列协定(AMQP)(Advanced Message Queuing Protocol)的开源音讯代理中间件。音讯队列是一种应用程序对应用程序的通行形式,应用程序通过写音讯,将消息传递于队列,由另一应用程序读取 实现通信。而作为中间件的 RabbitMq 无疑是目前最风行的音讯队列之一。目前应用较多的音讯队列有ActiveMQ,RabbitMQ,ZeroMQ,Kafka,MetaMQ,RocketMQ。 RabbitMQ总体架构 PS:生产者和消费者可能在不同的程序或主机中,当然也有可能一个程序有可能既是生产者,也是消费者。 RabbitMq 利用场景宽泛: 零碎的高可用:日常生活当中各种商城秒杀,高流量,高并发的场景。当服务器接管到如此大量申请解决业务时,有宕机的危险。某些业务可能极其简单,但这部分不是高时效性,不须要立刻反馈给用户,咱们能够将这部分解决申请抛给队列,让程序后置去解决,加重服务器在高并发场景下的压力。分布式系统,集成系统,子系统之间的对接,以及架构设计中经常须要思考音讯队列的利用。(二) RabbitMQ的装置这里通过官网下载须要的版本:RabbitMQ官网网址鉴于官网拜访下载比较慢,贴一个云盘地址:百度云盘地址 Mac的话,能够间接应用brew装置,brew相似ubuntu下的apt-get性能 # brew install rabbitmq# 启动rabbitmq: rabbitmq-server start# 进行rabbitmq: rabbitmq-server stop# 重启rabbitmq: rabbitmq-server restart启动后,就能够登陆后盾治理页面了,浏览器输出ip:15672 自带的明码和用户名都是guest (三) python操作RabbitMQpython中应用pika操作RabbitMQ pip3 install pika(四) RabbitMQ简略模式 上代码 # coding=utf-8### 生产者import pikaimport timeuser_info = pika.PlainCredentials('guest', 'guest')#用户名和明码connection = pika.BlockingConnection(pika.ConnectionParameters('localhost', 5672, '/', user_info))#连贯服务器上的RabbitMQ服务# 创立一个channelchannel = connection.channel()# 如果指定的queue不存在,则会创立一个queue,如果曾经存在 则不会做其余动作,官网举荐,每次应用时都能够加上这句channel.queue_declare(queue='hello')for i in range(0, 100): channel.basic_publish(exchange='',#以后是一个简略模式,所以这里设置为空字符串就能够了 routing_key='hello',# 指定音讯要发送到哪个queue body='{}'.format(i)# 指定要发送的音讯 ) time.sleep(1) # 敞开连贯# connection.close()PS:RabbitMQ中所有的音讯都要先通过交换机,空字符串示意应用默认的交换机 ...

July 15, 2022 · 4 min · jiezi

关于rabbitmq:设置mq并发限制入库并发数

1) 利用mq做限流, 正当的入库工夫2) 加重数据库的压力3) 保障我的项目的稳定性 【生产场景】 多个用户同时excel导入数据, 采纳多线程保留数据, 对数据库压力过大,把数据间接放到mq里/** * 监听核验身份队列 * * @param tag * @param msg * @param channel * @throws IOException */ @RabbitHandler @RabbitListener(queues = Constant.QueueName.CHECK_CARD_NO) public void receiverCardNo(@Header("amqp_deliveryTag") long tag, String msg, Channel channel) throws IOException { try { logger.info("核验身份队列:{},队列内容:{}", Constant.QueueName.CHECK_CARD_NO, msg); queueService.receiverCardNo(msg); } catch (Exception ex) { throw new CvsException(ResCode.FAIL_MQ_ERROR, ex); } finally { channel.basicAck(tag, false); } }手动配置为35,同时启动35个线程解决入库操作,大小依据cpu数配置就能够@RabbitListener(queues = Constant.QueueName.CHECK_CARD_NO, concurrency = "35")默认分支, 因该是2@RabbitListener(queues = Constant.QueueName.CHECK_CARD_NO)

July 7, 2022 · 1 min · jiezi

关于rabbitmq:php极速开发源码包之superrabbitmq

前言super.rabbitmq是php-super的子性能包,实现了php操作rabbitmq的源码封装,浏览本文之前,如需理解php-super请先浏览 php极速开发源码包super,本文是super.rabbitmq 的性能介绍。 文章简介本文提供php操作rabbitmq的代码包供开发者开发应用 实用对象php开发者文章价值开箱即用,节俭开发工夫提供测试代码供学习应用目录构造 RabbitMq/Service:外围代码封装RabbitMq/Client:调用Service的代码封装,开发者能够调用Client里的代码,也能够间接调用Service里的代码代码(图片)源码以图片形式展现,获取源码请分割站长查看源码获取源码 装置形式composer装置(举荐)间接复制源码到我的项目并调用调用形式那么,如何在业务中疾速应用源码进行开发呢?,查看测试代码 创立音讯队列 <?php// 示例代码:创立息队列/初始化音讯队列namespace tests\Service\Mq\RabbitMq;use Seed\Super\Service\Mq\RabbitMq\Service\InitService;use Seed\Super\Service\Mq\RabbitMq\Service\MqInstanceService;require_once __DIR__ . '/../../../../vendor/autoload.php';// 获取连贯$config = [];$config['mq_host'] = '127.0.0.1';# 默认端口:15672 为网页治理 5672 为 AMQP端口$config['mq_port'] = 5672;$config['mq_user'] = 'guest';$config['mq_password'] = 'guest';$config['mq_virtual_host'] = 'test-host';$mqInstanceService = new MqInstanceService($config);$connection = $mqInstanceService->handle();// 初始化路由、队列$config = [];$config['connection'] = $connection;$config['exchange'] = 'test-exchange';$config['queue'] = 'test-queue';$config['route_key'] = 'test-route_key';$initService = new InitService($config);$initService->handle();公布Mq音讯 <?php// 示例代码:公布音讯namespace tests\Service\Mq\RabbitMq;use Seed\Super\Service\Mq\RabbitMq\Service\MqInstanceService;use Seed\Super\Service\Mq\RabbitMq\Service\PublisherService;require_once __DIR__ . '/../../../../vendor/autoload.php';// 获取连贯$config = [];$config['mq_host'] = '127.0.0.1';# 默认端口:15672 为网页治理 5672 为 AMQP端口$config['mq_port'] = 5672;$config['mq_user'] = 'guest';$config['mq_password'] = 'guest';$config['mq_virtual_host'] = 'test-host';$mqInstanceService = new MqInstanceService($config);$connection = $mqInstanceService->handle();$config = [];$config['connection'] =$connection;$config['message'] = 'this is a test mq message';$config['route_key'] = 'test-route_key';$config['exchange'] = 'test-exchange';$publisherService = new PublisherService($config);$publisherService->handle();生产mq音讯 ...

June 26, 2022 · 1 min · jiezi

关于rabbitmq:系统学习消息队列RabbitMQ的发布确认高级篇

1.音讯公布确认的计划2.音讯的回退3.备份交换机 1.音讯公布确认的计划在后面的文章中,零碎学习音讯队列——RabbitMQ的音讯公布确认,咱们肯定水平上学习了音讯的公布确认的根底,然而在生产环境中,因为RabbitMq的重启,RabbitMQ在重启过程中投递失败,导致音讯失落,须要手动解决和复原。那么咱们该如何保障当RabbitMQ不可用的时候,音讯的稳固投递呢? 咱们采取上面的计划: 咱们将要发送音讯做一个长久化,发送音讯的时候,咱们长久化一份到数据库或者缓存中,当发送音讯失败的时候,咱们进行一次从新发送。所以在发送音讯的时候,咱们要进行代码业务逻辑的解决: yml: server: port: 11000spring: rabbitmq: host: 127.0.0.1 port: 5672 username: guest password: guest publisher-confirm-type: correlatedpublisher-confirm-type这个参数一共有三种配置办法: NONE:禁用公布确认,是默认值。CORRELATED:公布音讯后,替换机会触发回调办法。SIMPLE:有两种成果:1:和CORRELATED一样会触发回调办法2:公布音讯胜利后应用 rabbitTemplate 调用 waitForConfirms 或 waitForConfirmsOrDie 办法期待 broker 节点返回发送后果,依据返回后果来断定下一步的逻辑,要留神的点是waitForConfirmsOrDie 办法如果返回 false 则会敞开 channel,则接下来无奈发送音讯到 broker。回调办法类: @Component@Slf4jpublic class MyCallBack implements RabbitTemplate.ConfirmCallback { /** * 交换机是否收到音讯的回调办法 * CorrelationData 音讯相干数据 * ack 交换机是否收到音讯 * cause 交换机未收到音讯的起因 */ @Override public void confirm(CorrelationData correlationData, boolean ack, String cause) { if (ack) { log.info("交换机曾经收到 id 为:{}的音讯", correlationData.getId()); } else { log.info("交换机还未收到 id 为:{}音讯,因为起因:{}", correlationData.getId(), cause); } }}队列配置类: ...

June 20, 2022 · 3 min · jiezi

关于rabbitmq:系统学习消息队列RabbitMQ的延时队列

1.延时队列的概念2.延时队列实用场景3.RabbitMQ中的两种TTL4.队列的TTL5.音讯的TTL6.RabbitMQ插件实现延时队列 1.延时队列的概念延时队列,顾名思义,就是音讯等一段时间再发送进来,最重要的属性是延时属性,它侧重于延时队列中的音讯在指定的工夫到了之后再取出解决。 2.延时队列实用场景 2.1)用户给本人设置了一个揭示,到点推送音讯。2.2)订单在完结之后主动把钱打到买家账户。2.3)订单在几分钟内未领取主动勾销。2.4)用户发动退款,一天之内没解决就主动推送给相干人员。 以上这些场景都有一个特点,那就是在某个业务逻辑实现后,在指定的特定工夫实现某一项业务逻辑的解决。如:用户给本人设置了一个揭示,到点推送音讯。其实如果简略地来说,是不是应用定时工作解决,每分钟甚至每秒钟轮询所有数据,符合条件的推送就行了?如果在数据量少的状况,且对于工夫解决不是特地严格,能够领有肯定的延时的状况,是能够这么解决的,然而一旦数据量变得十分大,并且时效性十分强的业务场景,定时工作就会解决不过去,可能无奈在几秒钟或者一分钟大量解决数据,同时也会给数据库很大压力,既不满足业务要求,而且性能也很低下。 3.RabbitMQ中的两种TTLTTL是RabbitMQ中,一个音讯或者一个队列的属性,表明一条音讯或者队列中所有的音讯的最大存活工夫,单位是毫秒。 如果一条音讯设置了TTL属性或者音讯进入了设置TTL属性的队列,在这个工夫到了的状况下还没被生产,那么就会成为死信。如果同时配置了两个TTL属性,那么较小的值将会被应用。 4.队列的TTL pom: <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> <!--rabbitmq 依赖客户端--> <dependency> <groupId>com.rabbitmq</groupId> <artifactId>amqp-client</artifactId> <version>5.8.0</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> </dependency>yml: server: port: 11000spring: rabbitmq: host: 127.0.0.1 port: 5672 username: guest password: guest在写队列之前,咱们先画一张队列与交换机的关系图,就能够更顺利地编写代码,咱们这里要写两个有过期工夫的队列,过期工夫不同。 这次咱们不应用原生API,咱们应用springBoot整合好的API: 申明队列和交换机: @Configurationpublic class QueueConfig { private String xExchange = "x"; private String queueA = "QA"; private String queueB = "QB"; private String yDeadLetterExchange = "Y"; private String deadLetterQueue = "QD"; @Bean("xExchange") public DirectExchange xExchange(){ return new DirectExchange(xExchange); } @Bean("yExchange") public DirectExchange yExchange(){ return new DirectExchange(yDeadLetterExchange); } @Bean("queueA") public Queue queueA(){ Map<String, Object> args = new HashMap<>(3); //申明以后队列绑定的死信交换机 args.put("x-dead-letter-exchange", yDeadLetterExchange); //申明以后队列的死信路由 key args.put("x-dead-letter-routing-key", "YD"); //申明队列的 TTL args.put("x-message-ttl", 10000); return QueueBuilder.durable(queueA).withArguments(args).build(); } @Bean public Binding queueABindX(@Qualifier("queueA") Queue queueA, @Qualifier("xExchange") DirectExchange xExchange){ return BindingBuilder.bind(queueA).to(xExchange).with("XA"); } @Bean("queueB") public Queue queueB(){ Map<String, Object> args = new HashMap<>(3); //申明以后队列绑定的死信交换机 args.put("x-dead-letter-exchange", yDeadLetterExchange); //申明以后队列的死信路由 key args.put("x-dead-letter-routing-key", "YD"); //申明队列的 TTL args.put("x-message-ttl", 40000); return QueueBuilder.durable(queueB).withArguments(args).build(); } @Bean public Binding queueBBindingX(@Qualifier("queueB") Queue queueB, @Qualifier("xExchange") DirectExchange xExchange){ return BindingBuilder.bind(queueB).to(xExchange).with("XB"); } //申明死信队列 QD @Bean("queueD") public Queue queueD(){ return new Queue(deadLetterQueue); } //申明死信队列 QD 绑定关系 @Bean public Binding deadLetterBindingQAD(@Qualifier("queueD") Queue queueD, @Qualifier("yExchange") DirectExchange yExchange){ return BindingBuilder.bind(queueD).to(yExchange).with("YD"); }}音讯生产者代码: ...

June 18, 2022 · 3 min · jiezi

关于rabbitmq:系统学习消息队列RabbitMQ的死信队列

1.死信队列的概念2.死信产生的起因3.死信队列的架构图4.音讯过期的死信5.队列达到最大长度的死信6.音讯被回绝的死信 1.死信队列的概念死信,就是无奈被生产的音讯。生产者把音讯发送个broker,然而因为某些起因,queue中的音讯无奈被生产,这样的音讯被称之为死信,而这种音讯的后续解决,有专门的队列解决这类音讯,称之为死信队列。 2.死信产生的起因 个别会有上面三种起因: 音讯TTL工夫过期。 队列达到最大长度。 音讯被回绝。 3.死信队列的架构图 4.音讯过期的死信 消费者1: public class Consumer1 { private final static String EXCHANGE_NAME = "test_exchange"; private final static String NORMAL_QUEUE = "normal_queue"; private final static String DEAD_EXCHANGE_NAME = "dead_test"; private final static String DEAD_QUEUE = "dead_queue"; public static void main(String[] args) throws Exception { Channel channel = RabbitMqUtils.getChannel(); //申明一般交换机 channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.DIRECT); Map<String, Object> params = new HashMap<>(); //失常队列设置死信交换机 参数 key 是固定值 params.put("x-dead-letter-exchange", DEAD_EXCHANGE_NAME); //失常队列设置死信 routing-key 参数 key 是固定值 params.put("x-dead-letter-routing-key", "dead"); channel.queueDeclare(NORMAL_QUEUE,true,false,false,params); channel.queueBind(NORMAL_QUEUE,EXCHANGE_NAME,"test"); System.out.println("消费者1期待接管音讯........."); //音讯如何进行生产的业务逻辑 DeliverCallback deliverCallback = (consumerTag, delivery) -> { String message = new String(delivery.getBody()); System.out.println("消费者1控制台接管并打印消息:"+message); channel.basicAck(delivery.getEnvelope().getDeliveryTag(),false); }; //勾销生产的一个回调接口 如在生产的时候队列被删除掉了 CancelCallback cancelCallback = (consumerTag) -> { System.out.println("音讯生产被中断"); }; channel.basicConsume(NORMAL_QUEUE, false, deliverCallback, cancelCallback); }}消费者2: ...

June 17, 2022 · 4 min · jiezi

关于rabbitmq:系统学习消息队列RabbitMQ的交换机

1.Exchange的概念2.Exchange的绑定3.Exchange的Fanout4.Exchange的direct5.Exchange的Topics 1.Exchange的概念 在咱们之前练习mq的根本应用的时候,咱们发送一个信息,看起来是间接把音讯发送给了队列,其实,Rabbitmq消息传递模型的核心思想是:生产者生产的音讯不会发送给队列,而是发送给交换机。交换机工作的内容也非常简略,一方面承受来自生产者的音讯,另一方面将他们推入队列。交换机晓得如何精确地解决音讯,到底是发送给一个或者多个队列,还是丢掉,都由交换机决定。 所以看看之前咱们写的代码,咱们是把音讯发送给了一个无名的交换机 channel.basicPublish("", QUEUE_NAME, null, message.getBytes());第一个参数就是交换机的名称,空字符串示意无名交换机,音讯能路由到哪个队列中是由routingKey(bindingkey)绑定 key 指定的。 2.Exchange的绑定 因为交换机晓得要把音讯发送给哪个队列,然而咱们须要将队列和路由器进行绑定。 绑定的形式有Fanout(播送),Direct exchange(全匹配),Topics(主题匹配)。 3.Exchange的FanoutFanout类型的exchange简略粗犷,就是播送,将受到的所有音讯播送到它晓得的所有队列中。 消费者1: public class Consumer1 { private final static String EXCHANGE_NAME = "test"; public static void main(String[] args) throws Exception { Channel channel = RabbitMqUtils.getChannel(); //申明一个交换机 channel.exchangeDeclare(EXCHANGE_NAME, "fanout"); /** * 生成一个长期的队列 队列的名称是随机的 * 当消费者断开和该队列的连贯时 队列主动删除 */ String queueName = channel.queueDeclare().getQueue(); //交换机和队列绑定,因为是fanout类型,所以无需路由键 channel.queueBind(queueName,EXCHANGE_NAME,""); System.out.println("消费者1期待接管音讯........."); //音讯如何进行生产的业务逻辑 DeliverCallback deliverCallback = (consumerTag, delivery) -> { String message = new String(delivery.getBody()); System.out.println("消费者1控制台接管并打印消息:"+message); }; //勾销生产的一个回调接口 如在生产的时候队列被删除掉了 CancelCallback cancelCallback = (consumerTag) -> { System.out.println("音讯生产被中断"); }; channel.basicConsume(queueName, true, deliverCallback, cancelCallback); }}消费者2: ...

June 16, 2022 · 4 min · jiezi

关于rabbitmq:Docker搭建RabbitMQ镜像集群

Docker部署RabbitMQ镜像集群拉取镜像并运行容器#拉取镜像,指定带有“mangement”的版本(蕴含web治理页面),该版本蕴含了web管制页面docker pull rabbitmq:managementdocker run -d --hostname myRabbit1 --name rabbit1 -p 15672:15672 -p 4369:4369 -p 5672:5672 -e RABBITMQ_ERLANG_COOKIE='rabbitcookie' rabbitmq:managementdocker run -d --hostname myRabbit2 --name rabbit2 -p 5673:5672 -p 4370:4369 --link rabbit1:myRabbit1 -e RABBITMQ_ERLANG_COOKIE='rabbitcookie' rabbitmq:managementdocker run -d --hostname myRabbit3 --name rabbit3 -p 5674:5672 -p 4371:4369 --link rabbit1:myRabbit1 --link rabbit2:myRabbit2 -e RABBITMQ_ERLANG_COOKIE='rabbitcookie' rabbitmq:management容器内RabbitMQ设置#进入rabbitmq01容器,从新初始化一下,如果是新装置则reset能够疏忽重置。docker exec -it rabbit1 bashrabbitmqctl stop_apprabbitmqctl resetrabbitmqctl start_appexit#进入rabbitmq02容器,从新初始化一下,将02节点退出到集群中docker exec -it rabbit2 bashrabbitmqctl stop_apprabbitmqctl resetrabbitmqctl join_cluster --ram rabbit@myRabbit1 #参数“--ram”示意设置为内存节点,疏忽该参数默认为磁盘节点。rabbitmqctl start_appexit#进入rabbitmq03容器,从新初始化一下,将03节点退出到集群中docker exec -it rabbit3 bashrabbitmqctl stop_apprabbitmqctl resetrabbitmqctl join_cluster --ram rabbit@myRabbit1rabbitmqctl start_appexit设置镜像集群及个别操作#任意节点执行,设置镜像集群模式rabbitmqctl set_policy -p / ha "^" '{"ha-mode":"all","ha-sync-mode":"automatic"}'#查问策略 #查看vhost下的所有的策略(policies )rabbitmqctl list_policies -p / #查看集群的状态:rabbitmqctl cluster_status#查看镜像队列 `rabbitmqctl list_policies` #删除镜像队列 `rabbitmqctl clear_policy`网页监控平台http://localhost:15672/#/queues用户民/明码:guest/guest ...

May 15, 2022 · 1 min · jiezi

关于rabbitmq:RabbitMQ服务启动后无异常无法访问web管理页

启动rabbitmq-server.bat后,无显著异样。拜访http://localhost:15672 web治理页面无响应。 经排查,是因为插件rabbitmq_management、rabbitmq_management_agent、rabbitmq_web_dispatch没有启动。 执行命令rabbitmq-plugins enable rabbitmq_management,即可启动。 重新启动rabbitmq服务,页面恢复正常。

May 4, 2022 · 1 min · jiezi

关于rabbitmq:安装rabbitmq-扩展之-phpamqplibphpamqplib-失败解决方案

背景:有个我的项目须要装置laravel-queue-rabbitmq,但在composer install时爆以下谬误: No composer.lock file present. Updating dependencies to latest instead of installing from lock file. See https://getcomposer.org/install for more information.Loading composer repositories with package informationWarning: Accessing nexus.officemate.cn over http which is an insecure protocol.Updating dependenciesYour requirements could not be resolved to an installable set of packages. Problem 1 - php-amqplib/php-amqplib[v2.11.0, ..., 2.x-dev] require ext-sockets * -> it is missing from your system. Install or enable PHP's sockets extension. - vladimir-yuldashev/laravel-queue-rabbitmq v10.2.3 requires php-amqplib/php-amqplib ^2.11 -> satisfiable by php-amqplib/php-amqplib[v2.11.0, ..., 2.x-dev]. - Root composer.json requires vladimir-yuldashev/laravel-queue-rabbitmq 10.2.3 -> satisfiable by vladimir-yuldashev/laravel-queue-rabbitmq[v10.2.3].To enable extensions, verify that they are enabled in your .ini files: - D:\willen\phpStudy\PHPTutorial\php\php-7.2.1-nts\php.iniYou can also run `php --ini` in a terminal to see which files are used by PHP in CLI mode.Alternatively, you can run Composer with `--ignore-platform-req=ext-sockets` to temporarily ignore these required extensions.报错截图: ...

March 29, 2022 · 1 min · jiezi

关于rabbitmq:tshark-抓包-rabbitmq-协议包

tshark 抓包 rabbitmq 协定包 ─➤ tshark -Y amqp 1 ↵Capturing on 'enp34s0' 737 7.859437643 192.168.31.203 → 192.168.31.245 AMQP 578 Connection.Start 739 7.859776699 192.168.31.245 → 192.168.31.203 AMQP 251 Connection.Start-Ok 741 7.860942759 192.168.31.203 → 192.168.31.245 AMQP 86 Connection.Tune 743 7.861154346 192.168.31.245 → 192.168.31.203 AMQP 86 Connection.Tune-Ok 744 7.861217244 192.168.31.245 → 192.168.31.203 AMQP 82 Connection.Open vhost=/ 748 7.863124916 192.168.31.203 → 192.168.31.245 AMQP 79 Connection.Open-Ok 750 7.863814761 192.168.31.245 → 192.168.31.203 AMQP 79 Channel.Open 753 7.866605942 192.168.31.203 → 192.168.31.245 AMQP 82 Channel.Open-Ok 757 7.867457801 192.168.31.245 → 192.168.31.203 AMQP 102 Exchange.Declare x=nameko-rpc 759 7.868057657 192.168.31.203 → 192.168.31.245 AMQP 78 Exchange.Declare-Ok 760 7.868337152 192.168.31.245 → 192.168.31.203 AMQP 101 Queue.Declare q=rpc-add_service 762 7.868989637 192.168.31.203 → 192.168.31.245 AMQP 102 Queue.Declare-Ok q=rpc-add_service 763 7.869153745 192.168.31.245 → 192.168.31.203 AMQP 126 Queue.Bind q=rpc-add_service x=nameko-rpc bk=add_service.* 765 7.870936603 192.168.31.203 → 192.168.31.245 AMQP 78 Queue.Bind-Ok 766 7.871189277 192.168.31.245 → 192.168.31.203 AMQP 85 Basic.Qos 768 7.871669990 192.168.31.203 → 192.168.31.245 AMQP 78 Basic.Qos-Ok 769 7.872109455 192.168.31.245 → 192.168.31.203 AMQP 116 Exchange.Declare x=productor_service.events 771 7.872759415 192.168.31.203 → 192.168.31.245 AMQP 78 Exchange.Declare-Ok 772 7.872969399 192.168.31.245 → 192.168.31.203 AMQP 147 Queue.Declare q=evt-productor_service-test_no_rpc--add_service.handle_message 774 7.873727783 192.168.31.203 → 192.168.31.245 AMQP 148 Queue.Declare-Ok q=evt-productor_service-test_no_rpc--add_service.handle_message 775 7.873934181 192.168.31.245 → 192.168.31.203 AMQP 184 Queue.Bind q=evt-productor_service-test_no_rpc--add_service.handle_message x=productor_service.events bk=test_no_rpc 777 7.875732377 192.168.31.203 → 192.168.31.245 AMQP 78 Queue.Bind-Ok 778 7.875972839 192.168.31.245 → 192.168.31.203 AMQP 85 Basic.Qos 780 7.876535004 192.168.31.203 → 192.168.31.245 AMQP 78 Basic.Qos-Ok 781 7.876700655 192.168.31.245 → 192.168.31.203 AMQP 107 Basic.Consume q=rpc-add_service 784 7.877579736 192.168.31.203 → 192.168.31.245 AMQP 84 Basic.Consume-Ok 785 7.877817903 192.168.31.245 → 192.168.31.203 AMQP 153 Basic.Consume q=evt-productor_service-test_no_rpc--add_service.handle_message 788 7.878819634 192.168.31.203 → 192.168.31.245 AMQP 84 Basic.Consume-Ok 2068 20.603182475 192.168.31.203 → 192.168.31.245 AMQP 578 Connection.Start 2070 20.603405554 192.168.31.245 → 192.168.31.203 AMQP 251 Connection.Start-Ok 2072 20.604347773 192.168.31.203 → 192.168.31.245 AMQP 86 Connection.Tune 2074 20.604486404 192.168.31.245 → 192.168.31.203 AMQP 86 Connection.Tune-Ok 2075 20.604568878 192.168.31.245 → 192.168.31.203 AMQP 82 Connection.Open vhost=/ 2078 20.606191525 192.168.31.203 → 192.168.31.245 AMQP 79 Connection.Open-Ok 2080 20.606440563 192.168.31.245 → 192.168.31.203 AMQP 79 Channel.Open 2082 20.609904197 192.168.31.203 → 192.168.31.245 AMQP 82 Channel.Open-Ok 2084 20.610191467 192.168.31.245 → 192.168.31.203 AMQP 79 Confirm.Select 2086 20.610727133 192.168.31.203 → 192.168.31.245 AMQP 78 Confirm.Select-Ok 2088 20.611078102 192.168.31.245 → 192.168.31.203 AMQP 191 Basic.Publish x=productor_service.events rk=test_no_rpc Content-Header type=application/json Content-Body (application/json) 2091 20.612854878 192.168.31.203 → 192.168.31.245 AMQP 203 Basic.Deliver x=productor_service.events rk=test_no_rpc Content-Header type=application/json Content-Body (application/json) 2093 20.614442318 192.168.31.245 → 192.168.31.203 AMQP 87 Basic.Ack 2098 20.646187505 192.168.31.203 → 192.168.31.245 AMQP 87 Basic.Ack

March 8, 2022 · 2 min · jiezi

关于rabbitmq:资深架构师教你在windows环境安装RabbitMQ

装置Linux 环境装置装置Erlang官网提醒:https://www.erlang-solutions.... 装置erlang yum -y install esl-erlang_23.0.2-1_centos_7_amd64.rpm检测erlang 装置RabbitMQ文件下载 官网下载地址:http://www.rabbitmq.com/downl... 装置rabbitmq yum -y install rabbitmq-server-3.8.5-1.el7.noarch.rpm装置UI插件 rabbitmq-plugins enable rabbitmq_management 启用rabbitmq服务 systemctl start rabbitmq-server.service检测服务 systemctl status rabbitmq-server.service 批改防火墙,增加规定 -A INPUT -p tcp -m state --state NEW -m tcp --dport 15672 -j ACCEPT-A INPUT -p tcp -m state --state NEW -m tcp --dport 5672 -j ACCEPT重启防火墙 systemctl restart iptables.service拜访guest用户默认只能够localhost(本机)拜访 在rabbitmq的配置文件目录下(默认为:/etc/rabbitmq)创立一个rabbitmq.config文件。 文件中增加如下配置(请不要遗记那个“.”): [{rabbit, [{loopback_users, []}]}].重启rabbitmq服务 systemctl restart rabbitmq-server.service从新拜访 Windows 环境装置装置Erlang运行Erlang/OTP(otp_win64_21.2.exe) ...

February 23, 2022 · 1 min · jiezi

关于rabbitmq:RabbitMQ-安装使用攻略

MQ 有哪些?当今市面上有很多支流的消息中间件,如老牌的 ActiveMQ、RabbitMQ,煊赫一时的 Kafka(大数据,高效,安全性低),阿里巴巴自主开发 RocketMQ(OPPO 用的 RocketMQ)等。 不同 MQ 的特点 ActiveMQ JMS java13 种标准(接口)之一(jdbc)ActiveMQ 是Apache出品,最风行的,能力强劲的开源音讯总线。它是一个齐全反对JMS标准的的消息中间件。丰盛的API,多种集群架构模式让ActiveMQ在业界成为老牌的消息中间件,在中小型企业颇受欢迎! KafkaKafka是LinkedIn开源的分布式公布-订阅音讯零碎,目前归属于Apache顶级我的项目。Kafka次要特点是基于Pull的模式来解决音讯生产,谋求高吞吐量,一开始的目标就是用于日志收集和传输。0.8版本开始反对复制,不反对事务,对音讯的反复、失落、谬误没有严格要求,适宜产生大量数据的互联网服务的数据收集业务。 RocketMQRocketMQ是阿里开源的消息中间件,它是纯Java开发,具备高吞吐量、高可用性、适宜大规模分布式系统利用的特点。RocketMQ思路起源于Kafka,但并不是Kafka的一个Copy,它对音讯的牢靠传输及事务性做了优化,目前在阿里团体被广泛应用于交易、充值、流计算、音讯推送、日志流式解决、binglog散发等场景。 RabbitMQ (平安)RabbitMQ是应用Erlang语言开发的开源音讯队列零碎,基于AMQP协定来实现。AMQP的次要特色是面向音讯、队列、路由(包含点对点和公布/订阅)、可靠性、平安。AMQP协定更多用在企业零碎内对数据一致性、稳定性和可靠性要求很高的场景,对性能和吞吐量的要求还在其次。 RabbitMQ 比 Kafka 牢靠,Kafka 更适宜 IO 高吞吐的解决,个别利用在大数据日志解决或对实时性(大量提早),可靠性(大量丢数据)要求稍低的场景应用,比方 ELK 日志收集。 RabbitMQ 的装置(1)下载官网下载地址: https://www.rabbitmq.com/down... (2)下载的安装包 留神:这里的安装包是 centos7 装置的包 (3)装置步骤 1.将rabbitmq安装包上传到linux零碎中erlang-22.0.7-1.el7.x86_64.rpm #erlang环境 socat-1.7.3.2-2.el7.x86_64.rpm #内存治理依赖 rabbitmq-server-3.7.18-1.el7.noarch.rpm 2.装置Erlang依赖包rpm -ivh erlang-22.0.7-1.el7.x86_64.rpm rpm -ivh socat-1.7.3.2-2.el7.x86_64.rpm 3.装置RabbitMQ安装包(须要联网)yum install -y rabbitmq-server-3.7.18-1.el7.noarch.rpm 留神:默认装置实现后配置文件模板在:/usr/share/doc/rabbitmq-server-3.7.18/rabbitmq.config.example目录中,须要将配置文件复制到/etc/rabbitmq/目录中,并批改名称为rabbitmq.config 4.复制配置文件cp /usr/share/doc/rabbitmq-server-3.7.18/rabbitmq.config.example /etc/rabbitmq/rabbitmq.config 5.查看配置文件地位ls /etc/rabbitmq/rabbitmq.config 6.批改配置文件(参见下图:) :61 查看61行vim /etc/rabbitmq/rabbitmq.config 7.执行如下命令,启动rabbitmq中的插件治理rabbitmq-plugins enable rabbitmq_management 呈现如下阐明: ...

February 21, 2022 · 1 min · jiezi

关于rabbitmq:关于-RabbitMQ应该没有比这更详细的教程了

@[toc]从八月份开始,断断续续连载了不少 RabbitMQ 教程,最近抽空整顿了一下,将来可能会有一个视频教程,小伙伴们敬请期待。 1. 常见消息中间件大 PK说到消息中间件,预计大伙多多少少都能讲进去一些,ActiveMQ、RabbitMQ、RocketMQ、Kafka 等等各种以及 JMS、AMQP 等各种协定,然而这些消息中间件各自都有什么特点,咱们在开发中又该抉择哪种呢?明天松哥就来和小伙伴们梳理一下。 1.1 几种协定先来说说消息中间件中常见的几个协定。 1.1.1 JMS1.1.1.1 JMS 介绍先来说说 JMS。 JMS 全称 Java Message Service,相似于 JDBC,不同于 JDBC,JMS 是 JavaEE 的音讯服务接口,JMS 次要有两个版本: 1.12.0。两者相比,后者次要是简化了收发音讯的代码。 思考到消息中间件是一个十分罕用的工具,所以 JavaEE 为此制订了专门的标准 JMS。 不过和 JDBC 一样,JMS 作为标准,他只是一套接口,并不蕴含具体的实现,如果咱们要应用 JMS,那么个别还须要对应的实现,这就像应用 JDBC 须要对应的驱动一样。 1.1.1.2 JMS 模型JMS 音讯服务反对两种音讯模型: 点对点或队列模型公布/订阅模型在点对点或队列模型下,一个生产者向一个特定的队列公布音讯,一个消费者从该队列中读取音讯。这里,生产者晓得消费者的队列,并间接将音讯发送到对应的队列。这是一种点对点的音讯模型,这种模式被概括为: 只有一个消费者将取得音讯。生产者不须要在消费者生产该音讯期间处于运行状态,消费者也同样不须要在音讯发送时处于运行状态,即音讯的生产者和消费者是齐全解耦的。每一个胜利解决的音讯都由音讯消费者签收。发布者/订阅者模型反对向一个特定的音讯主题公布音讯,消费者则能够定义本人感兴趣的主题,这是一种点对面的音讯模型,这种模式能够被概括为: 多个消费者能够生产音讯。在发布者和订阅者之间存在工夫依赖性,发布者须要创立一个订阅(subscription),以便客户可能订阅;订阅者必须放弃在线状态以接管音讯;当然,如果订阅者创立了长久的订阅,那么在订阅者未连贯时,音讯生产者公布的音讯将会在订阅者从新连贯时从新公布。1.1.1.3 JMS 实现开源的反对 JMS 的消息中间件有: KafkaApache ActiveMQJBoss 社区的 HornetQJoramCoridan 的 MantaRayOpenJMS一些商用的反对 JMS 的消息中间件有: WebLogic Server JMSEMSGigaSpacesiBusIONA JMSIQManager(2005 年 8 月被Sun Microsystems并购)JMS+NirvanaSonicMQWebSphere MQ这里有不少是松哥考古开掘进去的,其实对于咱们日常开发接触较多的,可能就是 Kafka 和 ActiveMQ。 ...

January 10, 2022 · 24 min · jiezi

关于rabbitmq:RabbitMQ消息中间件技术精讲

RabbitMQ消息中间件技术精讲downloadSocket 是什么以及创建过程一个数据包经由应用程序产生,进入到协定栈中进行各种报文头的包装,而后操作系统调用网卡驱动程序指挥硬件,把数据发送到对端主机。整个过程的大抵的图示如下。 咱们大家知道,协定栈其实是位于操作系统中的一些协定的重叠,这些协定包含 TCP、UDP、ARP、ICMP、IP等。通常某个协定的设计都是为理解决某些问题,比如 TCP 的设计就负责安全可靠的传输数据,UDP 设计就是报文小,传输效率高,ARP 的设计是能够通过 IP 地址查问物理(Mac)地址,ICMP 的设计目标是返回谬误报文给主机,IP 设计的目标是为了实现大范畴主机的互联互通。 应用程序比如阅读器、电子邮件、文件传输服务器等产生的数据,会通过传输层协定进行传输,而应用程序是不会和传输层间接建立联系的,而是有一个能够连接应用层和传输层之间的套件,这个套件就是 Socket。 在下面这幅图中,应用程序蕴含 Socket 和解析器,解析器的作用就是向 DNS 服务器发动查问,查问目标 IP 地址。 应用程序的上面就是操作系统外部,操作系统外部包含协定栈,协定栈是一系列协定的重叠。操作系统上面就是网卡驱动程序,网卡驱动程序负责管制网卡硬件,驱动程序驱动网卡硬件实现收发工作。 在操作系统外部有一块用于存放管制信息的存储空间,这块存储空间记录了用于管制通信的管制信息。其实这些管制信息就是 Socket 的实体,或者说存放管制信息的内存空间就是套接字的实体。 这里大家有可能不太明显所以然,所以我用了一下 netstat 命令来给大伙看一下套接字是啥玩意。 咱们在 Windows 的命令提示符中输出 netstat -ano netstat 用于浮现套接字内容 , -ano 是可选选项a 不只浮现正在通信的套接字,还浮现包含尚未开始通信等状态的所有套接字n 浮现 IP 地址和端口号o 浮现套接字的程序 PID我的计算机会出现上面后果。 download图中的每一行都相当于一个套接字,每一列也被称为一个元组,所以一个套接字就是五元组(协定、本地地址、内部地址、状态、PID)。有的时候也被叫做四元组,四元组不包含协定。 比如图中的第一行,它的协定就是 TCP,本地地址和近程地址都是 0.0.0.0,这示意通信还没有开始,IP 地址临时还未必定,而本地端口已知是 135,然而近程端口还未知,此时的状态是 LISTENING,LISTENING 示意应用程序已经打开,正在等待与近程主机建立连接(对于各种状态之间的转换,大家可能浏览笔者的这篇文章 TCP ,丫的终于来了!!)最初一个元组是 PID,即过程标识符,PID 就像咱们的身份证号码,能够精确定位唯一的过程。 现在你可能对 Socket 有了一个基本的意识,现在喝口水,劳动一下,让咱们持续探究 Socket。 现在我有个问题,Socket 是如何创建的呢?Socket 是和应用程序一起创建的。应用程序中有一个 socket 组件,在应用程序启动时,会调用 socket 申请创建套接字,协定栈会根据应用程序的申请创建套接字:首先调配一个套接字所需的内存空间,这一步相当于是为管制信息筹备一个容器,但只有容器并没有实际作用,所以你还需要向容器中放入管制信息;如果你不申请创建套接字所需要的内存空间,你创建的管制信息也没有地方存放,所以分配内存空间,放入管制信息缺一不可。至此套接字的创建就已经实现了。 套接字创建实现后,会返回一个套接字描述符给应用程序,这个描述符相当于是分别不同套接字的号码牌。根据这个描述符,应用程序在托付协定栈收发数据时就需要提供这个描述符。 套接字连接套接字创建实现后,最终还是为数据收发服务的,在数据收发之前,还需要进行一步 connect,也就是建立连接的过程。这个连接并不是实在的连接:用一根水管插在两个电脑之间。 ...

January 7, 2022 · 1 min · jiezi

关于rabbitmq:新RabbitMQ精讲项目驱动落地分布式事务拔高ssh

download:新RabbitMQ精讲,我的项目驱动落地,分布式事务拔高明天咱们要探讨的问题是:Service层需要接口? 现在拆散我参加的我的项目以及浏览的一些我的项目源码来看。如果「我的项目中使用了像Spring这样的依赖注入框架,那可能不必接口」! 先来说说为什么使用了依赖注入框架当前,可能不使用接口! 不需要接口的理由我整顿了反对Service层和Dao层需要加上接口的理由,总结下来就这么三个: 可能在尚未实现具体Service逻辑的情况下编写下层代码,如Controller对Service的调用 Spring默认是基于动静代理实现AOP的,动静代理需要接口 可能对Service进行多实现 实际上,这三个理由都站不住脚! 先说说第一个理由:「下层可能在上层逻辑没有实现的情况下进行编码」!很典型的面向接口编程,对层与层之间进行了解耦,看起来好像没有问题。 这种开发方式适合不同模块之间是由不同的人或项目组开发的,因为沟通的成本比较大。同时避免因为项目组之间开发进度的差异而相互影响。 不过让咱们回忆一下,在一般我的项目开发外面,有几项目组是按层来切分开发工作的呢?实际上,大部分的我的项目都是按照功能划分的。即使是现在前后端分离的情况,单纯的后端开发也是按照功能模块进行工作划分,即一个人负责从Controller层到DAO层的完整逻辑处理。在这种情况下,每一层都先定义一个接口,再去实现逻辑,除了减少了开发人员的工作量(当然,如果代码量计入工作量的话,那开发人员应该也不是太排斥接口的!),实际没有任何用处。 如果开发人员想在上层逻辑没有实现的情况下,先开发下层逻辑,可能先编写上层类的空方法来先实现下层的逻辑。 这里推荐一个集体比较喜爱的开发流程,自上向下的编码流程: 先在Controller层编写逻辑,遇到需要托付Service调用的地方,间接先写出调用代码。优先实现Controller层的流程 而后使用IDE的主动补全,对方才调用上层的代码生成对应的类和方法,在外面增加TODO 等所有的类和方法都补全了,再基于TODO,按照下面的流程去一个个的欠缺逻辑。 此方法可能使你对业务流程有比较好的理解。 对于第二个理由,就残缺不成立了。Spring默认是基于动静代理的,不过通过配置是可能使用CGLib来实现AOP。CGLib是不需要接口的。 最初一个理由是「可能对Service进行多实现」。这个理由不充分,或者说没有考虑场景。实际上在大多数情况下是不需要多实现,或者说可能使用其它形式代替基于接口的多实现。 另外,对于很多使用了接口的我的项目,我的项目结构也是有待商讨的!上面,咱们拆散我的项目结构来说明。 我的项目结构与接口实现一般我的项目结构都是按层来划分的,如下所示: Controller Service Dao

December 21, 2021 · 1 min · jiezi

关于rabbitmq:Rabbit-MQ集群节点类型的选择

查看节点类型在应用命令 rabbitmqctl cluster_status 命令查看集群状态时,会有这样一项信息: {nodes,[{disc,[rabbit@centos1,rabbit@centos2,rabbit@centos3]}]}其中,disc 就示意节点的类型。 Rabbit MQ 的节点类型,总共有两种:磁盘节点和内存节点。 数据存储内存节点将所有的队列、交换器、绑定关系、用户、权限和 vhost 的元数据定义都存储在内存中。而磁盘节点会将这些信息都存储到磁盘中。 单节点的集群中,必然只有磁盘类型的节点,否则当重启 Rabbit MQ后,所有对于零碎的配置信息都会失落。 设置节点类型退出集群时设置退出集群时,默认类型为磁盘节点,能够指定 ”--ram“ 示意增加为内存节点: [root@centos2 ~]# rabbitmqctl join_cluster rabbit@centos1 --ram# 集群的信息为:[ {nodes,[{disc,[rabbit@centos1]},{ram,[rabbit@centos2]}]}, {running_nodes,[rabbit@centos1,rabbit@centos2]}, {cluster_name,<<"rabbit@centos1">>}, {partitions,[]}, {alarms,[{rabbit@centos1,[]},{rabbit@centos2,[]}]}]批改集群节点类型如果集群曾经搭建好,能够应用命令 rabbitmqctl change_cluster_node_type {disc,ram} 切换节点类型。将 centos2 更改为磁盘节点类型: [root@centos2 ~]# rabbitmqctl stop_app[root@centos2 ~]# rabbitmqctl change_cluster_node_type disc[root@centos2 ~]# rabbitmqctl start_app节点的抉择在集群中创立队列、交换器和绑定关系时,这些操作都须要集群中所有节点都胜利提交元数据才会返回。内存节点会存入内存,磁盘节点会写入磁盘。内存节点有着杰出的性能,磁盘节点能够提供高可靠性。 Rabbit MQ 要求在集群中至多有一个磁盘节点,其余的节点能够内存节点。当节点退出或来到集群时,必须将信息告诉到至多一个磁盘节点。 如果说,集群中只有一个磁盘节点,而凑巧不巧这个磁盘节点服务解体了,那么对于集群来说,依然能够持续承受或发送音讯,然而不能进行创立队列、交换器、绑定关系、用户,以及更改权限、增加和删除节点的操作。在磁盘节点复原之前是无奈执行任何更改操作的。所以,在集群中至多要有两个磁盘节点或者更多。 内存节点重启后,会先连贯到磁盘节点,拷贝以后集群的配置的元数据正本。当有内存节点增加到集群时,会告诉集群所有的磁盘节点。内存节点惟一写入磁盘的元数据信息就是集群中是磁盘节点的地址。只有内存节点能够找到至多一个磁盘节点,那么就能在重启后退出集群。 为了保障集群的可靠性,或者不确定是应用磁盘节点还是内存节点时,倡议全副抉择磁盘节点。

November 28, 2021 · 1 min · jiezi

关于rabbitmq:Rabbit-MQ多机多节点集群配置

像 Rabbit MQ 这种消息中间件,一旦在我的项目中用到了,就阐明我的项目的体量曾经到了肯定的级别,单机节点就显得顾此失彼了。所以,个别都会搭建一个集群。上面就试着搭建三台机器的集群。 节点信息节点一:192.168.0.116 centos1 节点二:192.168.0.117 centos2 节点三:192.168.0.118 centos3 配置 hosts 文件配置各个节点的 hosts 文件,让各个节点都能相互辨认对方。 # /etc/hosts192.168.0.116 centos1192.168.0.117 centos2192.168.0.118 centos3复制 cookie 文件编辑 Rabbit MQ 的 cookie 文件,以确保各个节点的 cookie 文件是同一个。这里应用 centos1 节点的 cookie 文件,将 centos1 的 cookie 文件复制到 centos2 和 centos3 的 /var/lib/rabbit/.erlang.cookie 或者 $HOME/.erlang.cookie下。 cookie 文件地位cookie 文件默认门路为 /var/lib/rabbit/.erlang.cookie 或者 $HOME/.erlang.cookie。cookie 相当于密钥令牌,集群中的节点须要通过替换密钥令牌取得互相认证。 如果应用解压缩装置形式(二进制装置或者编译装置),那么该文件存在地位为$HOME目录下。即$HOME/.erlang.cookie。如果咱们应用root装置,则地位为:/root/.erlang.cookie,其余用户为/home/用户名/.erlang.cookie。如果应用rpm包形式装置,那么这个文件会存在于/var/lib/rabbitmq目录下。查找 .erlang.cookie 文件能够通过查看 Rabbit MQ log 日志的信息,如上面所示:所以我的 .erlang.cookie 文件在 /root/.erlang.cookie [info] <0.270.0> node : rabbit@centos1 home dir : /root(我是 root 用户启动的) config file(s) : (none) cookie hash : tCXB8mlCcGEGGV1cYRkQCg== log(s) : /usr/local/rabbitmq_server/var/log/rabbitmq/rabbit@centos1.log : /usr/local/rabbitmq_server/var/log/rabbitmq/rabbit@centos1_upgrade.log database dir : /usr/local/rabbitmq_server/var/lib/rabbitmq/mnesia/rabbit@centos1配置集群配置集群有三种形式,这里应用 rabbitmqctl 工具配置: ...

November 27, 2021 · 6 min · jiezi

关于rabbitmq:个人学习系列-SpringBoot整合RabbitMQ

钻研一下音讯队列,当初来简略搭建一下。1. Docker搭建RabbitMQ1.1 查问并下载RabbitMQ镜像docker search rabbitmq // 抉择能够拜访web治理界面的tagdocker pull rabbitmq:management 1.2 运行RabbitMQ镜像// 设置账号密码都为admindocker run -dit --name myrabbitmq -e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=admin -p 15672:15672 -p 5672:5672 rabbitmq:management1.3 浏览器上拜访 服务器IP:15672呈现以下页面示意启动胜利 2. 搭建SpringBoot我的项目整合RabbitMQ2.1 pom.xml增加web和rabbitmq的依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId></dependency><dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId></dependency><dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope></dependency><dependency> <groupId>org.springframework.amqp</groupId> <artifactId>spring-rabbit-test</artifactId> <scope>test</scope></dependency>2.2 aplication.yml将rabbitmq的地址用户名明码等配置上 spring: rabbitmq: host: localhost port: 5672 username: admin password: admin2.3 新建交换机SenderConfig.java有以下三种罕用的交换机,咱们这里应用第三种 DirectExchange直连型交换机,依据音讯携带的路由键,将音讯转发给对应的队列FanoutExchange扇形交换机,接管到音讯后会将音讯转发到所有队列TopicExchange主题交换机,依据音讯携带的路由键和交换机与队列绑定键的规定,将音讯转发给对应的队列规定: *(星号):示意一个字符必须呈现 #(井号):示意任意数量的字符/** * 交换机 * @author zhouzhaodong */@Configurationpublic class SenderConfig { /** * ----- 交换机 ----- * 参数意义: * name: 名称 * durable: 长久化 * autoDelete: 主动删除 */ @Bean public TopicExchange topicExchange() { return new TopicExchange("topicExchange", true, false); } /** * ----- 队列 ----- */ @Bean public Queue queueOne() { return new Queue("queueOne", true); } @Bean public Queue queueTwo() { return new Queue("queueTwo", true); } @Bean public Queue queueThree() { return new Queue("queueThree", true); } /** * ----- 绑定 ----- * routingKey就是路由规定,音讯对应的队列,用来辨别不同的音讯队列 */ @Bean public Binding bindingFanoutOne() { return BindingBuilder.bind(queueOne()).to(topicExchange()).with("topic_one"); } @Bean public Binding bindingFanoutTwo() { return BindingBuilder.bind(queueTwo()).to(topicExchange()).with("topic_two"); } @Bean public Binding bindingFanoutThree() { return BindingBuilder.bind(queueThree()).to(topicExchange()).with("topic_one"); }}2.4 发送者 SenderController.java/** * 音讯发送者 * * @author zhouzhaodong */@RestControllerpublic class SenderController { @Resource AmqpTemplate amqpTemplate; Logger logger = LoggerFactory.getLogger(SenderController.class); @RequestMapping(value = "/send") public String sendMessage(String message) { logger.info("音讯发送开始工夫:" + new Date()); // 这里convertAndSend第一个参数是交换机的名称 // 第二个参数能够是routingKey // 最初一个参数就是要发送的音讯 amqpTemplate.convertAndSend("topicExchange", "topic_one", message); return "发送胜利"; }}2.5 消费者 ReceiverController.java/** * 消费者 * @author zhouzhaodong */@Componentpublic class ReceiverController { Logger logger = LoggerFactory.getLogger(ReceiverController.class); @RabbitHandler @RabbitListener(queues = "queueOne") public void processA(String message){ logger.info("queueOne接管音讯工夫为:" + new Date()); logger.info("queueOne接管音讯为:" + message); } @RabbitHandler @RabbitListener(queues = "queueTwo") public void processB(String message){ logger.info("queueTwo接管音讯工夫为:" + new Date()); logger.info("queueTwo接管音讯为:" + message); } @RabbitHandler @RabbitListener(queues = "queueThree") public void processC(String message){ logger.info("queueThree接管音讯工夫为:" + new Date()); logger.info("queueThree接管音讯为:" + message); }}3. 启动我的项目进行测试3.1 调用生产者接口发现有两个队列收到了音讯,因为这两个队列都配置的routingKey雷同,都是topic_one ...

November 23, 2021 · 2 min · jiezi

关于rabbitmq:RabbitMq38-的功能和配置

一、RabbitMQ的四种交换机最新版本的RabbitMQ有四种交换机类型,别离是:Direct exchange、Fanout exchange、Topic exchange、Headers exchange 1、Direct exchange---间接类型交换机要求音讯带的路由键和绑定的路由键齐全匹配,这是一个残缺的匹配。 比方一个队列A绑定到该交换机上的路由键是“abc”,则只有指定的路由键是“abc”的音讯才被投递给队列A,其余的不会投递给队列A 2、Fanout Exchange---扇出类型交换机只须要简略的将队列绑定到该类型交换机上,该类型的交换机绑定队列时能够不指定路由键(Routingkey) 当音讯发送给该交换机后,它会将音讯投递给与该交换机绑定的所有队列 很像播送,每台子网内的机器都会取得一份音讯,Fanout交换机转发音讯是最快的 3、Topic Exchange---主题类型交换机将路由键和某模式进行匹配。此时队列须要绑定某一个模式上。符号#匹配0个或多个单词,符号 *匹配一个单词。 4、Headers Exchanges能够选择性疏忽 首页 Broker:能够简略的了解为装置了RabbitMQ服务的这台机器就能够称为一个BrokerExchange:交换机,音讯经由它,通过路由键来判断并决定把音讯投递给哪个队列,它相似于一个路由器的角色Queue:队列,最终将音讯投递到队列中,由生产端监听队列进行生产Binding:绑定关系,须要给交换机绑定队列,绑定时须要给一个路由键Routingkey:路由键,交换机和队列进行绑定时,须要指定路由键或通配符路由键。交换机依据路由键来决定音讯投递到哪个或哪些队列大抵流程:首先须要依据业务来创立交换机和队列,应用RabbitMQ前创立实现后须要给交换机绑定队列(交换机和队列能够是多对多的关系),绑定队列时要指定具体的路由键或者通配符路由键当生产者发送一条音讯的时候,须要指定交换机和路由键,音讯达到Broker后先转给方才指定的交换机,交换机再依据路由键来决定把音讯投递给与本人绑定的哪一个或哪一些队列,最初再由生产端来监听这些队列,生产解决对应的音讯二、在治理页面配置交换机,队列等 2、创立队列点击Queues菜单 Add a new queue里输出要新创建的队列信息 3、创立绑定关系在交换机列表点击对应的交换机,进入绑定页面 三. 测试测试给Fanout类型交换机发送音讯 所有和Fanout类型交换机绑定的对应都应该收到音讯Automatic ack 示意读完不会把音讯放回队列Nack messages xx 示意读完 会把音讯放回队列测试给direct类型交换机发送音讯 测试给Topic类型交换机发送音讯测试发送一条路由键为China.news的音讯,依据咱们建设的绑定关系和绑定关系中的通配符路由键判断 这条音讯3个队列应该都能够收到

November 22, 2021 · 1 min · jiezi

关于rabbitmq:CentOS7安装RabbitMQ

装置erlang因为rabbitmq是基于erlang语言开发的,所以必须先装置erlang。 装置依赖 yum -y install gcc glibc-devel make ncurses-devel openssl-devel xmlto perl wget gtk2-devel binutils-devel下载(会比较慢,请急躁期待) wget http://erlang.org/download/otp_src_23.0.tar.gz 解压 [root@t3-yyknccs-hipcust-app01 sysadm]# tar -xf otp_src_23.0.tar.gz [root@t3-yyknccs-hipcust-app01 sysadm]# lsminio openresty-1.19.3.1_use.tar.gz otp_src_23.0 rabbitmq-server-3.8.11 seata-server-1.4.2.tar.gznohup.out openresty-usrlocal.tar.gz otp_src_23.0.tar.gz rabbitmq-server-3.8.11.tar.xz software.tar.gz[root@t3-yyknccs-hipcust-app01 sysadm]# cd otp_src_23.0[root@t3-yyknccs-hipcust-app01 otp_src_23.0]# lsAUTHORS CONTRIBUTING.md Jenkinsfile.benchmark Jenkinsfile.windows make otp_versions.table README.mdbin erl-build-tool-vars.sh Jenkinsfile.daily-rebuild Jenkinsfile.wsl Makefile.in plt scriptsbootstrap erts Jenkinsfile.run-otp-tests jenkins-swarm otp_build prebuilt.files systemconfigure HOWTO Jenkinsfile.run-otp-tests-wsl lib otp_patch_apply proposed_updates.json TAR.includeconfigure.src Jenkinsfile Jenkinsfile.test-configurations LICENSE.txt OTP_VERSION README-jenkins.md xcomp[root@t3-yyknccs-hipcust-app01 otp_src_23.0]# ./configure --prefix=/usr/local/erlang如果遇到这个错 你就伪装没看到 ...

November 19, 2021 · 1 min · jiezi

关于rabbitmq:科普-关于Rabbit-MQ与AMQP协议概念你想了解的都在这里

导语本文从AMQP协定(Advanced Message Queuing Protocol,高级音讯队列协定)、音讯性能、生产模型、金融级用法及其他性能点比照等概念介绍对RabbitMQ做了科普, 心愿对各位深刻了解RabbitMQ有帮忙。 AMQP协定概念AMQP协定本身定义了很多概念,上面先对这些概念进行分析,会更偏重从每个概念实体的作用域、职责范畴、从属关系等维度进行介绍。 Connection 对应底层一个AMQP-Client到RabbitMQ-Broker的一个TCP连贯。这边要思考两个端点问题,在TCP连贯建设实现后,如下图所示,连贯的指标Broker就曾经确定是集群中的一台了,因为是长连贯,除非断连重建,否则对端节点不可变。所以从这里能够看出RabbitMQ相比Pulsar、RocketMQ不一样的中央在于,其是一种服务端寻址模型,以Client的视角来看,想要连贯任意Exchange、Queue,只有连上任意一台Broker就行。Channel信道,能够了解为一种逻辑连贯,体现了多路复用的设计思路。反对串行执行,包含收和发的指令,能够了解为一种半双工模式的“虚构网络通道”。所有Exchange、Queue、Binding的操作都是在Channel之上进行的。Vhost等价于一种租户隔离概念,不同Vhost下能够创立同名Exchange、Queue,这样能够进行业务隔离。RabbitMQ的权限隔离和权限维度管制的机制是在Vhost级别的。Rabbit官网原生的全局Policy管制在Vhost级别。Exchange一个虚构实体,申明不同音讯的路由策略,本身不存储音讯。一个路由器,基于音讯头部的RoutingKey和Header将音讯路由到符合条件的具体的Queue。反对单播和播送。Queue音讯存储实体,是音讯底层存储的容器,相似Pulsar的Topic。单订阅模式,其下的Consumer别离生产到一部分音讯。和存储关联,因而有容量下限、TTL等存储层的个性。反对多生产和独占生产,取决于你订阅时设置的参数。因为它是存储音讯零碎的音讯,所以外部基于一个音讯位点管制长久化生产进度,记录最初被生产并Ack的地位。面向Consumer。Binding连接Exchange和Queue的桥梁,实质是一个规定的申明。一个Exchange下能够有多个Binding。一个Queue也能够被多个Binding关联。一个Exchange到一个Queue也能够申明多个Binding。音讯性能上面介绍RabbitMQ官网所提供的的开源原生性能,咱们晓得,AMQP协定能够看做成一种可编程式的音讯队列协定,能够基于其提供的根底模型,通过本人的奇妙搭配组合,结构出多种多样的业务模型。 音讯构造# publishInfoexchange: amq.directimmediate: falsemandatory: falseroutingKey: test# headerBodybodySize: 1024properties: - contentType: - encoding: - deliveryMode: - priority: - correlationId: - replyTo: - expiration: - messageId: - timestamp: - type: - userId: - appId: - clusterId: - headers: {}# contentBody二进制音讯体bytes每个音讯分为三个局部,在网络层面即三个独立数据帧: PublishInfo: 音讯路由申明信息,能够联想成写电子邮件时填写的指标邮箱、是否接管回执等前置申明。HeaderBody: 音讯头部,用于存储RabbitMQ本身当时定义的申明,能够联想层HTTP协定的Header一样,此处能够搁置一些对业务通明的上下文信息用于提供某种性能,比方分布式链路追踪的TraceId。ContentBody: 音讯体,无差别二进制数据块,服务端不感知其是否压缩、是否加密等,只进行通明的存储和读取投递。work queue 工作队列 它是一种模型简化,发送音讯时指定Exchange为空,RoutingKey为QueueName,Broker当前会间接把这个音讯发送至指标Queue,这样对用户来说相当于没Exchange,他认为是间接用Queue来生产,就比较简单。工作队列只实用于单订阅的场景,因为Queue只实用于单订阅。官网解说Publish/Subscribe 公布订阅模式 Queue不反对多订阅,通过转换思路实现: 一个Fanout类型的Exchange:相当于多订阅场景的Topic。多个不同的Queue:绑定到该Exchange,相当于多订阅场景下的Subscription。多个Consumer生产同一个Queue:惯例场景多订阅。每个Consumer各自生产一个Queue:实例级别播送。官网解说对齐RocketMQ、Pulsar的多订阅生产、播送生产Routing 路由模式 路由模式是用Rabbit最罕用的一种模式。Producer公布了一个Exchange,这个Exchange的类型是Direct,在Message中指定RoutingKey,并设置一个非空的值,接下来申明一些Queue,这些 Queue在申明和绑定Exchange的时候,须要指定Binding,音讯在路由的时候判断音讯里的RoutingKey和BindingKey是不是equal,如果是对等的就能够路由过去。相似tag过滤的音讯散发场景。官网解说对齐rocketmq、pulsar的tag过滤生产Topic 通配符模式 路由模式的升级版,反对通配符匹配。Exchange类型为Topic。匹配规定不是正则表达式,是AMQP本人的语法。官网解说Header模式不罕用,匹配规定不基于RoutingKey,而是基于HeaderBody.Properties.Headers中的键值对。反对齐全匹配所有键值对。反对只匹配一个键值对。RPC模式 RPC模式并不罕用,基于回复队列。生产者和消费者采纳一问一答的模式。等价于RPC的request-response模型。官网解说生产模型生产模型也是应用一个音讯零碎所须要特地关怀的一环,在业务的应用过程中,更多地会关注一条音讯从生产到投递至消费者整个过程中都经验了什么,整个音讯的申明周期是如何闭环的? 上面次要从TDMQ RabbitMQ版的实现来分析RabbitMQ协定的音讯生命周期。 从音讯的生命周期对待生产模型 已投递未Ack:Consumer独占,直到Consumer触发Ack或者Consumer断开。Ack音讯:标记已生产,位点后退。Nack音讯:底层操作等价于Ack,会依据配置转发到死信Exchange,否则抛弃。Requeue:音讯放回队头,待下次投递。从外部外围组件看生产模型 Queue:负责存储原始音讯数据,按序存储。RedeliveryTracker:负责记录Consumer端Requeue的音讯,并触发从新投递,标识投递次数。Dispatcher:负责管理连贯Queue的所有Consumer,负责音讯的负载平衡、散发、进度治理等。Limiter:QoS限流器,基于Unack数限流,而不是QPS,响应上方音讯生命周期。Unack Tracker:跟踪以后Channel中已投递未Ack的音讯。从这张图能够获取那些信息?一个Queue能够被不同Connection连贯、被同一个Connection的不同Channel连贯。一个Channel中能够启动两个Consumer连贯同一个Queue。QoS限流作用域为Channel,即一个Channel中创立的多个Cconsumer享有雷同的配额。如果BasicQoS Global设置为true,那么同一个Channel中的Consumer用尽配额,该Channel下的所有Consumer全副阻塞,无奈接管新音讯。Unack追踪器也是Channel作用域,故一个Channel敞开,被该Channel独占的所有未Ack音讯全副回收到Queue级别的跟踪器,进行全局重投递。basic指令集: https://www.rabbitmq.com/amqp...Consumer Prefetch: https://www.rabbitmq.com/cons...金融级用法 ...

November 10, 2021 · 1 min · jiezi

关于rabbitmq:RabbitMQ-解决消息延迟和堆积问题

大家好,我是小菜。一个心愿可能成为 吹着牛X谈架构 的男人!如果你也想成为我想成为的人,不然点个关注做个伴,让小菜不再孤独! 本文次要介绍 RabbitMQ的常见问题 如有须要,能够参考 如有帮忙,不忘 点赞 ❥ 微信公众号已开启,小菜良记,没关注的同学们记得关注哦! 音讯可靠性问题:如何确保发送的音讯至多被生产一次?提早音讯问题:如何实现音讯的提早投递?音讯沉积问题:如何解决数百万级以上音讯沉积,无奈及时生产问题?咱们在上篇曾经阐明了如何解决音讯失落的问题,也就是保障了音讯的可靠性,那么其余两个问题同样重要,这篇咱们将讲述其余两个问题的解决形式~! 音讯失落解决方案:《RabbitMQ》 | 音讯失落也就这么回事一、提早音讯提早音讯 字面意思就是让提早接管音讯,那么如何能让音讯提早达到?这就是咱们要思考解决的问题,在理解提早队列之前咱们须要先明确 RabbitMQ 中的两个概念 死信交换机TTL1)死信交换机死信(dead letter),也就是废除已死亡的音讯,那什么状况下一个一般的音讯可能成为死信?须要合乎以下三个条件: 消费者应用 basic.reject 或 basic.nack 申明生产失败,并将音讯的 requeue 参数设置为 false音讯是一个过期音讯,超时后无人生产要投递的队列音讯沉积满了,最早的音讯就会成为死信而 死信交换机 便是 死信 的归属。 如果一个队列配置了 dead-letter-exchange 属性,指定了一个交换机,那么队列中的死信就会投递到这个交换机中,而这个交换机就称为 死信交换机 - DLX(Dead Letter Exchange ) 步骤:当生产者失常投递到队列(simple.queue)中,如果消费者从队列(simple.queue) 生产音讯却申明了 reject,那并且队列绑定了死信交换机(dl.queue),那么这个时候成为死信的音讯就会投递到这个死信队列(dl.queue)中。 从失常队列 --> 死信队列 的过程,咱们必须申明两个要害信息 死信交换机的名称死信交换机与死信队列绑定的路由key而这两个信息也是咱们投递音讯的根底配置。 接下来咱们简略模仿一下 条件1 所产生的场景 1、首先申明一个死信交换机和死信队列咱们这边是应用简略的注解形式间接生成 通过 RabbitMQ 控制台界面能够看出曾经胜利生成 2、申明失常应用交换机与队列而后这个时候咱们就能够创立一个失常应用的交换机与队列,并指明死信交换机 同样能够通过控制台查看创立状态 其中是否有申明死信交换机咱们能够通过队列的 DLX 和 DLK 标记判断 3、模仿拒收而后咱们当初通过代码模仿客户端回绝音讯的场景 1)音讯发送 2)音讯接管 ...

November 7, 2021 · 2 min · jiezi

关于rabbitmq:RabbitMQ各Exchange适用场景

Default Exchange(默认交换机)在首先创立一个 Queen 之后,RabbitMQ 会把这个 Queen 间接绑定到默认交换机上,并且应用 Queen 的名字作为 Routing Key。因而,对外体现的成果就是,客户端向这个 Queen 间接投递音讯,严格匹配。 // TODO 此处应该有代码Direct exchange(直连交换机)和 Default Exchange 相似,但灵便度更高,基于 AMQP 协定,能够由 Producer 或 Consumer 进行指定,伪代码如下: //实现BeanPostProcessor类,应用Bean的生命周期函数@Componentpublic class DirectRabbitConfig implements BeanPostProcessor { //这是创立交换机和队列用的 RabbitAdmin 对象 @Resource private RabbitAdmin rabbitAdmin; //初始化 RabbitAdmin Bean @Bean public RabbitAdmin rabbitAdmin(ConnectionFactory connectionFactory) { RabbitAdmin rabbitAdmin = new RabbitAdmin(connectionFactory); // 只有设置为 true,spring 才会加载 RabbitAdmin 这个类 rabbitAdmin.setAutoStartup(true); return rabbitAdmin; } //实例化bean后,也就是Bean的后置处理器 @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { //向 RabbitMQ 申明创立 Exchange rabbitAdmin.declareExchange(rabbitmqDemoDirectExchange()); //向 RabbitMQ 申明创立 Queen rabbitAdmin.declareQueue(rabbitmqDemoDirectQueue()); return null; } /** * 申明一个 Queen Bean, 用于下面这个办法 */ @Bean public Queue rabbitmqDemoDirectQueue() { /** * 1、name: 队列名称 * 2、durable: 是否长久化 * 3、exclusive: 是否独享、排外的。如果设置为true,定义为排他队列。则只有创建者能够应用此队列。也就是private公有的。 * 4、autoDelete: 是否主动删除。也就是长期队列。当最初一个消费者断开连接后,会主动删除。 * */ return new Queue(RabbitMQConfig.RABBITMQ_DEMO_TOPIC, true, false, false); } /** * 申明一个 DirectExchange Bean, 用于下面的下面这个办法 */ @Bean public DirectExchange rabbitmqDemoDirectExchange() { //Direct交换机 return new DirectExchange(RabbitMQConfig.RABBITMQ_DEMO_DIRECT_EXCHANGE, true, false); } /** * 申明一个 Binding Bean, 用于把 Queen 和 Exchange 进行绑定 * 并设置 RabbitMQConfig.RABBITMQ_DEMO_DIRECT_ROUTING 作为 Routing Key * 投递音讯的时候能够应用这个 key 通过这个 Exchange 发送到这个 Queen 上 */ @Bean public Binding bindDirect() { //链式写法,绑定交换机和队列,并设置匹配键 return BindingBuilder //绑定队列 .bind(rabbitmqDemoDirectQueue()) //到交换机 .to(rabbitmqDemoDirectExchange()) //并设置匹配键 .with(RabbitMQConfig.RABBITMQ_DEMO_DIRECT_ROUTING); }}Fanout exchange(扇形交换机)无需依附 Routing Key,所有绑定到这种 Exchange 上的 Queen 都会收到投递,因而适宜播送音讯: ...

October 17, 2021 · 2 min · jiezi

关于rabbitmq:Linux环境下使用PackageCloud安装RabbitMQ

一、装置PackageCloud脚本运行 Package Cloud 提供 Erlang 环境疾速装置脚本 curl -s https://packagecloud.io/install/repositories/rabbitmq/erlang/script.rpm.sh | sudo bash运行 Package Cloud 提供的 RabbitMQ Server 疾速装置脚本 curl -s https://packagecloud.io/install/repositories/rabbitmq/rabbitmq-server/script.rpm.sh | sudo bash二、装置Erlang和RabbitMQ Server查看版本匹配 RabbitMQ和Erlang版本对应关系装置 Erlang环境 yum -y install erlang-23.3.4.3-1.el7.x86_64测试 Erlang erl -version装置 RabbitMQ Server yum -y install rabbitmq-server-3.8.19-1.el7.noarch三、设置RabbitMQ开机自启设置RABBITMQ开机启动 chkconfig rabbitmq-server on启动RABBITMQ服务 systemctl start rabbitmq-server.service开启WEB可视化治理插件 rabbitmq-plugins enable rabbitmq_management增加用户明码 rabbitmqctl add_user admin admin rabbitmqctl set_user_tags admin administrator登录 http://192.168.10.103:15672/ IP 换成本人的 IP四、查看防火墙做完下面步骤,肯能还是近程连贯不上,凋谢端口或者敞开防火墙查看防火墙状态 systemctl status firewalld查看开机是否启动防火墙服务 systemctl is-enabled firewalld敞开防火墙 systemctl stop firewalld禁用防火墙(系统启动时不启动防火墙服务) ...

September 14, 2021 · 1 min · jiezi

关于rabbitmq:EMQ-X-与-RabbitMQ-消息服务器-MQTT-性能对比下

在上篇文章中,咱们采纳雷同的硬件资源别离对 MQTT 音讯服务器 EMQ X 和 RabbitMQ 进行了压力测试。结果表明:在「多对一」 场景中,EMQ X 和 RabbitMQ 相比并没有太大差异;而在「一对多」场景中,RabbitMQ 则较 EMQ X 产生了较为显著的差距。 本期文章中咱们将对这一后果进行进一步的解析。 造成差距的起因次要有三个:节点间通信的形式、音讯流架构的形式、队列的应用。 节点间的通信RabbitMQ - 委托架构RabbitMQ 应用了 Erlang 语言的分布式连贯,即每个节点之间两两相互连贯,每个节点用一个繁多的链接连贯着另一个节点。在图中的状况下,三个节点顺次连贯;当节点之间须要通信时,一条音讯须要通过这个繁多链接从一个节点发送到另一节点。 在扇出(fan-out)的例子中,失常来讲你须要将音讯推送到所有节点的队列上。RabbitMQ 应用的优化形式则是:你的音讯只须要发送一次,之后其内置的代理委托框架会将这一条音讯派送并且发到其余节点的队列上。这个过程中,音讯是有序发送的,所以保障了音讯在不同队列里都是雷同的程序。 然而这个计划也不是美中不足的,因为你会将所有的音讯只发送一次,在散发工作都依附同一个委托过程。而且 RabbitMQ 抉择这个代理过程的策略是依据发布者的哈希算法。所以,当如果你只有一个发布者,所有的音讯都会被始终推送到单个的委托代理过程。 EMQ X - Gen_RPC在 EMQ X 中有个精妙的设计:其不仅存在着分布式连贯,还存在着 Gen_RPC。散布连贯和 Gen_RPC 各司其职,前者用于替换 Mnesia 的数据信息,后者则只实用于音讯的转发。每当你须要从一个节点向另一个节点公布一个音讯的时候,EMQ X 不是从新主动生成新的节点间链接(默认 1 个连贯),再通过这些新的连贯去解决把一个音讯从一个节点推送到另一个节点的工作。而是依附针对此场景顺便设计的,专有的 Gen_RPC 连贯来解决这个音讯推送的工作。所以在扇出(一对多)的例子中,这些链接会被齐全无效地利用。 但这种设计在网络分区环境中其性能有可能受到影响,RabbitMQ 节点之间只有一个分布式连贯,所以当连贯断开造成脑裂时,愈合修复的工作将会更简略。 音讯流MQTT 插件RabbitMQ 在应用 MQTT 插件后会监听应用 MQTT 协定公布的音讯。失去音讯之后,音讯被解析,之后再通过 AMQP 协定进行转化,最初才会被发送到 RabbitMQ 上。 如果要发送一条音讯,须要通过套接字后进入 mqtt_reader,接下来再进入下图所示的所有过程。然而如果要在同一条通道里同时接管刚刚发送的这条音讯,所有上图所示的过程则须要反着从新进行一次,包含 mqtt_reader。其中,mqtt_reader 不仅负责了读,也负责了写。 ...

September 2, 2021 · 2 min · jiezi

关于rabbitmq:rabbitmq学习整理

本篇文章次要是对《Rabbitmq实战》这本书的关键点做一些总结和整顿,另外再加一些网上整顿的扩大知识点。这里我截了一张图,不便辨认 知识点什么是Rabbitmq各个角色多租户模式如何做长久化集群模式其余重要点 什么是Rabbitmq简略的说就是一个用erlang编写的基于AMQP协定通信的音讯队列中间件,通过它可能做到程序之间通信的解耦、流控,可能做到对音讯的长久化,保障在通信过程中呈现宕机等状况下音讯不失落。如何装置见我另一篇文章《Rabbitmq装置部署》 各个角色生产者消费者信道/队列/交换器/绑定 生产者生产者就是生产音讯的一方,生产者创立完音讯之后,将音讯发送到rabbitmq。这里波及到音讯定义,音讯次要有两局部形成:数据和标签。数据就是咱们平时要发送给消费者的内容,标签次要是为了让rabbitmq晓得音讯的特色、要发送给谁。音讯发后即忘。 消费者消费者就是连贯到rabbitmq上,并订阅某个队列,期待接管该队列的音讯或者能够被动去拉取该队列的音讯。音讯的生产波及到推和拉两种模式,上面是两种模式的介绍 推模式(举荐):1、channel.basicConsume(queneName,consumer)办法将信道(channel)设置成投递模式,直到勾销队列的订阅为止;在投递模式期间,当音讯达到RabbitMQ时,RabbitMQ会主动地、一直地投递音讯给匹配的消费者,而不须要生产端手动来拉取,当然投递音讯的个数还是会受到channel.basicQos的限度。2、推模式将音讯提前推送给消费者,消费者必须设置一个缓冲区缓存这些音讯。长处是消费者总是有一堆在内存中待处理的音讯,所以当真正去生产音讯时效率很高。毛病就是缓冲区可能会溢出。3、因为推模式是信息达到RabbitMQ后,就会立刻被投递给匹配的消费者,所以实时性十分好,消费者能及时失去最新的音讯。拉模式:1、如果只想从队列中获取单条音讯而不是继续订阅,则能够应用channel.basicGet办法来进行生产音讯。2、拉模式在消费者须要时才去消息中间件拉取音讯,这段网络开销会明显增加音讯提早,升高零碎吞吐量。 3、因为拉模式须要消费者手动去RabbitMQ中拉取音讯,所以实时性较差;消费者难以获取实时音讯,具体什么时候能拿到新音讯齐全取决于消费者什么时候去拉取音讯。 信道/队列/交换器/绑定信道连贯到mq之后,在通信之前会首先创立一个信道(channel),他是基于Tcp连贯内的虚构连贯,能够复用一条Tcp连贯,从而缩小Tcp连贯的创立和销毁老本,每条信道都会有一个id,咱们和rabbitmq的所有交互都是通过信道实现的。ps:这里信道是如何实现共享一个tcp连贯并且可能不影响吞吐率的须要再钻研一下。 队列队列比较简单,就是一个寄存了一组音讯的数据结构,FIFO模式,生产者创立的音讯最终就是被mq放到队列里去了,消费者也是最终通过队列获取到音讯再进行生产,如果是多个消费者订阅一个队列的状况下,其中一个消费者生产胜利了,音讯就会从队列中被删除,音讯失败的话音讯就会被传递给下一个消费者(requeue设置为true)。当然mq的队列也有一些简单点的应用,包含死信队列和优先级队列。死信队列:当音讯没有被胜利生产咱们就能够把它丢入到死信队列中,哪些场景算没有胜利呢?1、音讯过期,也就是给音讯或者队列设置了TTL工夫;2、音讯被回绝,也就是音讯basic.reject或者basic.nack,并且reququq=false;3、队列达到最大长度;对以上这三种音讯成为死信音讯之后,咱们能够通过创立死信交换器,将死信音讯丢入到指定的队列中,这个队列就能够称之为死信队列,对于死信队列更具体的介绍,参考https://www.jianshu.com/p/986...。另外一个就是咱们能够基于音讯的优先程序创立优先级队列,如何创立优先级队列,参考https://blog.csdn.net/u013256...另外比拟有用的两个设置参数,这里截取书上一段话: 交换器交换器能够了解为一个路由器,生产者在发送音讯之后,mq会基于交换器的路由键(routing key)将音讯丢入对应的队列中去。类型有:direct、fanout、topic、headers。对于四种类型的具体形容,参考https://www.jianshu.com/p/469...。(headers曾经被淘汰,被direct取代) 绑定绑定比较简单,就是通过routing key将交换器和队列进行关联起来,使得音讯通过交换器之后能被发送到对应的队列里。 多租户模式每个rabbitmq服务器都能创立虚构音讯服务器,这就是虚拟主机(vhost)。vhost能够了解为一个mini版的rabbitmq服务器,它也有本人的队列、交换器、绑定等角色,还有本人的一套权限管制。比方你能够用同一个rabbitmq别离创立测试环境、开发环境、生产环境的vhost,达到不同环境隔离的目标,而不必启动多个rabbitmq服务器。咱们能够用rabbitmqctl去保护vhost,当然也能够通过web管理工具进行保护,参考:https://www.cnblogs.com/max19... 如何做长久化咱们在音讯通信的时候有时须要保障音讯不会失落,即便是零碎挂了,音讯仍然可能保留,这里就要说到音讯的长久化。默认状况下,rabbitmq重启之后,队列、交换器都是会隐没的,当然隐没的也包含外面的音讯。如何能做到不失落呢? 要长久化队列和交换器,设置其durable为true。次在音讯公布的时候将投递模式(delivery_mode)设置为2,并通过上一步设置的长久化交换器公布到长久化队列外面。 rabbitmq长久化音讯是写入到磁盘上的一个长久化日志文件里,写入胜利之后才会响应生产端胜利,后续如果该音讯被发到非长久化队列里,就会从持久性日志里移除。具体的长久化代码怎么写,参考:https://www.cnblogs.com/bigbe... 问题长久化保障了咱们的音讯不失落,同时也会带来一些问题,最次要的问题就是性能,因为它是写日志文件是波及到磁盘交互的。另外在集群模式下会有一些问题,因为默认的状况下,集群中每个节点都是各自保护本人的音讯队列,也就是其中一个节点宕机了,在其复原前,该节点内的音讯就无奈被生产了。总得来说应用长久化机制要进行衡量思考。 集群模式平时咱们在应用rabbitmq的时候,万一rabbitmq挂了怎么办,连带咱们的相干服务业务不就有影响了。这时候咱们就须要对rabbitmq做高可用,也就是部署rabbitmq集群。集群模式下,每个节点也能够抉择将元数据信息存入到磁盘或者内存中,这就是咱们看到DISK节点和RAM节点。默认状况下每个节点的队列都是各自保护的,也就是其中一个节点如果宕机了,那就意味着该节点所有队列中的所有音讯都临时隐没了,直到复原该节点。这时候你们可能曾经意识到问题了,这样的话那如何能保障其中一个节点挂了,音讯仍然失常解决呢?这里就波及到镜像队列的概念了,通过镜像队列,咱们就能够将节点的音讯都同步到其余节点。当然咱们还得做长久化,所有在集群模式下必须要有DISK节点来保障长久化。这里又波及到衡量取舍了,尽管保障了高可用,然而性能和存储空间方面又会受到影响,如果你的业务场景是不须要常常创立队列的,DISK节点影响就不大。失常集群搭建中,咱们须要保障有至多2个DISK节点来做长久化,另外RAM节点的效率是要高于DISK节点的,交互上能够和RAM节点交互。如何搭建,参考:https://blog.csdn.net/qq_2853... 其余重要点其余的重要点这里就是毫无逻辑的整顿了一下,大略晓得有这些点就能够了 erlang也有虚拟机,虚拟机上每个实例称为节点,erlang一个节点能够运行多个erlang应用程序,节点之间能够做本地通信(不论是否在同一台服务器上)。erlang上的应用程序解体了,erlang会主动尝试重启。日志目录在:/var/log/rabbitmq,能够以-detached形式以守护过程形式后盾启动。以stop命令洁净地进行敞开,避免音讯没解决完失落,rabbitmqctl治理操作参考https://www.cnblogs.com/wyt00...。通过对rabbitmq.config配置扭转监听端口以及占用的内存等信息,不存在这个文件本人新增一个。具体配置参考:https://www.cnblogs.com/wyt00...。应用mnesia数据库,他是非关系型rpc模式实现参考:https://blog.csdn.net/u013256...通过haproxy实现负载平衡,参考 https://www.cnblogs.com/Liang...提早队列实现,参考https://www.cnblogs.com/mfran... 总结因为知识点切实有点多,前面就做了一些简略的整顿,还须要本人多去操作能力相熟,文章记录只是作为疾速回顾。以上也只是本人的了解,有什么问题大家也能够提出来一起探讨。

August 19, 2021 · 1 min · jiezi

关于rabbitmq:Rabbitmq安装部署

最近在钻研rabbitmq,所以须要在本地搭建一套本人的mq,原本认为很简略,后果还是遇到了不少坑,这里记录一下,也顺便让大家在装置的时候可能有所借鉴。 版本抉择rabbitmq的装置,从网上一搜一大堆,有各种各样的文章,不过大体就两种形式装置:yum、rpm。这里咱们应用rpm形式装置(官网上举荐的是yum形式)。首先咱们要晓得rabbitmq是须要依赖erlang环境的,所以要先装置erlang。erlang的版本也不是随随便便找到一个就装置的,须要基于你要装置的rabbitmq版本来对应起来装置,具体对应关系在这:https://www.rabbitmq.com/whic...另外还和你的linux操作系统无关,截取官网一张图咱们本地的操作系统是centos7,所以我抉择装置erlang版本otp23.3,对应能抉择的最高的rabbitmq版本如图:这里我抉择最新的3.8.15版本。rabbitmq团队也基于mq的依赖缩减了官网erlang的内容,只保留的mq所需的内容(也就是精简版),两个地址别离为:erlang版本:https://www.erlang.org/downloadserlang精简版:https://github.com/rabbitmq/e...我这里抉择精简版装置,从这里抉择23.3的版本rabbitmq的rpm包也去下载一个本人要的版本,我这里是3.8.15下载地址:https://github.com/rabbitmq/r...下载完之后就传到本人的linux零碎对应的目录下。 装置1、先装置erlang所要依赖的环境yum install -y gccyum install -y perlyum install -y ncurses-develyum install -y openssl openssl-develyum -y install unixODBC-devel (如果还有漏装置的,依照报错提醒补上)2、装置erlangcd到你寄存erlang包的目录下,执行 rpm -ivh erlang-23.3-2.el7.x86_64.rpm执行erl -version查看是否装置胜利3、装置rabbitmqcd到你寄存rabbitmq包的目录下,执行 rpm -ivh rabbitmq-server-3.8.15-1.el7.noarch.rpm 部署执行 systemctl start rabbitmq-server如果是一个污浊的环境是比较顺利的,然而我本地就失败了,谬误如图依据提醒看具体信息:大略是曾经存在了,此时想起之前有装置过,然而没胜利,预计是那时候留下的。回过头看装置的时候其实也有提醒抵触:很显著的提醒了有一个3.8.1版本的抵触,那就先卸载原来的货色。 卸载先查一下装置的状况,执行命令:yum list | grep rabbitmq的确有曾经装置的版本,执行命令删除:yum -y remove rabbitmq-server.noarch实现卸载后从新依据下面的装置步骤装置rabbitmq包。 启动执行 systemctl start rabbitmq-server启动胜利之后装置治理插件。rabbitmq-plugins enable rabbitmq_management新增用户:rabbitmqctl add_user don 123456赋予权限:rabbitmqctl set_user_tags don administrator在本人的浏览器里拜访http://ip:15672就能看到如下治理界面: 总结至此,整个rabbitmq的装置部署就搞定了。理顺了其实还是挺简略的。参考资料:https://blog.csdn.net/weixin_...https://blog.csdn.net/wyp_810...https://blog.csdn.net/z_dy1/a...

August 6, 2021 · 1 min · jiezi

关于rabbitmq:docker安装rabbitmq集群

抉择rabbitmq镜像文件抉择那些带有management版本的镜像,刚开始不理解破费了很长时间没有搭建胜利,查看材料才晓得有的镜像只适宜单机搭建,只有带management的才可能搭建集群。镜像地址:https://hub.docker.com/_/rabb... 下载rabbitmq镜像文件:docker pull rabbitmq:3.8.3-management查看镜像文件docker images 创立三个容器docker run -d --name yx_rabbitmq1 -p 5672:5672 -p 15672:15672 --hostname rabbitmq1 -e RABBITMQ_ERLANG_COOKIE='rabbitmq' 867da7fcdf92docker run -d --name yx_rabbitmq2 -p 5673:5672 -p 15673:15672 --link yx_rabbitmq1:rabbitmq1 --hostname rabbitmq2 -e RABBITMQ_ERLANG_COOKIE='rabbitmq' 867da7fcdf92docker run -d --name yx_rabbitmq3 -p 5674:5672 -p 15674:15672 --link yx_rabbitmq2:rabbitmq2 --hostname rabbitmq3 -e RABBITMQ_ERLANG_COOKIE='rabbitmq' 867da7fcdf92PS: 同一个集群的RABBITMQ_ERLANG_COOKIE值须要设置一样,否则后边会出问题。这里不做具体解说,有趣味的话请看我下一期文章。run 多个容器能够通过--link去关联其它rabbitmq节点,--link {容器名}:hostname测试节点在浏览器输出 http://localhost:15672 间接查看当初节点散布状况。 由上图能够看出,三个节点还没有真正产生关联。为了集群内可能互相拜访,须要配置hosts文件。三个容器的hosts文件要配置的一样,如下图所示。 vim /etc/hosts 集群容器关联1.重置yx_rabbitmq1节点进入容器yx_rabbitmq1 docker exec -it yx_rabbitmq1 /bin/bash重置容器 yx_rabbitmq1 rabbitmqctl stop_app && rabbitmqctl reset && rabbitmqctl start_app2.设置节点yx_rabbitmq2,将其退出到集群: 进入容器yx_rabbitmq2 ...

August 5, 2021 · 1 min · jiezi

关于rabbitmq:mac-docker搭建rabbitmq

获取镜像docker pull rabbitmq创立并启动容器docker run -d --name rabbitmq --restart always --hostname rabbitmq -p 15672:15672 -p 5672:5672 rabbitmqps: --hostname rabbitmq存储数据的节点名称,默认是主机名,不指定更改主机名启动失败,默认门路/var/lib/rabbitmq/mnesia-p 指定宿主机和容器端口映射(5672:服务利用端口,15672:治理控制台端口)装置插件装置治理控制台插件 docker exec -it rabbitmq /bin/bashrabbitmq-plugins enable rabbitmq_managementps: 默认用户名/明码:guest/guest测试拜访http://localhost:15672/就能够呈现rabbitmq治理界面了 异样解决在点击Channels的时候,可能会揭示Stats in management UI are disabled on this node异样 #进入rabbitmq容器docker exec -it {rabbitmq容器名称或者id} /bin/bash#进入容器后,cd到以下门路cd /etc/rabbitmq/conf.d/#批改 management_agent.disable_metrics_collector = falseecho management_agent.disable_metrics_collector = false > management_agent.disable_metrics_collector.conf#退出容器exit#重启rabbitmq容器docker retart {rabbitmq容器id}

August 2, 2021 · 1 min · jiezi

关于rabbitmq:RabbitMQ进阶高级用法

音讯的去处mandatory和immediate是发送音讯办法中的两个参数,它们都有当消息传递过程中目的地不可达时将音讯返回给生产者的性能。RabbitMQ提供的备份交换器能够将未能被交换器路由的音讯存储起来,而不必返回给客户端。 mandatory参数当mandatory参数设为true时,交换器无奈依据本身的类型和路由键找到一个符合条件的队列,那么 RabbitMQ会将音讯返回给生产者。当mandatory参数设置为false时,则音讯间接被抛弃。 那么生产者如何获取到没有被正确路由到适合队列的音讯呢?这时候能够通过注册音讯返回监听器来实现: func (ch *Channel) NotifyReturn(c chan Return) chan Returnimmediate参数当immediate参数设为true时,如果交换器在将音讯路由到队列时发现队列上并不存在任何消费者,那么这条音讯将不会存入队列中。当与路由键匹配的所有队列都没有消费者时,该音讯会返回至生产者。 概括来说,mandatory参数通知服务器至多将该音讯路由到一个队列中,否则将音讯返回给生产者。immediate参数通知服务器,如果该音讯关联的队列上有消费者,则立即生产;如果所有匹配的队列上都没有消费者,则间接将音讯返还给生产看,不必将音讯存入队列而消费者了。 备份交换器生产者在发送音讯的时候如果不设置mandatory参数,那么音讯在未被路由的状况下将会失落。如果设置了mandatory参数,那么须要增加ReturnListener的编程逻辑,生产者的代码将变得复杂。如果既不想复杂化生产者的编程逻辑,又不想音讯失落,那么能够应用备份交换器,这样能够将未被路由的音讯存储在RabbitMQ中,再在须要的时候去解决这些音讯。 能够通过在申明交换器的时候设置args参数中的alternate-exchange选项来实现,也能够通过策略的形式实现。如果两者同时应用,则前者的优先级更高,会笼罩掉Policy的设置。 备份交换器其实和一般的交换器没有太大的区别,须要留神的是,音讯被从新发送到备份交换器时的路由键和从生产者收回的路由键是一样的。 对于备份交换器,总结了以下几种非凡状况: 如果设置的备份交换器不存在,客户端和RabbitMQ服务端都不会有异样呈现,此时音讯会失落。如果备份交换器没有绑定任何队列,客户端和RabbitMQ服务端都不会有异样呈现,此时音讯会失落。如果备份交换器没有任何匹配的队列,客户端和RabbitMQ服务端都不会有异样呈现,此时音讯会失落。如果备份交换器和mandatory参数一起应用,那么mandatory参数有效。过期工夫(TTL)设置音讯的TTL目前有两种办法能够设置音讯的TTL。第一种办法是通过队列属性设置,队列中所有音讯都有雷同的过期工夫。第二种办法是对音讯自身进行独自设置,每条音讯的TTL能够不同。如果两种办法一起应用,则音讯的TTL以两者之间较小的那个数值为准。音讯在队列中的生存工夫一旦超过设置的TTL值时,就会变成“死信”。 通过队列属性设置音讯TTL的办法是在QueueDeclare办法的args参数中退出x-message-ttl选项实现的,这个参数的单位是毫秒。同时也能够通过Policy或HTTP API接口设置。 如果不设置TTL,则示意此音讯不会过期。如果将TTL设置为0,则示意除非此时能够间接将音讯投递到消费者,否则该音讯会被立刻抛弃。 针对每条音讯设置TTL的办法是在Publish办法的音讯Publishing构造体中设置Expiration属性,单位为毫秒。也能够通过HTTP API接口设置。 对于第一种设置队列TTL属性的办法,一旦音讯过期,就会从队列中删除,而在第二种办法中,即便音讯过期,也不会马上从队列中删除,因为每条音讯是否过期是在行将投递到消费者之前断定的。 设置队列的TTL通过QueueDeclare办法的args参数中x-expires选项能够管制队列被主动删除前处于未应用状态的最大工夫,单位是毫秒,不能设置为0。未应用的意思是队列上没有任何的消费者,队列也没有被从新申明,并且在过期时间段内也未调用过Get办法。 设置队列里的TTL能够利用于相似RPC形式的回复队列,在RPC中,会创立很多未被应用的队列。 RabbitMQ会确保在过期工夫达到后将队列删除,然而不保障删除的动作有多及时。在RabbitMQ重启后,长久化的队列的过期工夫会被从新计算。 死信队列DLX,全称为Dead-Letter-Exchange,能够称之为死信交换器。当音讯在一个队列中变成死信之后,它能被从新被发送到另一个交换器中,这个交换器就是DLX,绑定DLX的队列就称之为死信队列。 音讯变成死信个别是因为以下几种状况: 音讯被回绝(Reject/Nack),并且设置requeue参数为false。音讯过期。队列达到最大长度。DLX也是一个失常的交换器,和个别的交换器没有区别,它能在任何的队列上被指定(实际上就是设置某个队列的属性)。当这个队列中存在死信时,RabbitMQ就会主动地将这个音讯从新公布到设置的DLX下来,进而被路由到死信队列。能够监听这个队列中的音讯以进行相应的解决,这个个性与将音讯的TTL设置为0配合应用能够补救immeaiate参数的性能。 通过在QueueDeclare办法的args参数中设置x-dead-letter-exchange选项来为这个队列增加DLX: err = ch.ExchangeDeclare( "dlx_exchange", "direct", true, false, false, false, nil, ) if err != nil { log.Fatalf("%s: %s", err, "Failed to declare an exchange") return } args := make(map[string]interface{}) args["x-dead-letter-exchange"] = "dlx_exchange" // 为队列my_queue增加DLX q, err := ch.QueueDeclare( "my_queue", true, false, false, false, args, ) if err != nil { log.Fatalf("%s: %s", err, "Failed to declare a queue") return }也能够为这个DLX指定路由键,如果没有非凡指定,则应用原队列的路由键: ...

July 14, 2021 · 2 min · jiezi

关于rabbitmq:RabbitMQ基础客户端开发

连贯RabbitMQ建设连贯func Dial(url string) (*Connection, error)url:RabbitMQ服务端url,例如:amqp://admin:admin@127.0.0.1:5672/创立信道func (c *Connection) Channel() (*Channel, error)Connection能够用来创立多个Channel实例,然而Channel实例不能在线程间共享,应用程序应该为每一个线程开拓一个Channel。某些状况下Channel的操作能够并发运行,然而在其余状况下会导致通信谬误,同时也会影响发送方确认(publisher confirm)机制的运行,所以多线程间共享Channel实例是非线程平安的。 应用交换器和队列申明交换器func (ch *Channel) ExchangeDeclare(name, kind string, durable, autoDelete, internal, noWait bool, args Table) errorname:交换器的名称。kind:交换器的类型,常见的如 fanout、direct、topic。durable:设置是否长久化。设置为长久化能够将交换器存盘,在服务器重启的时候不会失落相干信息。autoDelete:设置是否主动删除。主动删除的前提是至多有一个队列或者交换器与这个交换器绑定,当所有与这个交换器绑定的队列或者交换器都与此解绑时,会主动删除该交换器。留神不能谬误地把这个参数了解为“当与此交换器连贯的客户端都断开时,RabbitMQ会主动删除本交换器”。internal:设置是否是内置交换器。如果设置为true,则示意是内置的交换器,客户端程序无奈间接发送音讯到这个交换器中,只能通过交换器路由到交换器这种形式。noWait:是否非阻塞期待服务器返回。设置为true则不会阻塞期待RabbitMQ Server的返回信息(实际上服务器也不会返回),此时立刻应用这个交换器可能会导致异样,倡议设置为false。args:其余一些结构化参数,比方alternate-exchange等。还有另一个相似的参数齐全一样的办法ExchangeDeclarePassive,这个办法次要用来检测相应的交换器是否存在,如果存在则失常返回,不存在则抛出异样,同时Channel也会被敞开。 删除交换器func (ch *Channel) ExchangeDelete(name string, ifUnused, noWait bool) errorname:交换器名称。ifUnused:设置是否在交换器没有被应用的状况下删除。如果设置为true,则只有在此交换器没有被应用的状况下才会被删除;如果设置为false,则无论如何这个交换器都要被删除。noWait:是否非阻塞期待服务器返回,倡议设置为false。申明队列func (ch *Channel) QueueDeclare(name string, durable, autoDelete, exclusive, noWait bool, args Table) (Queue, error)name:队列的名称。durable:设置是否长久化。长久化的队列会存盘,在服务器重启的时候能够保障不失落队列及音讯(不失落是绝对的,如果宕机时有音讯没来得及存盘,还是会失落)。autoDelete:设置是否主动删除。主动删除的前提是至多有一个消费者连贯到这个队列,之后所有与这个队列连贯的消费者都断开时,才会主动删除。不能把这个参数谬误地了解为“当连贯到此队列的所有客户端断开时,这个队列会主动删除”,因为生产者客户端创立这个队列,或者没有消费者客户端与这个队列连贯时,都不会主动删除这个队列。exclusive:设置是否排他。如果一个队列被申明为排他队列,该队列仅对首次申明它的连贯可见,并在连贯断开时主动删除。有几点须要留神:排他队列是基于连贯可见的,同一个连贯的不同信道是能够同时拜访同一连贯创立的排他队列;如果一个连贯曾经申明了一个排他队列,其余连贯不容许建设同名的排他队列;即便该队列是长久化的,一旦连贯敞开或者客户端退出,该排他队列都会被主动删除。这种队列实用于一个客户端同时发送和读取音讯的利用场景。noWait:是否非阻塞期待服务器返回,倡议设置为false。args:设置队列的其余一些参数,如x-message-ttl、x-expires等。生产者和消费者都可能应用queueDeclare来申明一个队列,然而如果消费者在同一个信道上订阅了另一个队列,就无奈再申明队列了。必须先勾销订阅,而后将信道置为“传输”模式,之后能力申明队列。 同样这里还有一个参数齐全一样的queueDeclarePassive办法,这个办法用来检测相应的队列是否存在。如果存在则失常返回,如果不存在则抛出异样,同时Channel也会被敞开。 删除队列func (ch *Channel) QueueDelete(name string, ifUnused, ifEmpty, noWait bool) (int, error)name:队列名称。ifUnused:设置是否在队列没有被应用的状况下删除。ifEmpty:设置是否在队列为空(没有任何音讯沉积)的状况下才可能删除。noWait:是否非阻塞期待服务器返回,倡议设置为false。清空队列func (ch *Channel) QueuePurge(name string, noWait bool) (int, error)name:队列名称。noWait:是否非阻塞期待服务器返回,倡议设置为false。队列绑定func (ch *Channel) QueueBind(name, key, exchange string, noWait bool, args Table) errorname:队列名称。key:用来绑定队列和交换器的键。exchange:交换器名称。noWait:是否非阻塞期待服务器返回,倡议设置为false。args:定义绑定的一些参数。队列解绑func (ch *Channel) QueueUnbind(name, key, exchange string, args Table) errorname:队列名称。key:用来绑定队列和交换器的键。exchange:交换器名称。args:定义解绑的一些参数。交换器绑定func (ch *Channel) ExchangeBind(destination, key, source string, noWait bool, args Table) errordestination:目标交换器,通常是外部交换器。key:用来绑定源交换器和目标交换器的键。source:源交换器。nowait:是否非阻塞期待服务器返回,倡议设置为false。args:定义绑定的一些参数。生产者发送音讯至源交换器中,源交换器依据路由键找到与其匹配的目标交换器,并将音讯转发到给目标交换器,进而存储在目标交换器绑定的队列中。 ...

July 10, 2021 · 2 min · jiezi

关于rabbitmq:RabbitMQ基础概述

简介音讯队列中间件(Message Queue Middleware,简称为MQ)是指利用高效牢靠的消息传递机制进行与平台无关的数据交换,并基于数据通信来进行分布式系统的集成。通过提供消息传递和音讯排队模型,它能够在分布式环境下扩大过程间的通信。 目前开源的消息中间件有很多,比拟支流的有RabbitMQ、Kafka、ActiveMQ、RocketMQ等。面向音讯的中间件提供了以涣散耦合的灵便形式集成应用程序的一种机制。 消息中间件实用于须要牢靠的数据传送的分布式环境。采纳消息中间件的零碎中不同的对象之间通过传递音讯来激活对方的事件,以实现相应的操作。消息中间件常被用来屏蔽各种平台及协定之间的个性,实现应用程序之间的协同,其长处在于可能在客户和服务器之间提供同步和异步的连贯,并且在任何时刻都能够将音讯进行传送或者存储转发。 消息中间件的用处能够概括如下: 解耦冗余削峰可恢复性程序保障缓冲异步通信RabbitMQ是采纳Erlang语言实现AMQP (Advanced Message Queuing Protocol,高级音讯队列协定)的消息中间件,在易用性、扩展性、可靠性和高可用性等方面有着卓越体现。 装置手动装置RabbitMQ较为繁琐,这里提供一种简略的基于Docker的装置形式: docker run -d --name rabbitmq --hostname my-rabbitmq -p 5672:5672 -p 15672:15672 -e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=admin [拉取的RabbitMQ镜像id]外围概念RabbitMQ整体上是一个生产者与消费者模型,次要负责接管、存储和转发音讯。从计算机术语层面来说,RabbitMQ模型更像是一种交换机模型。RabbitMQ的整体模型架构如下图所示: Producer:生产者生产者创立音讯,而后公布到RabbitMQ中。音讯个别能够蕴含2个局部:音讯体和标签。在理论利用中,音讯体个别是一个带有业务逻辑构造的数据,比方一个JSON 字符串。音讯的标签用来表述这条音讯,比方一个交换器的名称和一个路由键。生产者把音讯交由RabbitMQ,RabbitMQ之后会依据标签把音讯发送给感兴趣的消费者(Consumer)。 Consumer:消费者消费者连贯到RabbitMQ服务器,并订阅到队列上。在音讯路由的过程中,音讯的标签会抛弃,存入到队列中的音讯只有音讯体,消费者也只会生产到音讯体。 Broker:服务节点对于RabbitMQ来说,一个RabbitMQ Broker能够简略地看作一个RabbitMQ服务节点,或者RabbitMQ服务实例。大多数状况下也能够将一个RabbitMQ Broker看作一台RabbitMQ服务器。 Queue:队列RabbitMQ的生产者生产音讯并最终投递到队列中,消费者能够从队列中获取音讯并生产。多个消费者能够订阅同一个队列,这时队列中的音讯默认会被均匀摊派(Round-Robin,即轮询)给多个消费者进行解决,而不是每个消费者都收到所有的音讯并解决,RabbitMQ不反对队列层面的播送生产。 Exchange:交换器生产者并不会间接将音讯发送到队列,而是将音讯发送到交换器,由交换器将音讯路由到一个或者多个队列中。如果路由不到,会依据配置返回给生产者或者间接抛弃。交换器有四种类型,不同的类型有不同的路由策略。 BindingKey:绑定键RabbitMQ中通过绑定将交换器与队列关联起来,在绑定的时候个别会指定一个绑定键,这样RabbitMQ就晓得如何正确地将音讯路由到队列了。 RoutingKey:路由键生产者将音讯发给交换器的时候,个别会指定一个RoutingKey,用来指定这个音讯的路由规定,而这个RoutingKey须要与交换器类型和绑定键联结应用能力最终失效。交换器会依据本身的类型对路由键和绑定键进行匹配,匹配胜利则将音讯转发到对应的队列中。 Connection:连贯无论是生产者还是消费者,都须要和RabbitMQ Broker建设TCP连贯,这个连贯就是Connection。 Channel:信道一旦TCP连贯建设起来,客户端就能够创立一个AMQP信道,每个信道都会被指派一个惟一的ID。信道是建设在Connection之上的虚构连贯,RabbitMQ解决的每条AMQP指令都是通过信道实现的。 注:在多线程利用场景下,每个线程对应一条信道,复用同一条连贯,这样能够进步性能,同时也便于管理。 交换器类型RabbitMQ罕用的交换器类型有fanout、direct、topic、headers这四种。 fanoutfanout类型交换器会把所有发送到该交换器的音讯路由到所有与该交换器绑定的队列中,会屏蔽掉路由键、绑定键的作用。 directdirect类型交换器会把音讯路由到那些BindingKey和RoutingKey齐全匹配的队列中。 topictopic类型的交换器在匹配规定上进行了扩大,它与direct类型的交换器类似,也是将音讯路由到 BindingKey和RoutingKey相匹配的队列中,但这里的匹配规定有些不同,它有上面这些约定: RoutingKey为一个点号“.”分隔的字符串,如“com.rabbitmq.client” 。BindingKey和RoutingKey一样也是点号“.”分隔的字符串。BindingKey中能够存在两种非凡字符串“*”和“#”,用于做含糊匹配,其中“#”用于匹配一个单词,“#”用于匹配一个或多个单词(能够是零个)。 headersheaders类型的交换器不依赖于路由键的匹配规定来路由音讯,而是依据发送的音讯内容中的headers属性进行匹配。在绑定队列和交换器时制订一组键值对,当发送音讯到交换器时,RabbitMQ会获取到该音讯的headers,比照其中的键值对是否齐全匹配队列和交换器绑定时指定的键值对,如果齐全匹配则音讯会路由到该队列,否则不会路由到该队列。headers类型的交换器性能很差,而且也不实用,基本上不会看到它的存在。 运行流程当初总结一下RabbitMQ的整个应用流程。首先是生产者: 生产者连贯到RabbitMQ Broker,建设一个连贯,开启一个信道。生产者申明一个交换器,并设置相干属性,比方交换机类型、是否长久化等。生产者申明一个队列并设置相干属性,比方是否排他、是否长久化、是否主动删除等。生产者通过路由键将交换器和队列绑定起来。生产者发送音讯至RabbitMQ Broker,其中蕴含路由键、交换器等信息。相应的交换器依据接管到的路由键查找相匹配的队列。如果找到,则将从生产者发送过去的音讯存入相应的队列中。如果没有找到,则依据生产者配置的属性抉择抛弃还是回退给生产者。敞开信道。敞开连贯。对于消费者: 消费者连贯到RabbitMQ Broker,建设一个连贯,开启一个信道。消费者向RabbitMQ Broker申请生产相应队列中的音讯(推模式),可能会设置相应的回调函数,以及做一些筹备工作。期待RabbitMQ Broker回应并投递相应队列中的音讯,消费者接管音讯。消费者确认(ack)接管到的音讯。RabbitMQ从队列中删除相应曾经被确认的音讯。敞开信道。敞开连贯。

July 8, 2021 · 1 min · jiezi

关于rabbitmq:『假如我是面试官』RabbitMQ我会这样问

1. 为什么你们公司抉择RabbitMQ作为消息中间件在音讯队列选型时,咱们调研了市场上比拟罕用ActiveMQ,RabbitMQ,RocketMQ,Kafka。 RabbitMQ绝对成熟稳固,这是咱们抉择它最次要的起因。社区比拟沉闷,有欠缺的材料能够参考。Rabbitmq的吞吐量能够达到万级,齐全满足咱们零碎的要求。RabbitMQ是Erlang语言开发的,性能比拟好。有欠缺的可视化界面,不便查看。2. 音讯队列的长处和毛病有哪些长处有: 异步解决 - 相比于传统的串行、并行形式,进步了零碎吞吐量。利用解耦 - 零碎间通过音讯通信,不必关怀其余零碎的解决。流量削锋 - 能够通过音讯队列长度管制申请量;能够缓解短时间内的高并发申请。毛病有: 零碎可用性升高零碎复杂度进步3. RabbitMQ罕用的工作模式有哪些2.1 简略模型 p:生成者C:消费者红色局部:quene,音讯队列2.2 工作模型 这种模式下一条音讯只能由一个消费者进行生产,默认状况下,每个消费者是轮询生产的。 p:生成者C1、C2:消费者红色局部:quene,音讯队列2.3 公布订阅模型(fanout) 这种模型中生产者发送的音讯所有消费者都能够生产。 p:生成者X:交换机C1、C2:消费者红色局部:quene,音讯队列2.4 路由模型(routing) 这种模型消费者发送的音讯,不同类型的音讯能够由不同的消费者去生产。 p:生成者X:交换机,接管到生产者的音讯后将音讯投递给与routing key齐全匹配的队列C1、C2:消费者红色局部:quene,音讯队列2.5 主题模型(topic) 这种模型和direct模型一样,都是能够依据routing key将音讯路由到不同的队列,只不过这种模型能够让队列绑定routing key 的时候应用通配符。这种类型的routing key都是由一个或多个单词组成,多个单词之间用.宰割。 通配符介绍: *:只匹配一个单词 #:匹配一个或多个单词 4. 如何保障音讯不失落(如何保障音讯的可靠性)一条音讯从生产到生产经验了三个阶段,别离是生产者,MQ和消费者,对于RabbitMQ来说,音讯的传递还波及到交换机。因而RabbitMQ呈现音讯失落的状况有四个 别离是 音讯生产者没有胜利将音讯发送到MQ导致音讯失落交换机未路由到音讯队列导致音讯失落音讯在MQ中时,MQ产生宕机导致音讯失落消费者生产音讯时出现异常导致音讯失落针对下面提到的四种状况,别离进行解决 amqp协定提供了事务机制,在投递音讯时开启事务,如果音讯投递失败,则回滚事务,很少有人去应用事务。除了事务之外,RabbitMQ还提供了生产者确认机制(publisher confirm)。生产者将信道设置成confirm(确认)模式,一旦信道进入confirm模式,所有在该信道下面公布的音讯都会被指派一个惟一的ID(从1开始),一旦音讯被投递到所有匹配的队列之后,RabbitMQ就会发送一个确认(Basic.Ack)给生产者(蕴含音讯的惟一ID),这就使得生产者通晓音讯曾经正确达到了目的地了。# 开启生产者确认机制,# 留神这里确认的是是否达到交换机spring.rabbitmq.publisher-confirm-type=correlated@RestControllerpublic class Producer { @Autowired private RabbitTemplate rabbitTemplate; @GetMapping("send") public void sendMessage(){ /** * 生产者确认音讯 */ rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() { @Override public void confirm(CorrelationData correlationData, boolean ack, String cause) { System.out.println(correlationData); System.out.println(ack); System.out.println(cause); } }); rabbitTemplate.convertAndSend("s","error","这是一条谬误日志!!!"); }}音讯从交换机未能匹配到队列时将此条音讯返回给生产者spring.rabbitmq.publisher-returns=true@RestControllerpublic class Producer { @Autowired private RabbitTemplate rabbitTemplate; @GetMapping("send") public void sendMessage(){ /** * 音讯未达队列时返回该条音讯 */ rabbitTemplate.setReturnsCallback(new RabbitTemplate.ReturnsCallback() { @Override public void returnedMessage(ReturnedMessage returnedMessage) { System.out.println(returnedMessage); } }); rabbitTemplate.convertAndSend("s","error","这是一条谬误日志!!!"); }}音讯在交换机或队列中产生失落,咱们只须要将交换机和队列进行长久化。/** * 定义一个长久化的topic交换机 * durable 长久化 * @return */@Beanpublic Exchange exchangeJavatrip(){ return ExchangeBuilder.topicExchange(EXCHANGE).durable(true).build();}/** * 定义一个长久化的队列 * durable 长久化 * @return */@Beanpublic Queue queueJavatrip(){ return QueueBuilder.durable(QUEUE).build();}消费者开启手动签收模式,生产实现后进行ack确认。spring.rabbitmq.listener.simple.acknowledge-mode=manual@RabbitListener(queues = MqConfig.QUEUE)public void receive(String body, Message message, Channel channel) throws Exception{ long deliveryTag = message.getMessageProperties().getDeliveryTag(); System.out.println(deliveryTag); // 零碎业务逻辑判断是否签收 if(deliveryTag % 2 == 0){ channel.basicAck(deliveryTag,false); }else{ // 第二个参数是否批量确认,第三个参数是否从新回队列 channel.basicNack(deliveryTag,false,true); }}5. 如何保障音讯不反复生产(如何保障音讯的幂等性)音讯反复的起因有两个: ...

June 22, 2021 · 2 min · jiezi

关于rabbitmq:RabbitMQ由浅入深入门全总结二

写在最后面间隔上一次发文章曾经很久了,其实这段时间始终也没有停笔,只不过在忙着找工作还有学校结课的事件,从新弄了一下博客,前面也会陆陆续续会把文章最近更新进去~ 这篇文章有点长,就分了两篇PS:那个Github上Java常识问答的文章也没有停笔,最近也会陆续更新6. 进阶补充6.1 过期工夫设置(TTL)过期工夫(TTL)就是对音讯或者队列设置一个时效,只有在工夫范畴内才能够被被消费者接管获取,超过过期工夫后音讯将主动被删除。 注:咱们次要讲音讯过期,在音讯过期的第一种形式中,顺便也就会提到队列过期的设置形式 通过队列属性设置,队列中所有音讯都有雷同的过期工夫对音讯进行独自设置,每条音讯 TTL能够不同两种办法同时被应用时,以两者过期工夫 TTL 较小的那个数值为准。音讯在队列的生存工夫一旦超过设置的 TTL 值,就称为 Dead Message 被投递到死信队列,消费者将无奈再收到该音讯(死信队列是咱们下一点要讲的) 6.1.1 利用于全副音讯的过期工夫配置类@Configurationpublic class RabbitMqConfiguration { public static final String TOPIC_EXCHANGE = "topic_order_exchange"; public static final String TOPIC_QUEUE_NAME_1 = "test_topic_queue_1"; public static final String TOPIC_ROUTINGKEY_1 = "test.*"; @Bean public TopicExchange topicExchange() { return new TopicExchange(TOPIC_EXCHANGE); } @Bean public Queue topicQueue1() { // 创立参数 Map 容器 Map<String, Object> args = new HashMap<>(); // 设置音讯过期工夫 留神此处是数值 5000 不是字符串 args.put("x-message-ttl", 5000); // 设置队列过期工夫 args.put("x-expires", 8000); // 在最初传入额定参数 即这些过期信息 return new Queue(TOPIC_QUEUE_NAME_1, true, false, false, args); } @Bean public Binding bindingTopic1() { return BindingBuilder.bind(topicQueue1()) .to(topicExchange()) .with(TOPIC_ROUTINGKEY_1); }}创立参数 Map 容器:类型是在 Queue 参数中所要求的,要依照要求来。设置音讯过期工夫:这里设置的音讯过期工夫,会利用到所有音讯中。设置队列过期工夫传入额定参数:将上述配置好的过期工夫设置,通过 Queue 传入即可。生产者@SpringBootTest(classes = RabbitmqSpringbootApplication.class)@RunWith(SpringRunner.class)public class RabbitMqTest { /** * 注入 RabbitTemplate */ @Autowired @Test public void testTopicSendMessage() { rabbitTemplate.convertAndSend(RabbitMqConfiguration.TOPIC_EXCHANGE, "test.order.insert", "This is a message !"); }}不要配置消费者,而后就能够在 Web 管理器中看到成果了 ...

June 17, 2021 · 4 min · jiezi

关于rabbitmq:二rabbitMQ进一步介绍

一、Rabbit作用 程序解耦,如一时间须要反复写入大量的数据时当RabbitMQ的负载减少时,因为它的音讯是循环给消费者解决的有肯定的负载平衡的作用二、发后即忘模型 音讯通信畛域次要实用的模型之一发后即忘模型是。咱们只需关怀这些工作将会实现,而不需关怀是否实时实现。1、发送正告2、批处理: 上传图片会有多个业务,如记录日志,减少积分等能够通过famous 交换器:会将音讯匹配到所有附加在此交换器上的队列 来播送你胜利上传的工作从而触发前面的工作。三、集群 RabbitMq会始终记录以下四种类型的外部元数据 队列元数据:队列名称和它们的属性(是否可长久化,是否主动删除?)交换器元数据:交换器名称、类型和属性(可长久化)绑定元数据 :一张简略的表格展现了如何将音讯路由到队列vhost元数据:为vhost内的队列、交换器和绑定提供明湖曾空间和平安属性1、集群中的队列 集群中单节点Rabbit的队列保留有本人的队列信息和队列绑定关系,而其余节点只有该队列的元数据(即队例的名称和属性),不会保留队列的内容和绑定关系。起因同步复制开销太大^_^。 留神:问题一、当Rabbit重启其队列的绑定关系也会销毁,音讯被销毁 解决形式:在开始时设置队列长久化。2、集群中的交换器 交换器只是逻辑上存在的,起到路由的用相当于一张记录了队列信息的查问表,取得信道的音讯后再这张表中通过不同形式进行匹配绑定。留神:问题一、在路由绑定之前产生了音讯失落怎么办勒? 解决:1、应用AMQP事务。 2、返回确认音讯,来记录连贯中断时尚未被确认的信息。 这两种办法来确认音讯无奈路由的到指标队列的状况。当在集群中齐全复制联合,保障路由胜利性从而不会失落一条信息。3、是内存节点还是磁盘节点 每个RabbitMQ节点,不论是繁多节点零碎或者是集群,要么是内存节点,要么是磁盘节点。内存节点将所有的队列、交换器、绑定、用户、权限和vhost元数据都仅存储在内存中磁盘节店则将元数据存储在磁盘中单节点零碎只容许磁盘类型的节点,否则每次你重启所有的配置信息都会失落。在集群中也能够抉择配置局部节点为内存节点,使得音讯流动的性能更好阐明:集群中要设置内存节点的起因,在集群中申明交换器、队列或绑定的时候所有集群节点都要同步其元数据。对于磁盘来说就是大量的磁盘操作,对于内存来就是变更写入内存。通常来说集群中至多有一个节点是写入磁盘的形式其余节点宕机导致元数据不能复原。

June 16, 2021 · 1 min · jiezi

关于rabbitmq:一Rabbitmq基础介绍

一、介绍AMQP协定 个性:1:分布式事务反对。2:音讯的长久化反对。3:高性能和高牢靠的音讯解决劣势。 散发策略:1: 轮询散发2: 偏心散发 AMQP音讯路由必须的三局部:交换器、路由、绑定 消费者从队列中接管音讯: 通过AMQP的basic.consume 命令将信道置为接管模式,直到勾销队列订阅为止。可能继续接管音讯通过AMQP的basic.get命令实现向队列获取一条音讯留神: RabbitMq基于AMQP协定对个消费者共用同一队列 ,音讯的生产流程循环生产,cosumerA,cosumerB。 1、 messageA 达到队列先 给conusumerA ,在consumerA中确认了接管了messageA音讯,RabbiMQ将messageA从队列中删除 2、message发送给consumerB ranhou....问题一:consumerA没有确认音讯会怎么样? messageA会发送给下一个消费者,从而保障音讯被生产,如果consumerA没有确认音讯,队列将不会发送音讯给消费者A,能够利用这点来管制生产时长。问题二:应用什么形式回绝解决该条音讯? 1、把消费者从rabbiMq断开(会减少对RabbitMQ的负荷) 2、RabbitMq2.0.0及以上版本能够应用AMQP的basic.reject命令。把reject命令的requeue 值设为true则将音讯发送到下一个message,false则是移除该音讯。名词介绍: 生产者有效载荷(理论传输数据),标签(形容数据,指定谁能够复制音讯)队列消费者信道:当TCp连贯建设会创立AMQP信道,AMQP的命令通过信道发送,每条信道被指定惟一id。二、交换器和绑定 交换器通过路由键来散发音讯到不同队列:一共有4中类型交换器 direct、famous、topic、headers(headers交换器容许你匹配Amqp音讯的header而非路由键)direct交换器:如果路由键匹配的话,音讯就被投递到对应的队列服务器必须实现direct类型交换器,蕴含一个空白字符串的默认交换器。队列的名称就是路由键famous 交换器:会将音讯匹配到所有附加在此交换器上的队列3.topic交换器:通过通配符匹配音讯,使得不同源头的音讯达到同一队列 三、虚拟主机 每一个vhost实质上是一个mini版的RabbitMq服务器,领有本人的队列、交换器和绑定。挡在Rabbitmq集群中创立了一个mq则整个集群中都会创立这个vhost。4、音讯长久化和策略 长久化的形式: 1、把它 的投递模式(delicery mode)选项设置为2 2、发不到长久化的交换器 3、达到长久化的队列。(服务器会将持久性的音讯写入到持久性日志中)5、应用Rabbitmq的大抵流程 连贯Rabbitmq获取信道申明交换器申明队列队列和交换器绑定生产音讯敞开信道敞开连贯RabbitMq是运行在Erlang上的1、启动结点 ./sbin/rabbitmq -server2、敞开结点 ./sbin/rabbitmqctl stop 只敞开rabbitmq ./rabbitmqctl stop_app3、Rabbitmq日志:LOG_BASE = /var/log/rabbitmq会创立两个日志文件RABBITMQ_NODENAME-sasl.log 和RABBITMQ_NODENAME.log 文章参考书籍:《Rabbimq实战 高效部署分布式音讯队列》

June 16, 2021 · 1 min · jiezi

关于rabbitmq:消息队列高可用高并发

文章参考:https://www.kuangstudy.com/zl/rabbitmq#1368199642499571713一、简介 当业务量减少时,申请也过大,一台消息中间件服务器的会涉及硬件(CPU,内存,磁盘)的极限,一台音讯服务器你曾经无奈满足业务的需要,所以消息中间件必须反对集群部署。来达到高可用的目标。二、高可用集群模式介绍 集群模式1 - Master-slave主从共享数据的部署形式 生产者讲生产发送到Master节点,所有的都连贯这个音讯队列共享这块数据区域,Master节点负责写入,一旦Master挂掉,slave节点持续服务。从而造成高可用,集群模式2 - Master- slave主从同步部署形式 这种模式写入音讯同样在Master主节点上,然而主节点会同步数据到slave节点造成正本,这样能够达到负载平衡的成果,如果消费者有多个这样就能够去不同的节点就行生产,音讯的拷贝和同步会占用很大的带宽和网络资源。在后续的rabbtmq中会有应用。集群模式3 - 多主集群同步部署模式 和下面的区别不是特地的大,然而它的写入能够往任意节点去写入。集群模式4 - 多主集群转发部署模式如果你插入的数据是broker-1中,元数据信息会存储数据的相干形容和记录寄存的地位(队列)。它会对形容信息也就是元数据信息就行同步,如果消费者在broker-2中进行生产,发现自己几点没有对应的音讯,能够从对应的元数据信息中去查问,而后返回对应的音讯信息,场景:比方买火车票或者黄牛买演唱会门票,比方第一个黄牛有顾客说要买的演唱会门票,然而没有然而他会去分割其余的黄牛询问,如果有就返回。集群模式5 Master-slave与Breoker-cluster组合的计划解释:实现多主多从的热备机制来实现音讯的高可用以及数据的热备机制,在生产规模达到肯定的阶段的时候,这种应用的频率比拟高。反正终归三句话:1:要么音讯共享,2:要么音讯同步3:要么元数据共享 如何保障中间件音讯的可靠性呢?能够从两个方面思考:1:音讯的传输:通过协定来保证系统间数据解析的正确性。2:音讯的存储牢靠:通过长久化来保障音讯的可靠性。

June 16, 2021 · 1 min · jiezi

关于rabbitmq:RabbitMQ由浅入深入门全总结一

写在最后面间隔上一次发文章曾经很久了,其实这段时间始终也没有停笔,只不过在忙着找工作还有学校结课的事件,从新弄了一下博客,前面也会陆陆续续会把文章最近更新进去~ 这篇文章有点长,就分了两篇PS:那个Github上Java常识问答的文章也没有停笔,最近也会陆续更新1. 浅浅道来1.1 什么是中间件?IDC(互联网数据中心)的定义:中间件是一种独立的系统软件服务程序,分布式应用软件借助这种软件在不同的技术之间共享资源,中间件位于客户机服务器的操作系统之上,治理计算资源和网络通信。首先,中间件是某一类软件的总称,而不是某一种具体的软件。它是一种位于平台(操作系统硬件) 和 应用程序之间的通用服务,它屏蔽了底层操作系统的各种复杂性,加重了开发人员的技术累赘,同时它的设计不针对某一具体指标,而是提供具备广泛通用特点的功能模块服务,这些服务具备规范的程序接口和协定,依据平台的不同,也能够有不同的实现。 艰深的例子(仅供参考,并不算完全一致): 我开了一家咖啡店,我身边有 A B C 等 n 家咖啡豆的供应商,然而我必定要筛选价格又实惠,品质还不错的豆子,然而市场是受到多方面因素稳定的,可能我当初的抉择,在一段时间后曾经不是最佳选项了。所以我专门找到一家市场中介,让他帮我操心这一摊子事件,我只和你说清价格和品质要求,你去找就是了,过程我一点也不操心。这个中介的概念,就相似中间件的 1.1.1 分布式的概念(补充)这一段,来自我之前写的 Dubbo 入门的那篇文章哈 在百度以及维基中的定义都绝对业余且艰涩,大部分博客或者教程常常会应用《分布式系统原理和范型》中的定义,即:“分布式系统是若干独立计算机的汇合,这些计算机对于用户来说就像是单个相干零碎” 上面咱们用一些篇幅来艰深的解释一下什么叫做分布式 1.1.1.1 什么是集中式零碎提到分布式,不得不提的就是 “集中式零碎”,这个概念最好了解了,它就是将性能,程序等装置在同一台设施上,就由这一台主机设施向外提供服务 举个最简略的例子:你拿一台PC主机,将其改装成了一台简略的服务器,配置好各种内容后,你将MySQL,Web服务器,FTP,Nginx 等等,全副装置在其中,打包部署我的项目后,就能够对外提供服务了,然而一旦这台机器无论是软件还是硬件呈现了问题,整个零碎都会受到重大的株连谬误,鸡蛋放在一个篮子里,要打就全打了 1.1.12 什么是分布式系统既然集中式零碎有这样一种牵一发而动全身的问题,那么分布式的其中一个作用,天然是来解决这样的问题了,正如定义中所知,分布式系统在用户的体验感官里,就像传统的单零碎一样,一些变动都是这个零碎自身外部进行的,对于用户并没有什么太大的感觉 例如:淘宝,京东这种大型电商平台,它们的主机都是数以万计的,否则基本没法解决大量的数据和申请,具体其中有什么划分,以及操作,咱们上面会说到,然而对于用户的咱们,咱们不须要也不想关怀这些,咱们仍能够单纯的认为,咱们面对的就是 “淘宝” 这一台 “主机” 所以分布式的一个绝对业余一些的说法是这样的(过程粒度)两个或者多个程序,别离运行在不同的主机过程上,它们互相配合协调,实现独特的性能,那么这几个程序之间形成的零碎就能够叫做分布式系统 这几者都是雷同的程序 —— 分布式这几者都是不同的程序 —— 集群 1.2 什么是消息中间件/音讯队列(MQ)消息中间件,顾名思义就是用来解决音讯相干服务的中间件,它提供了一种零碎之间通信交互的通道,例如发送方只须要把想传输的信息交给消息中间件,而发送的协定,形式,发送过程中呈现的网络,故障等等问题,都由中间件进行解决,因而它负责保障信息的牢靠传输。 所以消息中间件,就是一种用来承受数据,存储数据,发送数据的技术,它提供了各种性能,能够实现音讯的高可用,高牢靠,也提供了很好的容错机制等。能够程序对系统资源的占用,以及传输效率的晋升有很大帮忙。 常说的 MQ 就是指音讯队列,即 Message Quene,常见的音讯队列有,经典的 ActivieMQ,热门的 Kafka,阿里的 RocketMQ 等等,以及这里解说的 RabbitMQ。 不同的 MQ 有着不同的特点,以及其更加善于的方向,倒也说不上谁好谁坏,只有谁更适合。1.2.1 音讯队列利用场景依据业务的须要,其实它能够有多种利用场景,例如解耦,削峰填谷,播送等,咱们举两个场景来梳理一下简略的过程 1.2.1.1 业务解耦最近在思考买几本书看,就以买书下订单举例,当我点击购买之后,可能会有这么一串业务逻辑执行,① 减去库存容量 ② 生成订单 ③ 领取 ④ 更新订单状态 ⑤ 发送购买胜利短信 ⑥ 更新商品快递揽收状态。在初期阶段,咱们齐全能够让这些业务同步执行,然而前期为了晋升效率,就能够将须要立刻执行的工作和可稍缓执行的工作进行拆散,例如 ⑤ 发送购买胜利短信 ⑥ 更新商品快递揽收状态,都能够思考异执行。在主流程执行完结后,这些可稍缓的业务能够通过给 MQ 发送音讯,就断定曾经执行,保障流程先完结。而后再通过拉取 MQ 音讯,或者 MQ 被动推送去异步执行其余的业务。 ...

June 15, 2021 · 16 min · jiezi

关于rabbitmq:RabbitMQ-实现远程过程调用-RPC

装置依赖# composer.json{ "require": { "php-amqplib/php-amqplib": ">=3.0" }}> composer.phar install模式构造 RPC 工作流程: 当客户端启动时,会创立一个匿名独占回调队列。对于 RPC 申请,客户端发送具备两个属性的音讯: reply_to,设置为回调队列;correlation_id,为每个申请设置惟一值。申请被发送到 rpc_queue 队列。服务器期待该队列上的申请。当申请呈现时,执行工作并将带有后果的音讯通过reply_to指定的队列发送回客户端。客户端期待回调队列上的音讯。当呈现一条音讯时,查看correlation_id属性。如果它与申请中的值匹配,则将响应返回给应用程序。客户端<?phprequire_once __DIR__ . '/vendor/autoload.php';use PhpAmqpLib\Connection\AMQPStreamConnection;use PhpAmqpLib\Message\AMQPMessage;class FibonacciRpcClient{ private $connection; private $channel; private $callback_queue; private $response; private $corr_id; public function __construct() { // 创立连贯 $this->connection = new AMQPStreamConnection( 'localhost', 5672, 'guest', 'guest' ); // 创立通道 $this->channel = $this->connection->channel(); // 创立队列,已存在的不会反复创立,第三个参数为敞开队列长久化 list($this->callback_queue, ,) = $this->channel->queue_declare( "", false, false, true, false ); // 第四个参数设为false敞开主动音讯确认,为true关上主动音讯确认即投递音讯后立即标记为删除 $this->channel->basic_consume( $this->callback_queue, '', false, true, false, false, array( $this, 'onResponse' ) ); } public function onResponse($rep) { if ($rep->get('correlation_id') == $this->corr_id) { $this->response = $rep->body; } } public function call($n) { $this->response = null; $this->corr_id = uniqid(); $msg = new AMQPMessage( (string) $n, array( 'correlation_id' => $this->corr_id, 'reply_to' => $this->callback_queue ) ); // 通过默认的交换机发送音讯到队列 (音讯内容, 默认交换机, 路由键); $this->channel->basic_publish($msg, '', 'rpc_queue'); while (!$this->response) { $this->channel->wait(); } return intval($this->response); }}$fibonacci_rpc = new FibonacciRpcClient();// 发送 RPC 申请并阻塞直到收到响应$response = $fibonacci_rpc->call(30);echo ' [.] Got ', $response, "\n";服务端<?phprequire_once __DIR__ . '/vendor/autoload.php';use PhpAmqpLib\Connection\AMQPStreamConnection;use PhpAmqpLib\Message\AMQPMessage;// 创立连贯$connection = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest');// 创立通道$channel = $connection->channel();// 创立队列,已存在的不会反复创立,第三个参数为敞开队列长久化$channel->queue_declare('rpc_queue', false, false, false, false);// 申明斐波那契生成函数function fib($n){ if ($n == 0) { return 0; } if ($n == 1) { return 1; } return fib($n-1) + fib($n-2);}echo " [x] Awaiting RPC requests\n";// 定义回调函数$callback = function ($req) { $n = intval($req->body); echo ' [.] fib(', $n, ")\n"; $msg = new AMQPMessage( (string) fib($n), array('correlation_id' => $req->get('correlation_id')) ); $req->delivery_info['channel']->basic_publish( $msg, '', $req->get('reply_to') ); // 手动音讯确认 $req->ack();};// 设置 prefetch_count = 1,开启偏心散发(默认为循环散发)// 在解决并确认上一条音讯之前,不要将新音讯发送给消费者,而发送给其余消费者$channel->basic_qos(null, 1, null);// 第四个参数设为false敞开主动音讯确认,为true关上主动音讯确认即投递音讯后立即标记为删除$channel->basic_consume('rpc_queue', '', false, false, false, false, $callback);while ($channel->is_open()) { $channel->wait();}$channel->close();$connection->close();运行关上一个终端,运行服务端: ...

June 6, 2021 · 2 min · jiezi

关于rabbitmq:RabbitMQ-七种队列模式应用场景案例分析通俗易懂

七种模式介绍与利用场景简略模式(Hello World) 做最简略的事件,一个生产者对应一个消费者,RabbitMQ相当于一个音讯代理,负责将A的音讯转发给B 利用场景:将发送的电子邮件放到音讯队列,而后邮件服务在队列中获取邮件并发送给收件人 工作队列模式(Work queues) 在多个消费者之间分配任务(竞争的消费者模式),一个生产者对应多个消费者,个别实用于执行资源密集型工作,单个消费者解决不过去,须要多个消费者进行解决 利用场景:一个订单的解决须要10s,有多个订单能够同时放到音讯队列,而后让多个消费者同时解决,这样就是并行了,而不是单个消费者的串行状况 订阅模式(Publish/Subscribe) 一次向许多消费者发送音讯,一个生产者发送的音讯会被多个消费者获取,也就是将音讯将播送到所有的消费者中。 利用场景:更新商品库存后须要告诉多个缓存和多个数据库,这里的构造应该是: 一个fanout类型交换机扇出两个个音讯队列,别离为缓存音讯队列、数据库音讯队列一个缓存音讯队列对应着多个缓存消费者一个数据库音讯队列对应着多个数据库消费者路由模式(Routing) 有选择地(Routing key)接管音讯,发送音讯到交换机并且要指定路由key ,消费者将队列绑定到交换机时须要指定路由key,仅生产指定路由key的音讯 利用场景:如在商品库存中减少了1台iphone12,iphone12促销流动消费者指定routing key为iphone12,只有此促销流动会接管到音讯,其它促销流动不关怀也不会生产此routing key的音讯 主题模式(Topics) 依据主题(Topics)来接管音讯,将路由key和某模式进行匹配,此时队列须要绑定在一个模式上,#匹配一个词或多个词,*只匹配一个词。 利用场景: 同上,iphone促销流动能够接管主题为iphone的音讯,如iphone12、iphone13等 近程过程调用(RPC) 如果咱们须要在近程计算机上运行性能并期待后果就能够应用RPC,具体流程能够看图。利用场景:须要期待接口返回数据,如订单领取 发布者确认(Publisher Confirms)与发布者进行牢靠的公布确认,发布者确认是RabbitMQ扩大,能够实现牢靠的公布。在通道上启用发布者确认后,RabbitMQ将异步确认发送者公布的音讯,这意味着它们已在服务器端解决。(搜寻公众号民工哥技术之路,查看更多 Java后端技术栈及面试题精选) 利用场景:对于音讯可靠性要求较高,比方钱包扣款 代码演示代码中没有对前面两种模式演示,有趣味能够本人钻研 简略模式import com.rabbitmq.client.Channel;import com.rabbitmq.client.Connection;import com.rabbitmq.client.ConnectionFactory;import java.io.IOException;import java.util.concurrent.TimeoutException;public class Sender { private final static String QUEUE_NAME = "simple_queue"; public static void main(String[] args) throws IOException, TimeoutException { ConnectionFactory factory = new ConnectionFactory(); factory.setHost("localhost"); factory.setPort(5672); Connection connection = factory.newConnection(); Channel channel = connection.createChannel(); // 申明队列 // queue:队列名 // durable:是否长久化 // exclusive:是否排外 即只容许该channel拜访该队列 个别等于true的话用于一个队列只能有一个消费者来生产的场景 // autoDelete:是否主动删除 生产完删除 // arguments:其余属性 channel.queueDeclare(QUEUE_NAME, false, false, false, null); //音讯内容 String message = "simplest mode message"; channel.basicPublish("", QUEUE_NAME, null, message.getBytes()); System.out.println("[x]Sent '" + message + "'"); //最初敞开通关和连贯 channel.close(); connection.close(); }}import com.rabbitmq.client.Channel;import com.rabbitmq.client.Connection;import com.rabbitmq.client.ConnectionFactory;import com.rabbitmq.client.DeliverCallback;import java.io.IOException;import java.util.concurrent.TimeoutException;public class Receiver { private final static String QUEUE_NAME = "simplest_queue"; public static void main(String[] args) throws IOException, InterruptedException, TimeoutException { // 获取连贯 ConnectionFactory factory = new ConnectionFactory(); factory.setHost("localhost"); factory.setPort(5672); Connection connection = factory.newConnection(); Channel channel = connection.createChannel(); channel.queueDeclare(QUEUE_NAME, false, false, false, null); DeliverCallback deliverCallback = (consumerTag, delivery) -> { String message = new String(delivery.getBody(), "UTF-8"); System.out.println(" [x] Received '" + delivery.getEnvelope().getRoutingKey() + "':'" + message + "'"); }; channel.basicConsume(QUEUE_NAME, true, deliverCallback, consumerTag -> { }); }}工作队列模式import com.rabbitmq.client.Channel;import com.rabbitmq.client.Connection;import com.rabbitmq.client.ConnectionFactory;import com.rabbitmq.client.DeliverCallback;import java.io.IOException;import java.util.concurrent.TimeoutException;public class Receiver1 { private final static String QUEUE_NAME = "queue_work"; public static void main(String[] args) throws IOException, InterruptedException, TimeoutException { ConnectionFactory factory = new ConnectionFactory(); factory.setHost("localhost"); factory.setPort(5672); Connection connection = factory.newConnection(); Channel channel = connection.createChannel(); channel.queueDeclare(QUEUE_NAME, false, false, false, null); // 同一时刻服务器只会发送一条音讯给消费者 channel.basicQos(1); DeliverCallback deliverCallback = (consumerTag, delivery) -> { String message = new String(delivery.getBody(), "UTF-8"); System.out.println(" [x] Received '" + delivery.getEnvelope().getRoutingKey() + "':'" + message + "'"); }; channel.basicConsume(QUEUE_NAME, true, deliverCallback, consumerTag -> { }); }}import com.rabbitmq.client.Channel;import com.rabbitmq.client.Connection;import com.rabbitmq.client.ConnectionFactory;import com.rabbitmq.client.DeliverCallback;import java.io.IOException;import java.util.concurrent.TimeoutException;public class Receiver2 { private final static String QUEUE_NAME = "queue_work"; public static void main(String[] args) throws IOException, InterruptedException, TimeoutException { ConnectionFactory factory = new ConnectionFactory(); factory.setHost("localhost"); factory.setPort(5672); Connection connection = factory.newConnection(); Channel channel = connection.createChannel(); channel.queueDeclare(QUEUE_NAME, false, false, false, null); // 同一时刻服务器只会发送一条音讯给消费者 channel.basicQos(1); DeliverCallback deliverCallback = (consumerTag, delivery) -> { String message = new String(delivery.getBody(), "UTF-8"); System.out.println(" [x] Received '" + delivery.getEnvelope().getRoutingKey() + "':'" + message + "'"); }; channel.basicConsume(QUEUE_NAME, true, deliverCallback, consumerTag -> { }); }}import com.rabbitmq.client.Channel;import com.rabbitmq.client.Connection;import com.rabbitmq.client.ConnectionFactory;import java.io.IOException;import java.util.concurrent.TimeoutException;public class Sender { private final static String QUEUE_NAME = "queue_work"; public static void main(String[] args) throws IOException, InterruptedException, TimeoutException { ConnectionFactory factory = new ConnectionFactory(); factory.setHost("localhost"); factory.setPort(5672); Connection connection = factory.newConnection(); Channel channel = connection.createChannel(); // 申明队列 channel.queueDeclare(QUEUE_NAME, false, false, false, null); for (int i = 0; i < 100; i++) { String message = "work mode message" + i; channel.basicPublish("", QUEUE_NAME, null, message.getBytes()); System.out.println("[x] Sent '" + message + "'"); Thread.sleep(i * 10); } channel.close(); connection.close(); }}公布订阅模式import com.rabbitmq.client.Channel;import com.rabbitmq.client.Connection;import com.rabbitmq.client.ConnectionFactory;import com.rabbitmq.client.DeliverCallback;public class Receive1 { private static final String EXCHANGE_NAME = "logs"; public static void main(String[] argv) throws Exception { ConnectionFactory factory = new ConnectionFactory(); factory.setHost("localhost"); Connection connection = factory.newConnection(); Channel channel = connection.createChannel(); channel.exchangeDeclare(EXCHANGE_NAME, "fanout"); String queueName = channel.queueDeclare().getQueue(); channel.queueBind(queueName, EXCHANGE_NAME, ""); System.out.println(" [*] Waiting for messages. To exit press CTRL+C"); // 订阅音讯的回调函数 DeliverCallback deliverCallback = (consumerTag, delivery) -> { String message = new String(delivery.getBody(), "UTF-8"); System.out.println(" [x] Received '" + message + "'"); }; // 消费者,有音讯时登程订阅回调函数 channel.basicConsume(queueName, true, deliverCallback, consumerTag -> { }); }}import com.rabbitmq.client.Channel;import com.rabbitmq.client.Connection;import com.rabbitmq.client.ConnectionFactory;import com.rabbitmq.client.DeliverCallback;public class Receive2 { private static final String EXCHANGE_NAME = "logs"; public static void main(String[] argv) throws Exception { ConnectionFactory factory = new ConnectionFactory(); factory.setHost("localhost"); Connection connection = factory.newConnection(); Channel channel = connection.createChannel(); channel.exchangeDeclare(EXCHANGE_NAME, "fanout"); String queueName = channel.queueDeclare().getQueue(); channel.queueBind(queueName, EXCHANGE_NAME, ""); System.out.println(" [*] Waiting for messages. To exit press CTRL+C"); // 订阅音讯的回调函数 DeliverCallback deliverCallback = (consumerTag, delivery) -> { String message = new String(delivery.getBody(), "UTF-8"); System.out.println(" [x] Received2 '" + message + "'"); }; // 消费者,有音讯时登程订阅回调函数 channel.basicConsume(queueName, true, deliverCallback, consumerTag -> { }); }}import com.rabbitmq.client.Channel;import com.rabbitmq.client.Connection;import com.rabbitmq.client.ConnectionFactory;public class Sender { private static final String EXCHANGE_NAME = "logs"; public static void main(String[] argv) throws Exception { ConnectionFactory factory = new ConnectionFactory(); factory.setHost("localhost"); Connection connection = factory.newConnection(); Channel channel = connection.createChannel(); channel.exchangeDeclare(EXCHANGE_NAME, "fanout"); String message = "publish subscribe message"; channel.basicPublish(EXCHANGE_NAME, "", null, message.getBytes("UTF-8")); System.out.println(" [x] Sent '" + message + "'"); channel.close(); connection.close(); }}路由模式import com.rabbitmq.client.Channel;import com.rabbitmq.client.Connection;import com.rabbitmq.client.ConnectionFactory;import com.rabbitmq.client.DeliverCallback;import java.io.IOException;import java.util.concurrent.TimeoutException;public class Receiver1 { private final static String QUEUE_NAME = "queue_routing"; private final static String EXCHANGE_NAME = "exchange_direct"; public static void main(String[] args) throws IOException, TimeoutException { ConnectionFactory factory = new ConnectionFactory(); factory.setHost("localhost"); factory.setPort(5672); Connection connection = factory.newConnection(); Channel channel = connection.createChannel(); channel.queueDeclare(QUEUE_NAME, false, false, false, null); // 指定路由的key,接管key和key2 channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "key"); channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "key2"); channel.basicQos(1); DeliverCallback deliverCallback = (consumerTag, delivery) -> { String message = new String(delivery.getBody(), "UTF-8"); System.out.println(" [x] Received '" + delivery.getEnvelope().getRoutingKey() + "':'" + message + "'"); }; channel.basicConsume(QUEUE_NAME, true, deliverCallback, consumerTag -> { }); }}import com.rabbitmq.client.Channel;import com.rabbitmq.client.Connection;import com.rabbitmq.client.ConnectionFactory;import com.rabbitmq.client.DeliverCallback;import java.io.IOException;import java.util.concurrent.TimeoutException;public class Receiver2 { private final static String QUEUE_NAME = "queue_routing2"; private final static String EXCHANGE_NAME = "exchange_direct"; public static void main(String[] args) throws IOException, TimeoutException { ConnectionFactory factory = new ConnectionFactory(); factory.setHost("localhost"); factory.setPort(5672); Connection connection = factory.newConnection(); Channel channel = connection.createChannel(); channel.queueDeclare(QUEUE_NAME, false, false, false, null); // 仅接管key2 channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "key2"); channel.basicQos(1); DeliverCallback deliverCallback = (consumerTag, delivery) -> { String message = new String(delivery.getBody(), "UTF-8"); System.out.println(" [x] Received '" + delivery.getEnvelope().getRoutingKey() + "':'" + message + "'"); }; channel.basicConsume(QUEUE_NAME, true, deliverCallback, consumerTag -> { }); }}import com.rabbitmq.client.Channel;import com.rabbitmq.client.Connection;import com.rabbitmq.client.ConnectionFactory;import java.io.IOException;import java.util.concurrent.TimeoutException;public class Sender { private final static String EXCHANGE_NAME = "exchange_direct"; private final static String EXCHANGE_TYPE = "direct"; public static void main(String[] args) throws IOException, TimeoutException { ConnectionFactory factory = new ConnectionFactory(); factory.setHost("localhost"); factory.setPort(5672); Connection connection = factory.newConnection(); Channel channel = connection.createChannel(); // 交换机申明 channel.exchangeDeclare(EXCHANGE_NAME, EXCHANGE_TYPE); // 只有routingKey雷同的才会生产 String message = "routing mode message"; channel.basicPublish(EXCHANGE_NAME, "key2", null, message.getBytes()); System.out.println("[x] Sent '" + message + "'");// channel.basicPublish(EXCHANGE_NAME, "key", null, message.getBytes());// System.out.println("[x] Sent '" + message + "'"); channel.close(); connection.close(); }}主题模式import com.rabbitmq.client.Channel;import com.rabbitmq.client.Connection;import com.rabbitmq.client.ConnectionFactory;import com.rabbitmq.client.DeliverCallback;import java.io.IOException;import java.util.concurrent.TimeoutException;public class Receiver1 { private final static String QUEUE_NAME = "queue_topic"; private final static String EXCHANGE_NAME = "exchange_topic"; public static void main(String[] args) throws IOException, InterruptedException, TimeoutException { ConnectionFactory factory = new ConnectionFactory(); factory.setHost("localhost"); factory.setPort(5672); Connection connection = factory.newConnection(); Channel channel = connection.createChannel(); channel.queueDeclare(QUEUE_NAME, false, false, false, null); // 能够接管key.1 channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "key.*"); channel.basicQos(1); DeliverCallback deliverCallback = (consumerTag, delivery) -> { String message = new String(delivery.getBody(), "UTF-8"); System.out.println(" [x] Received '" + delivery.getEnvelope().getRoutingKey() + "':'" + message + "'"); }; channel.basicConsume(QUEUE_NAME, true, deliverCallback, consumerTag -> { }); }}import com.rabbitmq.client.Channel;import com.rabbitmq.client.Connection;import com.rabbitmq.client.ConnectionFactory;import com.rabbitmq.client.DeliverCallback;import java.io.IOException;import java.util.concurrent.TimeoutException;public class Receiver2 { private final static String QUEUE_NAME = "queue_topic2"; private final static String EXCHANGE_NAME = "exchange_topic"; private final static String EXCHANGE_TYPE = "topic"; public static void main(String[] args) throws IOException, InterruptedException, TimeoutException { ConnectionFactory factory = new ConnectionFactory(); factory.setHost("localhost"); factory.setPort(5672); Connection connection = factory.newConnection(); Channel channel = connection.createChannel(); channel.queueDeclare(QUEUE_NAME, false, false, false, null); // *号代表单个单词,能够接管key.1 channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "*.*"); // #号代表多个单词,能够接管key.1.2 channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "*.#"); channel.basicQos(1); DeliverCallback deliverCallback = (consumerTag, delivery) -> { String message = new String(delivery.getBody(), "UTF-8"); System.out.println(" [x] Received '" + delivery.getEnvelope().getRoutingKey() + "':'" + message + "'"); }; channel.basicConsume(QUEUE_NAME, true, deliverCallback, consumerTag -> { }); }}import com.rabbitmq.client.Channel;import com.rabbitmq.client.Connection;import com.rabbitmq.client.ConnectionFactory;import java.io.IOException;import java.util.concurrent.TimeoutException;public class Sender { private final static String EXCHANGE_NAME = "exchange_topic"; private final static String EXCHANGE_TYPE = "topic"; public static void main(String[] args) throws IOException, TimeoutException { ConnectionFactory factory = new ConnectionFactory(); factory.setHost("localhost"); factory.setPort(5672); Connection connection = factory.newConnection(); Channel channel = connection.createChannel(); channel.exchangeDeclare(EXCHANGE_NAME, EXCHANGE_TYPE); String message = "topics model message with key.1"; channel.basicPublish(EXCHANGE_NAME, "key.1", null, message.getBytes()); System.out.println("[x] Sent '" + message + "'"); String message2 = "topics model message with key.1.2"; channel.basicPublish(EXCHANGE_NAME, "key.1.2", null, message2.getBytes()); System.out.println("[x] Sent '" + message2 + "'"); channel.close(); connection.close(); }}四种交换机介绍直连交换机(Direct exchange): 具备路由性能的交换机,绑定到此交换机的时候须要指定一个routing_key,交换机发送音讯的时候须要routing_key,会将音讯发送道对应的队列扇形交换机(Fanout exchange): 播送音讯到所有队列,没有任何解决,速度最快主题交换机(Topic exchange): 在直连交换机根底上减少模式匹配,也就是对routing_key进行模式匹配,*代表一个单词,#代表多个单词首部交换机(Headers exchange): 疏忽routing_key,应用Headers信息(一个Hash的数据结构)进行匹配,劣势在于能够有更多更灵便的匹配规定总结这么多种队列模式中都有其利用场景,大家能够依据利用场景示例中进行抉择 ...

June 5, 2021 · 6 min · jiezi

关于rabbitmq:RabbitMQ-主题模式的使用

主题模式与路由模式相似,发送到 topic 交换机的路由键必须是一个单词列表,由点号分隔。 例如:stock.usd.nyse、nyse.vmw、quick.orange.rabbit。 路由键中能够有任意多个单词,最多 255 个字节。 同时绑定键也必须应用雷同的模式。 装置依赖# composer.json{ "require": { "php-amqplib/php-amqplib": ">=3.0" }}> composer.phar install模式构造 topic 交换机背地的路由算法相似于 direct 替换,应用特定路由键发送的音讯将被传递到应用匹配绑定键绑定的所有队列。 绑定键有两个重要的非凡状况: *(星号)能够代替一个单词。\#(井号)能够代替零个或多个单词。上图的绑定能够总结为: Q1 对所有 orange 色彩的音讯都感兴趣。Q2 接管所有 rabbit 的音讯,以及所有 lazy 的音讯。示例路由键设置为 quick.orange.rabbit 的音讯将发送给两个队列。 lazy.orange.elephant 也会发送给两个队列。 quick.orange.fox 只会进入第一个队列。 lazy.brown.fox 只会进入第二个队列。 lazy.pink.rabbit 只会进入第二个队列一次,即便命中了两次绑定规定。 quick.brown.fox 不会进入任何队列。 orange 和 quick.orange.male.rabbit 不会进入任何队列,会被抛弃。 lazy.orange.male.rabbit 会进入第二个队列,命中了最初一个规定。 主题交换机功能强大,反对其余所有交换机的性能。 当队列与 \#(井号)绑定键绑定时将接管所有音讯,和 fanout 交换机一样。 当绑定中不应用特殊字符 *(星号)和 \#(井号)时,和 direct 交换机一样。 生产者生产者连贯到RabbitMQ,发送一条音讯,而后退出。 # send.php<?phprequire_once __DIR__ . '/vendor/autoload.php';use PhpAmqpLib\Connection\AMQPStreamConnection;use PhpAmqpLib\Message\AMQPMessage;// 创立连贯$connection = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest');// 创立通道$channel = $connection->channel();// 定义一个名为 topic_logs 的 topic 交换机$channel->exchange_declare('topic_logs', 'topic', false, false, false);// 从参数中获取交换机的路由键$routing_key = isset($argv[1]) && !empty($argv[1]) ? $argv[1] : 'anonymous.info';$data = implode(' ', array_slice($argv, 2));if (empty($data)) { $data = "Hello World!";}// $msg = new AMQPMessage($data);// 通过名为 topic_logs 的 topic 交换机发送音讯到队列 (音讯内容, 交换机, 路由键);$channel->basic_publish($msg, 'topic_logs', $routing_key);echo ' [x] Sent ', $routing_key, ':', $data, "\n";$channel->close();$connection->close();消费者消费者监听来自RabbitMQ的音讯,通常须要始终放弃运行状态以监听音讯。 ...

May 30, 2021 · 2 min · jiezi

关于rabbitmq:RabbitMQ-路由模式的使用

路由模式与公布订阅相似,区别是公布订阅替换机会将所有音讯播送给所有消费者绑定的队列,消费者生产全副音讯;而路由模式交换机只会将与路由键齐全匹配的音讯发送给消费者绑定的队列,消费者只生产该类音讯。 装置依赖# composer.json{ "require": { "php-amqplib/php-amqplib": ">=3.0" }}> composer.phar install模式构造 路由模式应用的是direct 交换机,这个交换机的路由算法也很简略,将它收到的所有音讯进入绑定键与音讯的路由键齐全匹配的队列 。 生产者生产者连贯到RabbitMQ,发送一条音讯,而后退出。 # send.php<?phprequire_once __DIR__ . '/vendor/autoload.php';use PhpAmqpLib\Connection\AMQPStreamConnection;use PhpAmqpLib\Message\AMQPMessage;// 创立连贯$connection = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest');// 创立通道$channel = $connection->channel();// 定义一个名为 direct_logs 的 direct 交换机$channel->exchange_declare('direct_logs', 'direct', false, false, false);// 从参数中获取交换机的路由键$severity = isset($argv[1]) && !empty($argv[1]) ? $argv[1] : 'info';$data = implode(' ', array_slice($argv, 2));if (empty($data)) { $data = "Hello World!";}// $msg = new AMQPMessage($data);// 通过名为 direct_logs 的 direct 交换机发送音讯到队列 (音讯内容, 交换机, 路由键);$channel->basic_publish($msg, 'direct_logs', $severity);echo ' [x] Sent ', $severity, ':', $data, "\n";$channel->close();$connection->close();消费者消费者监听来自RabbitMQ的音讯,通常须要始终放弃运行状态以监听音讯。 ...

May 30, 2021 · 1 min · jiezi

关于rabbitmq:RabbitMQ-发布订阅的使用

公布订阅的利用场景通常为一个生产者、一个交换机,多个消费者各自创立队列绑定到交换机上订阅音讯并生产。 公布订阅通常配合以下设置独特应用: 消费者创立的队列随机命名即可敞开队列长久化敞开音讯长久化消费者创立的队列在连贯敞开时主动删除开启主动音讯确认装置依赖# composer.json{ "require": { "php-amqplib/php-amqplib": ">=3.0" }}> composer.phar install模式构造 在 RabbitMQ 消息传递模型中,生产者是不会向队列间接发送音讯的,只能将音讯发送给交换机。 交换机接管来自生产者的音讯,而后将它们推送到队列中。 公布订阅应用的是fanout 交换机,这个交换机非常简单,将它收到的所有音讯播送到它绑定的所有队列。 生产者生产者连贯到RabbitMQ,发送一条音讯,而后退出。 # send.php<?phprequire_once __DIR__ . '/vendor/autoload.php';use PhpAmqpLib\Connection\AMQPStreamConnection;use PhpAmqpLib\Message\AMQPMessage;// 创立连贯$connection = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest');// 创立通道$channel = $connection->channel();// 定义一个名为 logs 的 fanout 播送交换机$channel->exchange_declare('logs', 'fanout', false, false, false);$data = implode(' ', array_slice($argv, 1));if (empty($data)) { $data = "info: Hello World!";}// $msg = new AMQPMessage($data);// 将音讯发送到名为 logs 的 fanout 播送交换机 (音讯内容, 交换机, 路由键);$channel->basic_publish($msg, 'logs');echo ' [x] Sent ', $data, "\n";$channel->close();$connection->close();消费者消费者监听来自RabbitMQ的音讯,通常须要始终放弃运行状态以监听音讯。 ...

May 30, 2021 · 1 min · jiezi

关于rabbitmq:RabbitMQ-工作队列的使用

工作队列的利用场景通常为一个生产者、一个队列、多个消费者偏心生产队列。 工作队列通常配合以下设置独特应用: 开启队列长久化开启音讯长久化开启偏心散发敞开主动音讯确认手动确认音讯装置依赖# composer.json{ "require": { "php-amqplib/php-amqplib": ">=3.0" }}> composer.phar install模式构造 生产者生产者连贯到RabbitMQ,发送一条音讯,而后退出。 # send.php<?phprequire_once __DIR__ . '/vendor/autoload.php';use PhpAmqpLib\Connection\AMQPStreamConnection;use PhpAmqpLib\Message\AMQPMessage;// 创立连贯$connection = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest');// 创立通道$channel = $connection->channel();// 创立队列,已存在的不会反复创立,第三个参数为开启队列长久化$channel->queue_declare('task_queue', false, true, false, false);$data = implode(' ', array_slice($argv, 1));if (empty($data)) { $data = "Hello World!";}// 第二个参数 delivery_mode = AMQPMessage::DELIVERY_MODE_PERSISTENT 为设置音讯长久化$msg = new AMQPMessage( $data, array('delivery_mode' => AMQPMessage::DELIVERY_MODE_PERSISTENT));// 通过默认的交换机发送音讯到队列 (音讯内容, 默认交换机, 路由键);$channel->basic_publish($msg, '', 'task_queue');echo ' [x] Sent ', $data, "\n";$channel->close();$connection->close();消费者消费者监听来自RabbitMQ的音讯,通常须要始终放弃运行状态以监听音讯。 ...

May 29, 2021 · 1 min · jiezi

关于rabbitmq:RabbitMQ-简单队列的使用

简略队列通常为一个生产者、一个消费者、一个队列的构造。 装置依赖# composer.json{ "require": { "php-amqplib/php-amqplib": ">=3.0" }}> composer.phar install模式构造 生产者生产者连贯到RabbitMQ,发送一条音讯,而后退出。 # send.php<?phprequire_once __DIR__ . '/vendor/autoload.php';use PhpAmqpLib\Connection\AMQPStreamConnection;use PhpAmqpLib\Message\AMQPMessage;// 创立连贯$connection = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest');// 创立通道$channel = $connection->channel();// 创立队列,已存在的队列不会反复创立$channel->queue_declare('hello', false, false, false, false);$msg = new AMQPMessage('Hello World!');// 通过默认的交换机发送音讯到队列 (音讯内容, 默认交换机, 路由键)$channel->basic_publish($msg, '', 'hello');echo " [x] Sent 'Hello World!'\n";$channel->close();$connection->close();消费者消费者监听来自 RabbitMQ 的音讯,通常须要始终放弃运行状态以监听音讯。 # receive.php<?phprequire_once __DIR__ . '/vendor/autoload.php';use PhpAmqpLib\Connection\AMQPStreamConnection;// 创立连贯$connection = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest');// 创立通道$channel = $connection->channel();// 创立队列,已存在的不会反复创立$channel->queue_declare('hello', false, false, false, false);echo " [*] Waiting for messages. To exit press CTRL+C\n";// 定义音讯解决回调函数$callback = function ($msg) { echo ' [x] Received ', $msg->body, "\n";};$channel->basic_consume('hello', '', false, true, false, false, $callback);while ($channel->is_open()) { $channel->wait();}$channel->close();$connection->close();运行关上一个终端,运行消费者: ...

May 29, 2021 · 1 min · jiezi

关于rabbitmq:RabbitMQ-的安装使用

装置Docker 装置docker run -it --rm --name rabbitmq -p 5672:5672 -p 15672:15672 rabbitmq:3-management镜像地址:https://registry.hub.docker.c... Debian, Ubuntu 装置https://www.rabbitmq.com/inst... RHEL, CentOS, Fedora 装置https://www.rabbitmq.com/inst... Windows 装置应用 choco 装置(举荐)应用命令行装置,会主动治理依赖: choco install rabbitmq应用安装包装置以管理员身份装置64位的 Erlang。下载并装置 RabbitMQ 服务,下载地址。RabbitMQ 会作为 Windows 服务装置并默认启动。能够在开始菜单中启动或者进行 RabbitMQ。PHP 相干扩大php-amqplib 一个纯 PHP 开发、功能齐全的 RabbitMQ 客户端 PECL AMQP library 建设在 RabbitMQ C 客户端 上的库 应用 CLI工具 治理RabbitMQ进行节点(以管理员身份运行): sbin/rabbitmqctl.bat stop查看节点状态(以管理员身份运行): sbin/rabbitmqctl.bat status参考:CLI 工具的应用,监控和状态查看 默认用户本地连接:guest/guest 参考:受权治理 端口阐明4369: Epmd,RabbitMQ 节点和 CLI 工具应用的对等发现服务,相当于 dns 的作用5672、5671:客户端通信端口,通过 server: amqp://guest:guest@localhost:5672/ 拜访15672: HTTP API客户端,Web 治理界面 和 Rabbitmqadmin,通过 http://serverip:15672 拜访其余RabbitMQ 与 Erlang 版本对应关系 ...

May 29, 2021 · 1 min · jiezi

关于rabbitmq:RabbitMQ最新完整教程IDEA版通俗易懂-视频笔记

笔记地址: https://www.bilibili.com/vide... 什么是中间件1 1 1 1

May 11, 2021 · 1 min · jiezi

关于rabbitmq:三RabbitMQ消息确认机制AMQP事务

咱们晓得能够通过长久化(交换机、队列和音讯长久化)来保障咱们在服务器解体是,重启服务器音讯数据不会失落,然而咱们无奈确认当音讯的发送者在将音讯发送进来之后,音讯到底有没有正确达到Broker代理服务器,如果不进行非凡配置的话,默认状况下公布操作是不会返回任何信息给生产者的,也就是默认状况下咱们的生产者是不晓得音讯有没有正确达到Broker的,如果音讯在达到Broker之前失落的话,长久化操作也解决不了这个问题,因为音讯基本就没达到代理服务器,这个是没有方法进行长久化的。这篇介绍应用AMQP协定层面提供的解决方案。 一、应用java原生事务RabbitMQ的事务机制与事务无关的次要有三个办法: txSelect()txCommit()txRollback()txSelect次要用于将以后channel设置成transaction模式,txCommit用于提交事务,txRollback用于回滚事务。 当咱们应用txSelect提交开始事务之后,咱们就能够公布音讯给Broke代理服务器,如果txCommit提交胜利了,则音讯肯定达到了Broke了,如果在txCommit执行之前Broker出现异常解体或者因为其余起因抛出异样,这个时候咱们便能够捕捉异样通过txRollback办法进行回滚事务了。这套事务次要代码为: channel.txSelect(); channel.basicPublish(exchange, routingKey, MessageProperties.PERSISTENT_TEXT_PLAIN, msg.getBytes()); channel.txCommit();即音讯的散发过程为: Client发送Tx.SelectBroker发送Tx.Select-Ok(在它之后,发送音讯)Client发送Tx.CommitBroker发送Tx.Commit-Ok二、联合SpringBoot应用事务在SpringBoot中次要是通过封装的RabbitTemplate模板来实现音讯的发送,这里次要也是分为两种状况,应用RabbitTemplate同步发送,或者异步发送。 留神:公布确认和事务。(两者不可同时应用)在channel为事务时,不可引入确认模式;同样channel为确认模式下,不可应用事务。 所以在应用事务时,在application.properties中,须要将确认模式更改为false。 # 反对公布确认spring.rabbitmq.publisher-confirms=falseA、同步通过设置RabbitTemplate的channelTransacted为true,来设置事务环境,使得能够应用RabbitMQ事务。如下: @Bean @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) public RabbitTemplate rabbitTemplateNew() { RabbitTemplate template = new RabbitTemplate(connectionFactory()); template.setChannelTransacted(true); return template; }这里与后面咱们解说的原生事务是统一的,而当发送音讯出现异常时,就会响应执行事务回滚。 B、异步方才咱们解说的是同步的状况,当初咱们解说一下异步的模式。在异步当中,次要应用MessageListener 接口,它是 Spring AMQP 异步音讯投递的监听器接口。而MessageListener的实现类SimpleMessageListenerContainer则是作为了整个异步音讯投递的外围类存在。 接下来咱们开始介绍应用异步的办法,同样示意须要的内部事务,用户须要在容器配置的时候指定PlatformTransactionManager的实现。代码如下: @Bean public SimpleMessageListenerContainer messageListenerContainer() { SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(); container.setConnectionFactory(connectionFactory()); container.setTransactionManager(rabbitTransactionManager()); container.setChannelTransacted(true); // 开启手动确认 container.setAcknowledgeMode(AcknowledgeMode.MANUAL); container.setQueues(transitionQueue()); container.setMessageListener(new TransitionConsumer()); return container; }这段代码咱们是增加在config下的RabbitConfig.java下,通过配置事务管理器,将channelTransacted属性被设置为true。 在容器中配置事务时,如果提供了transactionManager,channelTransaction必须为true,使得如果监听器解决失败,并且抛出异样,那么事务将进行回滚,那么音讯将返回给音讯代理;如果为false,内部的事务依然能够提供给监听容器,造成的影响是在回滚的业务操作中也会提交音讯传输的操作。 通过应用RabbitTransactionManager,这个事务管理器是PlatformTransactionManager接口的实现,它只能在一个Rabbit ConnectionFactory中应用。 留神:这种策略不可能提供XA事务,例如在音讯和数据库之间共享事务。 除了下面的代码外,还有RabbitTransactionManager和TransitionConsumer须要增加,代码如下: /** * 申明transition2队列 * * @return */ @Bean public Queue transitionQueue() { return new Queue("transition2"); } /** * 事务管理 * * @return */ @Bean public RabbitTransactionManager rabbitTransactionManager() { return new RabbitTransactionManager(connectionFactory()); } /** * 自定义消费者 */ public class TransitionConsumer implements ChannelAwareMessageListener { @Override public void onMessage(Message message, Channel channel) throws Exception { byte[] body = message.getBody(); System.out.println("TransitionConsumer: " + new String(body)); // 确认音讯胜利生产 channel.basicAck(message.getMessageProperties().getDeliveryTag(), false); // 除以0,模仿异样,进行事务回滚 // int t = 1 / 0; } }

March 28, 2021 · 1 min · jiezi

关于rabbitmq:二RabbitMQ消息分发机制

咱们晓得每个音讯的解决工夫是不同的,换句话说音讯的复杂度是不同的,有些音讯很简单,须要很久的工夫,有些音讯很简略,只需耗时一会就能够实现,而在理论状况下如何分配资源,让效率达到最大化,从而实现按能力分配任务,达到物尽其用。这就须要音讯的散发机制。 一、Fair dispatch(偏心散发)这里咱们创立DistributionSender.java和DistributionReceiver.java来模仿发送者和接收者。DistributionSender.java @Componentpublic class DistributionSender { @Autowired private AmqpTemplate rabbitTemplate; public void send(int i) { // 发送的音讯 String message = "This is a task, and the complexity is " + i + "。" + StringUtils.repeat(".", i); this.rabbitTemplate.convertAndSend("distribu", message); }}应用默认交换机,队列为“distribu” /** * 申明distribu队列 * * @return */ @Bean public Queue DistribuQueue() { return new Queue("distribu"); }java和DistributionReceiver.java @Componentpublic class DistributionReceiver { /** * 消费者A * * @param msg */ @SuppressWarnings("deprecation") @RabbitListener(queues = "distribu") public void processA(Message message) { String msg = new String(message.getBody()); System.out.println(" DistributionReceiverA : " + msg); SimpleDateFormat time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSSS"); System.out.println(" ProccessingA... at " + time.format(new Date())); try { for (char ch : msg.toCharArray()) { if (ch == '.') { doWork(1000); } } } catch (InterruptedException e) { } finally { System.out.println(" A Done! at " + time.format(new Date())); } } private void doWork(long time) throws InterruptedException { Thread.sleep(time); }}增加RabbitTest.java文件模仿申请 ...

March 28, 2021 · 3 min · jiezi

关于rabbitmq:一RabbitMQ消息路由机制

一、Rabbit路由协定——AMQP协定AMQP(Advanced Message Queuing Protocol,高级音讯队列协定)是一个网络协议。它反对符合要求的客户端利用(application)和消息中间件代理(messaging middleware broker)之间进行通信。次要特色是面向音讯、队列、路由(包含点对点和公布/订阅)、可靠性、平安。简略点说就是在异样通信中,音讯不会立刻达到接管方,而是被寄存到一个容器中,当满足肯定的条件之后,音讯会被容器发送给接管方,这个容器就是音讯队列(MQ),而实现这个性能须要单方和容器以及其中的各个组件遵循规定,AMQP就是这样一种协定,音讯发送和接管的单方都要恪守。AMQP机制为:音讯(message)被发布者(publisher)发送给交换机(exchange),交换机将收到的音讯依据路由规定发给绑定的队列(queue)。最初AMQP代理会将音讯投递给订阅了此队列的消费者,或者消费者依照需要自行获取,如图:这是一个简略的“Hello,world”示例,从发布者到生成者音讯的大抵流向,其中还省略了一些AMQP理论的组件细节。这里次要包含以下一些组件: Publisher,数据的发送方。Exchange,音讯交换机,它指定音讯按什么规定,路由到哪个队列,这里的规定前面会有介绍。Queue,音讯队列载体,每个音讯都会被投入到一个或多个队列。Consumer,数据的接管方。发布者(Publisher)公布音讯时能够给音讯指定各种音讯属性(message meta-data)。有些属性有可能会被音讯代理(Brokers)应用,然而其余的属性则是齐全不通明的,它们只能被接管音讯的利用所应用。 从平安角度思考,网络是不牢靠的,接管音讯的利用也有可能在解决音讯的时候失败。基于此起因,AMQP模块蕴含了一个音讯确认(message acknowledgements)的概念:当一个音讯从队列中投递给消费者后(Consumer),消费者会告诉一下音讯代理(Broker),这个能够是主动的,也能够由解决音讯的利用的开发者执行。当“音讯确认”被启用的时候,音讯代理不会齐全将音讯从队列中删除,直到它收到来自消费者的确认回执(acknowledgement)。 在某些状况下,例如当一个音讯无奈被胜利路由时,音讯或者会被返回给发布者并被抛弃。或者,如果音讯代理执行了延期操作,音讯会被放入一个所谓的死信队列中。此时,音讯发布者能够抉择某些参数来解决这些非凡状况。 队列,交换机和绑定统称为AMQP实体(AMQP entities)。 以上这些是在上图中显示进去的一些AMQP组件元件,除了这些外,还有一些额定的概念,次要为:Binding,绑定,音讯队列与交换器间接关联的,它的作用就是把Exchange和Queue依照路由规定绑定起来。 Routing Key,路由关键字,Exchange依据这个关键字进行音讯投递。 Channel,信道,多路复用连贯中的一条独立的双向数据流通道,为会话提供物理传输介质。Channel是在connection外部建设的逻辑连贯,如果应用程序反对多线程,通常每个thread创立独自的channel进行通信,AMQP method蕴含了channel id帮忙客户端和message broker辨认channel,所以channel之间是齐全隔离的。Channel作为轻量级的Connection极大缩小了操作系统建设TCP connection的开销。在客户端的每个连贯里,可建设多个Channel,每个Channel代表一个会话工作。 Broker ,AMQP的服务端称为Broker。其实Broker就是接管和散发音讯的利用,也就是说RabbitMQ Server就是Message Broker。 Virtual Host,虚拟主机,一批交换器(Exchange),音讯队列(Queue)和相干对象。虚拟主机是共享雷同身份认证和加密环境的独立服务器域。同时一个Broker里能够开设多个vhost,用作不同用户的权限拆散。 Connection ,连贯,一个网络连接,比方TCP/IP套接字连贯。Channel是建设在Connection之上的,一个Connection能够建设多个Channel。 Message,音讯体,是AMQP所操纵的根本单位,它由Producer产生,通过Broker被Consumer所生产。它的根本构造有两局部: Header和Body。Header是由Producer增加上的各种属性的汇合,这些属性有管制Message是否可被缓存,接管的Queue是哪个,优先级是多少等。Body是真正须要传送的数据,它是对Broker不可见的二进制数据流,在传输过程中不应该受到影响。 下面的简略实例图只是简略阐明了一些音讯传送的根本流程,可能其中的频道、虚拟主机、连贯、信道等都没有体现进去。到前面RabbitMQ的知识点都会缓缓介绍到。 总的AMQP的结构图如下所示: 上面对AMQP的一些重要概念做详细分析: 交换机(音讯交换机)交换机是用来发送音讯的AMQP实体。交换机拿到一个音讯之后将它路由给一个或零个队列。它应用哪种路由算法是由交换机类型和被称作绑定(bindings)的规定所决定的。 四种交换机: Direct exchange(直连交换机)Fanout exchange(扇型交换机)Topic exchange(主题交换机)Headers exchange(头交换机)交换机能够有两个状态:长久(durable)、暂存(transient)。长久化的替换机会在音讯代理(Broker)重启后仍旧存在,而暂存的交换机则不会(它们须要在代理再次上线后从新被申明)。然而并不是所有的利用场景都须要长久化的交换机。 不同的交换机的区别和用法,会在前面的文章中做介绍,这里只须要晓得有几种类型的交换机就能够了。 交换机的几个重要属性:NameDurability (音讯代理重启后,交换机是否还存在)Auto-delete (当所有与之绑定的音讯队列都实现了对此交换机的应用后,删掉它)Arguments(依赖代理自身) 队列AMQP中的队列(Queue)跟其余音讯队列或工作队列中的队列是很类似的:它们存储着行将被利用生产掉的音讯。队列跟交换机共享某些属性,然而队列也有一些另外的属性。 NameDurable(音讯代理重启后,队列仍旧存在)Exclusive(只被一个连贯(connection)应用,而且当连贯敞开后队列即被删除)Auto-delete(当最初一个消费者退订后即被删除)Arguments(一些音讯代理用他来实现相似与TTL的某些额定性能) 队列在申明(declare)后能力被应用。如果一个队列尚不存在,申明一个队列会创立它。如果申明的队列曾经存在,并且属性完全相同,那么此次申明不会对原有队列产生任何影响。如果申明中的属性与已存在队列的属性有差别,那么一个错误代码为406的通道级异样就会被抛出。 队列长久化长久化队列(Durable queues)会被存储在磁盘上,当音讯代理(broker)重启的时候,它仍旧存在。没有被长久化的队列称作暂存队列(Transient queues)。长久化的队列并不会使得路由到它的音讯也具备持久性。假使音讯代理挂掉了,重新启动,那么在重启的过程中长久化队列会被从新申明,无论怎样,只有通过长久化的音讯能力被从新复原。(队列长久化 ≠ 音讯长久化) 绑定绑定(Binding)是交换机(Exchange)将音讯(Message)路由给队列(Queue)所需遵循的规定。如果要批示交换机“E”将音讯路由给队列“Q”,那么“Q”就须要与“E”进行绑定。绑定操作须要定义一个可选的路由键(Routing Key)属性给某些类型的交换机。路由键的意义在于从发送给交换机的泛滥音讯中抉择出某些音讯,将其路由给绑定的队列。 打个比方: 队列(Queue)是咱们想要去的目的地交换机(Exchange)是一个转换站,比方车站绑定(Binding)就是车站到目的地的路线。可能达到目的地的路线能够是一条或者多条领有了交换机这个中间层,很多由发布者间接到队列难以实现的路由计划可能得以实现,并且防止了利用开发者的许多重复劳动。 如果AMQP的音讯无奈路由到队列(例如,发送到的交换机没有绑定队列),音讯会被就地销毁或者返还给发布者。如何解决取决于发布者设置的音讯属性。 虚拟主机为了在一个独自的代理上实现多个隔离的环境(用户、用户组、交换机、队列 等),AMQP提供了一个虚拟主机(virtual hosts - vhosts)的概念。这跟Web servers虚拟主机概念十分类似,这为AMQP实体提供了齐全隔离的环境。当连贯被建设的时候,AMQP客户端来指定应用哪个虚拟主机。 连贯AMQP连贯通常是长连贯。AMQP是一个应用TCP提供牢靠投递的应用层协定。AMQP应用认证机制并且提供TLS(SSL)爱护。当一个利用不再须要连贯到AMQP代理的时候,须要优雅的开释掉AMQP连贯,而不是间接将TCP连贯敞开。 信道有些利用须要与AMQP代理建设多个连贯。无论怎样,同时开启多个TCP连贯都是不适合的,因为这样做会消耗掉过多的系统资源并且使得防火墙的配置更加艰难。AMQP 0-9-1提供了信道(channels)来解决多连贯,能够把信道了解成共享一个TCP连贯的多个轻量化连贯。 在波及多线程/过程的利用中,为每个线程/过程开启一个信道(channel)是很常见的,并且这些通道不能被线程/过程共享。 二、RabbitMQ的工作流程介绍建设信息。Publisher定义须要发送音讯的构造和内容。建设Conection和Channel。由Publisher和Consumer创立连贯,连贯到Broker的物理节点上,同时建设Channel。Channel是建设在Connection之上的,一个Connection能够建设多个Channel。Publisher连贯Virtual Host 建设Channel,Consumer连贯到相应的Queue上建设Channel。申明交换机和队列。申明一个音讯交换机(Exchange)和队列(Queue),并设置相干属性。发送音讯。由Publisher发送音讯到Broker中的Exchange中路由转发。RabbitMQ收到音讯后,依据音讯指定的Exchange(交换机) 来查找Binding(绑定) 而后依据规定(Routing Key)散发到不同的Queue。这里就是说应用Routing Key在音讯交换机(Exchange)和音讯队列(Queue)中建设好绑定关系,而后将音讯发送到绑定的队列中去。音讯接管。Consumer监听相应的Queue,一旦Queue中有能够生产的音讯,Queue就将音讯发送给Consumer端。音讯确认。当Consumer实现某一条音讯的解决之后,须要发送一条ACK音讯给对应的Queue。 ...

March 28, 2021 · 1 min · jiezi

关于rabbitmq:00-RabbitMQ基础实践单节点环境安装

一、装置装置依赖: yum install socat -y下载并装置Erlang: # downloadwget https://github.com/rabbitmq/erlang-rpm/releases/download/v23.0.2/erlang-23.0.2-1.el7.x86_64.rpm# installrpm -ivh erlang-23.0.2-1.el7.x86_64.rpm装置RabbitMQ # downloadwget https://github.com/rabbitmq/rabbitmq-server/releases/download/v3.8.5/rabbitmq-server-3.8.5-1.el7.noarch.rpm# installrpm -ivh rabbitmq-server-3.8.5-1.el7.noarch.rpm# systemctl list-unit-files|grep rabbitmq-serversystemctl aux|grep rabbitmq-serverrabbitmq理论的装置地位是:/usr/lib/rabbitmq二、启动并创立用户启用治理插件: [root@localhost zephyr]# rabbitmq-plugins enable rabbitmq_managementEnabling plugins on node rabbit@localhost:rabbitmq_managementThe following plugins have been configured: rabbitmq_management rabbitmq_management_agent rabbitmq_web_dispatchApplying plugin configuration to rabbit@localhost...The following plugins have been enabled: rabbitmq_management rabbitmq_management_agent rabbitmq_web_dispatchset 3 plugins.Offline change; changes will take effect at broker restart.# 查看所有插件rabbitmq-plugins list启动RabbitMQ(两种模式二选一即可): # 前台启动rabbitmq-server# 后盾启动systemctl start rabbitmq-server# 或 rabbitmq-server -detached增加用户: ...

March 18, 2021 · 1 min · jiezi

关于rabbitmq:分享自画的一个支付方案图

February 28, 2021 · 0 min · jiezi

关于rabbitmq:消息队列概览

为什么要音讯队列利用场景很多,典型的就是生产者和消费者。比方须要异步解决的时候,或者须要对队列进行流量管制的时候,以及服务解耦等,这些中央都能够用到音讯队列。 音讯队列有很多益处,比方某些场景能够对音讯队列组件长期横向扩容,来抵挡抵挡大流量,达到削峰填谷的成果;生产消费者的队列,来实现两边速率不统一的问题;还能够是其余的:增加流计算解决;作为公布 / 订阅零碎实现一个微服务级零碎间的观察者模式;用于将音讯播送给大量接收者。总之作用很多,利用场景也很多。 然而音讯队列不是实现的,要依据理论状况来确定,依据各种音讯队列的特点来抉择应用。 该如何抉择音讯队列以下几个指标能够作为一个参考 音讯的牢靠传递:确保不丢音讯Cluster:反对集群,确保不会因为某个节点宕机导致服务不可用,当然也不能丢音讯;性能:具备足够好的性能,能满足绝大多数场景的性能要求。上边三点是工作中比拟常关注的点,理论工作中常常遇到,不过也有一些其余的因素,只是一个参考罢了 那么常见的音讯队列都有哪些呢 RabbitMQRocketMQKafka以上就是常见的音讯队列了,其中redis能够说算不上音讯队列,但次要是redis应用的太多了,大家都比拟手熟,所以也放到了这里。他们别离呈现在不同的期间,解决不同工夫的问题。 首先RabbitMQ,算是一个老牌的音讯队列了,呈现的背景为了解决电信零碎之间牢靠通信。 他的音讯队列的能力大略是每秒钟几万到几十万条数据,特点是轻量级迅捷,这也是他的slogan。而且他也是应用十分多的一个消息中间件。他有一个十分有特色的性能,就是在生产者和队列之间,他提供了一个Exchange模块,这个模块能够让你来决定音讯该放到哪一个队列里边去,而且规定非常灵活。最初这个中间件还反对很多种语言,能够说是最丰盛的几个之一他的也有毛病,而且比拟头疼 RabbitMQ 对音讯沉积的反对并不好,在它的设计理念外面,音讯队列是一个管道,大量的音讯积压是一种不失常的状况,该当尽量去防止。有时候这种沉积不是你被动造成的,比方其他人的代码抢占了你的消费者的计算资源,你往往很难预料到RabbitMQ 的性能是咱们介绍的这几个音讯队列中最差的,尽管也够日常应用了他要命的编程语言,elang的确是个大坑,不是很举荐。其次是RocketMQ 这是一个号称领有金融机稳定性的中间件,各方面都不错,性能、稳定性和可靠性都是值得信赖的。作为一个国产产品,益处是中文文档比拟全,毛病是应用的人不是多,生态跟其它的比拟还是逊色了些。 最初是kafka,赫赫有名 Kafka 应用 Scala 和 Java 语言开发,设计上大量应用了批量和异步的思维,这种设计使得 Kafka 能做到超高的性能。Kafka 的性能,尤其是异步收发的性能,是三者中最好的,但与 RocketMQ 并没有量级上的差别,大概每秒钟能够解决几十万条音讯。 然而他的批量发送的逻辑,让实时性不是太好,对于某些实时性较高的场景他不是很适合。然而除了这点外,大型互联里边就很常常用到它了。 音讯队列的应用音讯队列中应用的常见痛点 丢音讯丢音讯是一件重大的问题。绝大多数的丢音讯,都是因为开发者不理解他的特点导致的。为了防止丢了音讯还不晓得,能够在音讯中增加间断递增的序号,来判断音讯是否有失落,失落的是哪个。 然而在分布式中有以下问题,比方kafka不保障整个集群是间断的,只能保障单个实例是间断的。所以个别是保障分区数据始终性。 确保音讯牢靠传递 生产节点要确保发送胜利了,有异样要及时捕捉 存储阶段合理配置,保证数据存写到磁盘中;如果是集群,请确保音讯是发送到了多个broker上的 生产音讯后,尽量保障音讯正确生产后再通知队列这个音讯被生产了反复音讯 音讯队列有几种精度,At most once、At least once、Exactly once。个别中间件提供的精度也就是al least once。 kafka也一样所以做法是在生产端做幂等操作。然而有些操作也不是人造能够做成幂等的,所以有一些常见的办法操作来设置幂等性 利用数据库的惟一束缚实现幂等为更新的数据设置前置条件记录并查看操作解决音讯积压 生产者太快了,升高生产者这边的生产速度;消费者太慢了,进步消费者的生产速率,一般来说正当的设计是消费者效率高于生产者的效率才行;是否生产端存在异样;

February 24, 2021 · 1 min · jiezi

关于rabbitmq:docker部署rabbitmq带控制台

一、拉去镜像:management带有控制台的rabbitmq:docker pull rabbitmq:management咱们进入rabbitmq容器,执行上面的命令开启stomp插件rabbitmq-plugins enable rabbitmq_web_stomp rabbitmq_web_stomp_examples将以后的容器提交为新的镜像docker commit 3989ec68bf3c rabbitmq:stomp进行以后的容器docker stop 3989ec68bf3c重新启动一个容器docker run -di --name=changgou_rabbitmq -p 5671:5617 -p 5672:5672 -p 4369:4369 -p 15671:15671 -p 15672:15672 -p 25672:25672 -p 15670:15670 -p 15674:15674 rabbitmq:stomp

February 3, 2021 · 1 min · jiezi

关于rabbitmq:RabbitM思维导图

January 14, 2021 · 0 min · jiezi

关于rabbitmq:RabbitMQ-phpamqplib-基本操作与日常场景示例

发现网上并没有RabbitMQ PHP客户端的较为详实的应用文档(当然也可能是我搜索引擎应用不纯熟?)总之,简略的总结了此文,附录各参数和罕用的工作队列,死信队列,以及不同类型交换器的示例,自己程度无限,不免有谬误之处,欢送大佬斧正~ 服务器环境 Ubuntu 18.04.5 LTSPHP 7.2.24RabbitMQ 3.6.10php-amqplib 2.7 1.各办法参数//1.1 建设连贯$conn = new AMQPStreamConnection($host, $port, $user, $password, $vhost);参数:$host: RabbitMQ服务器主机IP地址$port: RabbitMQ服务器端口$user: 连贯RabbitMQ服务器的用户名$password: 连贯RabbitMQ服务器的用户明码$vhost: 连贯RabbitMQ服务器的vhost(服务器能够有多个vhost,虚拟主机,相似nginx的vhost)//1.2 建设信道$channel = $conn->channel($channel_id); 参数:$channel_id 信道id,不传则获取$channel[“”]信道,再无则循环$this->channle数组,下标从1到最大信道数找第一个不是AMQPChannel对象的下标,实例化并返回AMQPChannel对象,无则抛出异样No free channel ids//1.3 申明交换器$channel->exchange_declare($exhcange_name, $type, $passive, $durable, $auto_delete);参数:$exhcange_name 交换器名字$type 交换器类型$passive 是否检测同名队列$durable 交换机是否开启长久化$auto_detlete 通道敞开后是否删除队列(1)交换器类型枚举 [ direct: (默认)间接交换器,工作形式相似于单播,Exchange会将音讯发送齐全匹配ROUTING_KEY的Queue, fanout: 播送是式交换器,不论音讯的ROUTING_KEY设置为什么,Exchange都会将音讯转发给所有绑定的Queue, topic: 主题交换器,工作形式相似于组播,Exchange会将音讯转发和ROUTING_KEY匹配模式雷同的所有队列,比方,ROUTING_KEY为user.stock的Message会转发给绑定匹配模式为 * .stock,user.stock, * . * 和#.user.stock.#的队列。(* 表是匹配一个任意词组,#示意匹配0个或多个词组), headers:依据音讯体的header匹配 ]//1.4 申明队列$channel->queue_declare($queue_name, $passive, $durable, $exclusive, $auto_delete);参数:$queue_name 队列名称$passive 是否检测同名队列$durable 是否开启队列长久化$exclusive 队列是否能够被其余队列拜访$auto_delete 通道敞开后是否删除队列//1.5 创立要发送的信息 ,能够创立多个音讯$msg = new AMQPMessage($data, $properties)$data 要发送的音讯$properties Array 设置的属性,比方设置该音讯长久化['delivery_mode'=>2]//单个发送$channel->basic_publish($msg, $exchange = '', $routing_key = '', $mandatory = false, $immediate = false, $ticket = null);参数:$msg 音讯内容$exchange 交换器$routing_key routing_key$mandatory 匹配不到队列时,是否立刻抛弃音讯$immediate 队列无消费者时,是否立刻抛弃音讯$ticket 这个俺也不晓得 坐等大佬//多个发送1.屡次调用 $channel->batch_basic_publish($msg, $exchange = '', $routing_key = '', $mandatory = false, $immediate = false, $ticket = null)外部实现:往$this->batch_messages[]塞2.再调用一次$channel->publish_batch(),实现发送1.6 路由绑定$channel->queue_bind( $queue, $exchange, $routing_key = '', $nowait = false, $arguments = array(), $ticket = null )参数:$queue 队列名$exchange 交换器名$routing_key routing_key$nowait 同上 俺也不知$arguments$ticket 1.7 生产音讯$channel->basic_consume( $queue = '', $consumer_tag = '', $no_local = false, $no_ack = false, $exclusive = false, $nowait = false, $callback = null, $ticket = null, $arguments = array() )参数:$queue 队列名$consumer_tag $no_local $no_ack 是否不须要手动ack:true就是不须要ack|false须要手动ack$exclusive$nowait$callback 音讯回调函数$ticket$arguments1.8 手动ack 示例$callback = function($msg) { sleep($msg->body); echo " [x] Received sleep ", $msg->body, "\n"; $msg->delivery_info['channel']->basic_ack($msg->delivery_info['delivery_tag']); echo " [x] Ack "."\n"; };1.9 限度散发 示例限度RabbitMQ只发不超过1条的音讯给同一个消费者。当音讯处理完毕后,有了反馈,才会进行第二次发送。$channel->basic_qos(null,1,null);2.罕用场景2.1 工作队列 按生产能力散发生产者和消费者均减少$channel->basic_qos(null,1,null);即可。2.2 fanout播送示例 注册行为例如注册后须要发送欢送短信和邮件,将注册行为播送至短信和邮件生产者//定义交换器$channel->exchange_declare('register','fanout',false,false,false);$msg = new AMQPMessage('register event');$channel->basic_publish($msg, 'register');注册短信消费者$channel->exchange_declare('register','fanout',false,false,false);$channel->queue_declare('register.sms', false, false, false, false);$channel->queue_bind('register.sms', 'register');注册邮件消费者$channel->exchange_declare('register','fanout',false,false,false);$channel->queue_declare('register.mail', false, false, false, false);$channel->queue_bind('register.mail', 'register');2.3 topic类型 含糊匹配示例 日志分级例如我想一个消费者承受所有日志,一个消费者只接管Error级别日志生产者//定义交换器$channel->exchange_declare('log','topic',false,false,false);$num = rand(0,10);if ($num%3 == 0) { $level = 'error';}elseif($num%3 == 1){ $level = 'warning';}else{ $level = 'common';}$msg = new AMQPMessage('log event '.$level);$channel->basic_publish($msg, 'log', 'log.'.$level);全量日志消费者$channel->exchange_declare('log','topic',false,false,false);$channel->queue_declare('log.all', false, false, false, false);$channel->queue_bind('log.all', 'log', 'log.*');Error日志消费者$channel->exchange_declare('log','topic',false,false,false);$channel->queue_declare('log.error', false, false, false, false);$channel->queue_bind('log.error', 'log', 'log.error');2.4 headers类型 匹配示例 日志分级例如我想一个消费者承受所有日志,一个消费者只接管Error级别日志生产者//定义交换器$channel->exchange_declare('log2','headers',false,false,false);$num = rand(0,10);if ($num%3 == 0) { $level = 'error';}elseif($num%3 == 1){ $level = 'warning';}else{ $level = 'common';}$msg = new AMQPMessage('log2 event '.$level);$bindArguments = [ 'level' => $level, 'type' => 'log' ]; $headers = new AMQPTable($bindArguments);$msg->set('application_headers', $bindArguments); $channel->basic_publish($msg, 'log2');全量日志消费者$channel->exchange_declare('log2','headers',false,false,false);$channel->queue_declare('log2.all', false, false, false, false);$bindArguments = [ 'type' => 'log', //'x-match' => 'any' //默认any]; $headers = new AMQPTable($bindArguments);$channel->queue_bind('log2.all', 'log2', '', false, $headers);Error日志消费者$channel->exchange_declare('log2','headers',false,false,false);$channel->queue_declare('log2.error', false, false, false, false);$bindArguments = [ 'type' => 'log', 'level' => 'error', 'x-match' => 'all' //默认any]; $headers = new AMQPTable($bindArguments);$channel->queue_bind('log2.error', 'log2', '', false, $headers);2.5死信队列//2.5.1 定义一个没有消费者,5s后音讯过期的队列//生产者$arguments = new AMQPTable([ 'x-dead-letter-exchange' => 'dead', 'x-message-ttl' => 5000, //音讯存活工夫毫秒 'x-dead-letter-routing-key' => 'dead']);//定义队列 不要交换器$channel->queue_declare('no_consume', false, false, false, false, false, $arguments);$now = time();$msg = new AMQPMessage(time()); $channel->basic_qos(null,1,null);$channel->basic_publish($msg, '', 'no_consume');echo " [x] Sent no_consume :".date('Y-m-d H:i:s',$now)."\n";$channel->close();$connection->close();//消费者$channel->exchange_declare('dead','topic',false,false,false);$channel->queue_declare('dead.all', false, false, false, false);$channel->queue_bind('dead.all', 'dead', 'dead');$channel->basic_qos(null,1,null);echo ' [*] Waiting for messages. To exit press CTRL+C', "\n";$callback = function($msg) { var_dump('msg:'.date('Y-m-d H:i:s',$msg->body)); var_dump('now:'.date('Y-m-d H:i:s')); echo " [x] Received log error ", $msg->body, "\n";};$channel->basic_consume('dead.all', '', false, true, false, false, $callback);while(count($channel->callbacks)) { $channel->wait();} ...

January 2, 2021 · 2 min · jiezi

关于rabbitmq:RabbitMQ实践code

简略模式-生产与生产producer生产者 import pikaimport json credentials = pika.PlainCredentials('guest', 'guest')conn = pika.BlockingConnection( pika.ConnectionParameters(host='your robbitmq server', port=5672, virtual_host='/', credentials=credentials)) channel = conn.channel()result = channel.queue_declare(queue='zy_test') for i in range(100): message = json.dumps({'OrderId': f'1000{i}'}) channel.basic_publish(exchange='', routing_key='zy_test', body=message) print(message) conn.close()consumer消费者 import pikaimport json credentials = pika.PlainCredentials('guest', 'guest')conn = pika.BlockingConnection( pika.ConnectionParameters(host='your robbitmq server', port=5672, virtual_host='/', credentials=credentials)) channel = conn.channel()# durable 长久化 音讯不失落channel.queue_declare(queue='zy_test', durable=True)# 负载平衡:应用basicQos( prefetchCount = 1)办法,来限度RabbitMQ只发不超过1条的音讯给同一个消费者。当音讯处理完毕后,有了反馈,才会进行第二次发送。channel.basic_qos(prefetch_count=1) def callback(ch, method, properties, body): ch.basic_ack(delivery_tag=method.delivery_tag) print(body.decode()) channel.basic_consume(queue='zy_test', on_message_callback=callback)channel.start_consuming()公布与订阅公布与订阅要借助交换机(EXchange)的原理来实现: ...

December 28, 2020 · 3 min · jiezi

关于rabbitmq:RobbitMQ安装

装置以CentOS零碎为例 1、在服务器上配置epel源# CentOS6wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-6.repo# 验证是否胜利yum repolist # 如果出错,就编辑vi epel.repo,勾销baseurl的正文,将mirrorlist行正文,就差不多了. # CentOS7同理wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repowget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo2、装置#装置erlang语言,rabbitMQ应用erlang语言写的yum -y install erlangyum -y install rabbitmq-server3、启动、进行# 启动service rabbitmq-server start# 进行service rabbitmq-server stop# 更多命令:start|stop|status|rotate-logs|restart|condrestart|try-restart|reload|force-reload4、次要端口阐明4369 -- erlang发现口 5672 --client端通信口 15672 -- 治理界面ui端口 25672 -- server间外部通信口 RabbitMQ界面 http://host:15672/默认用户名/明码:guest/guest 连贯RabbitMQ要用client端通信口:server: amqp://guest:guest@localhost:5672/ 5、web界面打不开解决方案cd /usr/lib/rabbitmq/lib/rabbitmq_server-3.1.5/sbin./rabbitmq-plugins list # 如果下图中几项后面中括号为空,则执行如下命令:./rabbitmq-plugins enable rabbitmq_management# 而后再执行list命令,看web页面相干plugins是否启动,参照下图./rabbitmq-plugins list# 如果曾经启动则重启rabbitmq service rabbitmq-server restart 6、罕用概念Broker:简略来说就是音讯队列服务器实体。Exchange:音讯交换机,他制订音讯按什么规定,路由到哪个队列。Queue:音讯队列载体,每个音讯都会被投入一个或多个队列。Binding:绑定,他的作用就是把exchange和queue依照路由规定绑定起来。Routing Key:路由关键字,exchange依据这个关键字进行音讯投递。vhost:虚拟主机,一个broker里能够设多个vhost,用作不同用户得权限拆散。producer:音讯生产者,就是投递音讯得程序。consumer:音讯消费者,就是承受音讯得程序。channel:音讯通道,在客户端得每个连贯里。能够建设多个channel,每个channel代表一个会话工作。

December 28, 2020 · 1 min · jiezi

关于rabbitmq:RobbitMQ使用入门

什么是MQ音讯总线(Message Queue),是一种跨过程、异步的通信机制,用于上下游传递音讯。由音讯零碎来确保音讯的牢靠传递。 MQ是干什么用的?利用解耦、异步、流量削锋、数据散发、错峰流控、日志收集等等... 解耦举例:看这么个场景。A 零碎发送数据到 BCD 三个零碎,通过接口调用发送。如果 E 零碎也要这个数据呢?那如果 C 零碎当初不须要了呢?A 零碎负责人简直解体......,所以通过公布订阅模式,谁须要谁订阅即可。 异步举例:A 零碎接管一个申请,须要在本人本地写库,还须要在 BCD 三个零碎写库,本人本地写库要 3ms,BCD 三个零碎别离写库要 300ms、450ms、200ms。最终申请总延时是 3 + 300 + 450 + 200 = 953ms,靠近 1s,用户感觉搞个什么货色,慢死了慢死了。用户通过浏览器发动申请,期待个 1s,这简直是不可承受的。 如果应用异步,A零碎解决完本人的逻辑,间接返回给用户;而后发消息让BCD写库;用户收到申请只有3ms,体验晦涩美滋滋。 流量削峰举例:每天 0:00 到 12:00,A 零碎惊涛骇浪,每秒并发申请数量就 50 个。后果每次一到 12:00 ~ 13:00 ,每秒并发申请数量忽然会暴增到 5k+ 条。然而零碎是间接基于 MySQL 的,大量的申请涌入 MySQL,每秒钟对 MySQL 执行约 5k 条 SQL。个别的 MySQL,扛到每秒 2k 个申请就差不多了,如果每秒申请到 5k 的话,可能就间接把 MySQL 给打死了,导致系统解体,用户也就没法再应用零碎了。 这时能够通过MQ,把音讯挤压在队列中,至多能够保证系统失常可用;而后依照零碎失常处理速度写入数据,也不会失落数据。 MQ的潜在毛病零碎可用性升高零碎引入的内部依赖越多,越容易挂掉。原本你就是 A 零碎调用 BCD 三个零碎的接口就好了,人 ABCD 四个零碎好好的,没啥问题,你偏加个 MQ 进来,万一 MQ 挂了咋整,MQ 一挂,整套零碎解体的,你不就完了?如何保障音讯队列的高可用零碎复杂度进步硬生生加个 MQ 进来,你怎么保障音讯没有反复生产?怎么解决音讯失落的状况?怎么保障消息传递的程序性?头大头大,问题一大堆,苦楚不已。一致性问题A 零碎解决完了间接返回胜利了,人都认为你这个申请就胜利了;然而问题是,要是 BCD 三个零碎那里,BD 两个零碎写库胜利了,后果 C 零碎写库失败了,咋整?你这数据就不统一了。主流产品RabbitMQ,Kafka,ActiveMQ,RocketMQ等等 ...

December 28, 2020 · 1 min · jiezi

关于rabbitmq:2020最新RabbitMQ图文教程通俗易懂版上内附视频链接

RabbitMQ学习指标 MQ简介 在计算机科学中,音讯队列(英语:Message queue)是一种过程间通信或同一过程的不同线程间的通信形式,软件的贮列用来解决一系列的输出,通常是来自用户。音讯队列提供了异步的通信协议,每一个贮列中的纪录蕴含具体阐明的数据,蕴含产生的工夫,输出设施的品种,以及特定的输出参数,也就是说:音讯的发送者和接收者不须要同时与音讯队列互交。音讯会保留在队列中,直到接收者取回它。 实现 音讯队列经常保留在链表构造中。领有权限的过程能够向音讯队列中写入或读取音讯。 目前,有很多音讯队列有很多开源的实现,包含JBoss Messaging、JORAM、Apache ActiveMQ、Sun Open Message Queue、IBM MQ、Apache Qpid和HTTPSQS。 以后应用较多的音讯队列有RabbitMQ、RocketMQ、ActiveMQ、Kafka、ZeroMQ、MetaMq等,而局部数据库如Redis、Mysql以及phxsql也可实现音讯队列的性能。 特点 MQ是消费者-生产者模型的一个典型的代表,一端往音讯队列中一直写入音讯,而另一端则能够读取或者订阅队列中的音讯。MQ和JMS相似,但不同的是JMS是SUN JAVA消息中间件服务的一个规范和API定义,而MQ则是遵循了AMQP协定的具体实现和产品。 留神: AMQP,即Advanced Message Queuing Protocol,一个提供对立音讯服务的应用层规范高级音讯队列协定,是应用层协定的一个凋谢规范,为面向音讯的中间件设计。基于此协定的客户端与消息中间件可传递音讯,并不受客户端/中间件不同产品,不同的开发语言等条件的限度。JMS,Java音讯服务(Java Message Service)利用程序接口,是一个Java平台中对于面向消息中间件的API,用于在两个应用程序之间,或分布式系统中发送音讯,进行异步通信。 Java音讯服务是一个与具体平台无关的API,绝大多数MOM提供商都对JMS提供反对。常见的音讯队列,大部分都实现了JMS API,如ActiveMQ,Redis以及RabbitMQ等。优缺点长处 利用耦合、异步解决、流量削锋 解耦 传统模式: 传统模式的毛病: 零碎间耦合性太强,如上图所示,零碎A在代码中间接调用零碎B和零碎C的代码,如果未来D零碎接入,零碎A还须要批改代码,过于麻烦! 中间件模式 中间件模式的的长处: 将音讯写入音讯队列,须要音讯的零碎本人从音讯队列中订阅,从而零碎A不须要做任何批改。 异步 传统模式: 传统模式的毛病: 一些非必要的业务逻辑以同步的形式运行,太消耗工夫。 中间件模式: 中间件模式的的长处: 将音讯写入音讯队列,须要音讯的零碎本人从音讯队列中订阅,从而零碎A不须要做任何批改。 削峰 传统模式: 传统模式的毛病: 并发量大的时候,所有的申请间接怼到数据库,造成数据库连贯异样 ...

December 25, 2020 · 2 min · jiezi

关于rabbitmq:RabbitMQ-消费者获取队列消息的两种模式

订阅模式-Push API消息中间件被动将音讯推送给订阅的消费者,实时性好。 利用能够通过订阅特定的队列,获取到 RabbitMQ 被动推送(主动投递)的队列音讯。通过在队列中注册一个消费者实现。订阅胜利后,RabbitMQ 将开始投递音讯。每一次音讯投递都会调用用户提供的处理程序。处理程序须要遵循特定的接口。 订阅胜利会返回订阅标识符,能够用来勾销订阅。 boolean autoAck = false;channel.basicConsume(queueName, autoAck, "myConsumerTag", new DefaultConsumer(channel) { @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { String routingKey = envelope.getRoutingKey(); String contentType = properties.getContentType(); long deliveryTag = envelope.getDeliveryTag(); // (process the message components here ...) channel.basicAck(deliveryTag, false); } });检索模式-Pull API消费者被动从消息中间件中拉取音讯,实时性差。 利用能够通过 basic.get 办法,一条一条地从 RabbitMQ 中拉取音讯,音讯以先进先出的程序被拉取,能够主动或手动确认。 不倡议应用检索模式,与订阅模式相比效率极低。尤其在音讯公布数量少、队列长时间为空的利用中会造成大量资源节约。 boolean autoAck = false;GetResponse response = channel.basicGet(queueName, autoAck);if (response == null) { // No message retrieved.} else { AMQP.BasicProperties props = response.getProps(); byte[] body = response.getBody(); long deliveryTag = response.getEnvelope().getDeliveryTag(); // (process the message components here ...) channel.basicAck(deliveryTag, false);}

December 19, 2020 · 1 min · jiezi

关于rabbitmq:RabbitMQ集群镜像模式搭建

RabbitMQ集群-镜像模式搭建[TOC] 简介RabbitMQ是基于Erlang编写,Erlang语言天生具备分布式个性(通过同步Erlang集群各节点的magic cookie来实现)。因而,RabbitMQ人造反对Clustering。这使得RabbitMQ自身不须要像ActiveMQ、Kafka那样通过ZooKeeper别离来实现HA高可用计划和保留集群的元数据。集群是保障可靠性的一种形式,同时能够通过程度扩大以达到减少音讯吞吐量能力的目标。 单机模式个别就是本地启动进行开发,不用于生产用 高可用模式主备模式Warren 模式。实现 rabbitMQ 的高可用集群,个别在并发和数据量不高的状况下,这种模式十分的好用且简略。 也就是一个主/备计划,主节点提供读写,备用节点不提供读写。如果主节点挂了,就切换到备用节点,原来的备用节点降级为主节点提供读写服务,当原来的主节点复原运行后,原来的主节点就变成备用节点,和 activeMQ 利用 zookeeper 做主/备一样,也能够一主多备。 <img src="https://test-1251230131.cos.ap-shanghai.myqcloud.com//imgimage-20201206161314300.png" style="zoom:50%;" /> 近程模式近程模式能够实现双活的一种模式,简称 shovel 模式,所谓的 shovel 就是把音讯进行不同数据中心的复制工作,能够跨地区的让两个 MQ 集群互联,远距离通信和复制。 Shovel 就是咱们能够把音讯进行数据中心的复制工作,咱们能够跨地区的让两个 MQ 集群互联。rabbitMQ 比拟晚期的架构模型了,当初很少应用了。 多活模式多活模式:这种模式也是实现异地数据复制的支流模式,因为Shovel模式配置比较复杂,所以一般来说实现异地集群都是应用这种双活或者多活模型来实现的。这种模型须要依赖rabbitmq的federation插件,能够实现继续的牢靠的AMQP数据通信,多活模式在理论配置与利用上十分的简略。提供了更牢靠的齐备的数据保障,即便一个集群挂掉,也还有另外一个集群。 RabbitMQ部署架构采纳双核心模式(多核心) , 那么在两套(或多套)数据中心中各部署一套RabbitMQ集群,各核心的RabbitMQ服务除了须要为业务提供失常的音讯服务外,核心之间还须要实现局部队列音讯共享。 集群模式一般集群默认模式,RabbitMQ集群中节点包含内存节点、磁盘节点。内存节点就是将所有数据放在内存,磁盘节点将数据放在磁盘上。如果在投递音讯时,关上了音讯的长久化,那么即便是内存节点,数据还是平安的放在磁盘。那么内存节点的性能只能体现在资源管理上,比方减少或删除队列(queue),虚拟主机(vrtual hosts),交换机(exchange)等,发送和承受message速度同磁盘节点一样。一个集群至多要有一个磁盘节点。一个rabbitmq集群中能够共享user,vhost,exchange等,所有的数据和状态都是必须在所有节点上复制的,对于queue依据集群模式不同,应该有不同的体现。在集群模式下只有有任何一个节点可能工作,RabbitMQ集群对外就能提供服务。 以两个节点(rabbit01、rabbit02)为例来进行阐明。对于 Queue 来说,音讯实体只存在于其中一个节点 rabbit01(或者 rabbit02),rabbit01 和 rabbit02 两个节点仅有雷同的元数据,即队列的构造。当音讯进入 rabbit01 节点的 Queue 后,consumer 从 rabbit02 节点生产时,RabbitMQ 会长期在 rabbit01、rabbit02 间进行音讯传输,把 A 中的音讯实体取出并通过 B 发送给 consumer。所以 consumer 应尽量连贯每一个节点,从中取音讯。即对于同一个逻辑队列,要在多个节点建设物理 Queue。否则无论 consumer 连 rabbit01 或 rabbit02,进口总在 rabbit01,会产生瓶颈。当 rabbit01 节点故障后,rabbit02 节点无奈取到 rabbit01 节点中还未生产的音讯实体。如果做了音讯长久化,那么得等 rabbit01 节点复原,而后才可被生产;如果没有长久化的话,就会产生音讯失落的景象。 ...

December 10, 2020 · 3 min · jiezi

关于rabbitmq:RabbitMQ二RabbitMQ整合SpringBoot

新建我的项目 pom.xml<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.4.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>cn.tedu</groupId> <artifactId>rabbitmq-springboot</artifactId> <version>0.0.1-SNAPSHOT</version> <name>rabbitmq-springboot</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.springframework.amqp</groupId> <artifactId>spring-rabbit-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build></project>application.ymlspring: rabbitmq: host: 192.168.64.140 username: admin password: admin主程序删除主动创立的主程序 ...

December 6, 2020 · 6 min · jiezi

关于rabbitmq:RabbitMQ常用命令

RabbitMQ常用命令简介基本概念Server(broker): 承受客户端连贯,实现AMQP音讯队列和路由性能的过程。Virtual Host:其实是一个虚构概念,相似于权限控制组,一个Virtual Host外面能够有若干个Exchange和Queue,然而权限管制的最小粒度是Virtual Host。Exchange:承受生产者发送的音讯,并依据Binding规定将音讯路由给服务器中的队列。ExchangeType决定了Exchange路由音讯的行为,例如,在RabbitMQ中,ExchangeType有direct、Fanout和Topic三种,不同类型的Exchange路由的行为是不一样的。Message Queue:音讯队列,用于存储还未被消费者生产的音讯。Message: 由Header和Body组成,Header是由生产者增加的各种属性的汇合,包含Message是否被长久化、由哪个Message Queue承受、优先级是多少等。而Body是真正须要传输的APP数据。Binding:Binding分割了Exchange与Message Queue。Exchange在与多个Message Queue产生Binding后会生成一张路由表,路由表中存储着Message Queue所需音讯的限度条件即Binding Key。当Exchange收到Message时会解析其Header失去Routing Key,Exchange依据Routing Key与Exchange Type将Message路由到Message Queue。Binding Key由Consumer在Binding Exchange与Message Queue时指定,而Routing Key由Producer发送Message时指定,两者的匹配形式由Exchange Type决定。Connection:连贯,对于RabbitMQ而言,其实就是一个位于客户端和Broker之间的TCP连贯。Channel:信道,仅仅创立了客户端到Broker之间的连贯后,客户端还是不能发送音讯的。须要为每一个Connection创立Channel,AMQP协定规定只有通过Channel能力执行AMQP的命令。一个Connection能够蕴含多个Channel。之所以须要Channel,是因为TCP连贯的建设和开释都是非常低廉的,如果一个客户端每一个线程都须要与Broker交互,如果每一个线程都建设一个TCP连贯,暂且不思考TCP连贯是否节约,就算操作系统也无奈接受每秒建设如此多的TCP连贯。RabbitMQ倡议客户端线程之间不要共用Channel,至多要保障共用Channel的线程发送音讯必须是串行的,然而倡议尽量共用Connection。Command:AMQP的命令,客户端通过Command实现与AMQP服务器的交互来实现本身的逻辑。例如在RabbitMQ中,客户端能够通过publish命令发送音讯,txSelect开启一个事务,txCommit提交一个事务。用户角色用户角色分为5中类型: 用户角色可分为五类,超级管理员, 监控者, 策略制定者, 一般管理者以及其余。 超级管理员(administrator)可登陆治理控制台(启用management plugin的状况下),可查看所有的信息,并且能够对用户,策略(policy)进行操作。 监控者(monitoring)可登陆治理控制台(启用management plugin的状况下),同时能够查看rabbitmq节点的相干信息(过程数,内存应用状况,磁盘应用状况等) 策略制定者(policymaker)可登陆治理控制台(启用management plugin的状况下), 同时能够对policy进行治理。但无奈查看节点的相干信息 一般管理者(management)仅可登陆治理控制台(启用management plugin的状况下),无奈看到节点信息,也无奈对策略进行治理。 其余(none)无奈登陆治理控制台,通常就是一般的生产者和消费者。 常用命令节点治理# 查问节点状态rabbitmqctl status# 进行RabbitMQ利用,然而Erlang虚拟机还是处于运行状态。此命令的执行优先于其余治理操作,比方rabbitmqctl reset。rabbitmqctl stop_ app # 启动RabbitMQ利用。在执行了其余治理操作之后,重新启动之前进行的RabbitMQ利用,比rabbitmqctl reset。rabbitmqctl start_app# 重置RabbitMQ节点,将RabbitMQ节点重置还原到最后状态。包含从原来所在的集群中删除此节点,从治理数据库 中删除所有的配置数据,如己配置的用户、 vhost 等,以及删除所有的长久化音讯。执行 rabbi tmqctl reset 命令前必须进行RabbitMQ 利用。rabbitmqctl reset# 强制将 RabbitMQ 节点重置还原到最后状态。不同于 rabbitmqctl reset 命令, rabbitmqctl force_reset 命令不管以后治理数据库的状态和集群配置是什么,都会无条件地重直节点。它只能在数据库或集群配置己损坏的状况下应用。与 rabbitmqctl reset 命令一样,执行 rabbitmqctl force_reset 命令前必须先进行 RabbitMQ 利用。rabbitmqctl force_reset# 批示RabbitMQ节点轮换日志文件。RabbitMQ节点会将原来的日志文件中的内容追加到"原 始名称+后缀"的日志文件中,而后再将新的日志内容记录到新创建的日志中(与原日志文件同名)。当指标文件不存在时,会从新创立。如果不指定后缀suffix. 则日志文件只是从新关上而不会进行轮换。rabbitmqctl rotate_logs {suffix}# 进行运行RabbitMQ的Erlang虚拟机和RabbitMQ利用。如果RabbitMQ没有胜利敞开,则会返回一个非零值。这个命令和rabbitmqctl stop 不同的是,它不须要指定pid_file而能够阻塞期待指定过程的敞开。rabbitmqctl shutdown# 进行运行RabbitMQ的Erlang虚拟机和RabbitMQ服务利用,其中pid_file是通过rabbitmq-server命令启动RabbitMQ 服务时创立的,默认状况下寄存于mnesia目录中。留神rabbitmq-server -detach 这个带有 -detach后缀的命令来启动 RabbitMQ 服务则不会生成 pid_file 文件。指定pid_file会期待指定过程的完结。rabbitmqctl stop [pid_file] 插件治理# rabbitmq-plugins [-n node] {command} [command options ...]# 启动插件# rabbitmq-plugins enable [--offline] [--online] {plugin ...}rabbitmq-plugins enable rabbitmq_management# 禁用插件# rabbitmq-plugins disable [--offline] [--online] {plugin ...}rabbitmq-plugins disable rabbitmq_management# 示意启用参数指定的插件,并且禁用其余所有插件# 没有参数示意禁用所有的插件rabbitmq-plugin set rabbitmq_management# 显示所有的插件,每一行一个rabbitmq-plugins list# 显示所有的插件,并且显示插件的版本号和形容信息rabbitmq-plugins list -v# 显示所有名称含有 "management" 的插件rabbitmq-plugins list -v management# 显示所有显示或者隐式启动的插件rabbitmq-plugins list -e rabbit对象治理# name:列举出所有虚拟机,tracing:示意是否应用了 RabbitMQ 的 trace 性能rabbitmqctl list_vhosts [name,tracing]# 查看交换器rabbitmqctl list_exchanges [-p vhost] [exchangeinfoitem ...]# 查看绑定关系的细节rabbitmqctl list_bindings [-p vhost] [bindinginfoitem ...]# 查看已申明的队列rabbitmqctl list_queues [-p vhost] [queueinfoitem ...] # 返回 TCP!IP连贯的统计信息。rabbìtmqctl lìst_connectìons [connectìonìnfoìtem ...]# 返回以后所有信道的信息。rabbitmqctl list_channels [channelinfoitem ...]# 列举消费者信息 每行将显示由制表符分隔的己订阅队列的名称、相干信道的过程标识、consumerTag、是否须要生产端确认 prefetch_count 及参数列表这些信息。rabbitmqctl list_consumers [-p vhost]# 创立一个新的 vhost ,大括号里的参 数示意 vhost 的名称。rabbitmqctl add vhost {vhostName}# 删除一个vhost,同时也会删除其下所有的队列、交换器、绑定关系、 用户权限、参数和策略等信息。rabbitmqctl delete_vhost {vhostName}# RabbitMQ 中的授予权限是指在 vhost 级别对用户而言的权限授予。rabbitmqctl set permissions [-p vhostName] {userName} {conf} {write} {read} # 对RabbitMQ 节点进行健康检查,确认利用是否失常运行、list_queues list_channels 是否可能失常返回等。rabbitmqctl node_health_check# 显示每个运行程序环境中每个变量的名称和值。rabbitmqctl environment# 为所有服务器状态生成一个服务器状态报告,井将输入重定向到一个文件:rabbitmqctl report > report.txtrabbitmqctl report# 显示 Broker 的状态,比方以后 Erlang 节点上运行的应用程序、RabbitMQ/Erlang的版本信息、os 的名称、内 存及文件描述符等统计信息。rabbitmqctl status# 策略管理# 策略查看rabbitmqctl list_policies [-p <vhost>]# 策略设置rabbitmqctl set_policy [-p <vhost>] [--priority <priority>] [--apply-to <apply-to>] <name> <pattern> <definition># 策略革除rabbitmqctl clear_policy [-p <vhost>] <name>集群治理# 显示集群的状态rabbitmqctl cluster_status # 将节点退出指定集群中。在这个命令执行前须要进行 RabbitMQ利用井重置节点。rabbitmqctl joio_cluster {cluster_node} [--ram] # 批改集群节点的类型。在这个命令执行前须要进行 RabbitMQ利用。rabbitmqctl change_cluster_node_type {disclram}# 将节点从集群中删除,容许离线执行。rabbitmqctl forget_cluster_node [--offiine] # 来查看那些slaves曾经实现同步:rabbitmqctl list_queues {queue_name} {slave_pids} synchronised_slave_pids# 手动的形式同步一个queue:rabbitmqctl sync_queue {queue_name}# 勾销某个queue的同步性能:rabbitmqctl cancel_sync_queue {queue_name}用户治理# 查看用户列表rabbitmqctl list_users# 删除用户rabbitmqctl delete_user {username}# 革除用户明码rabbitmqctl clear_password {username}# 批改明码rabbitmqctl change_password {username} {newPassword}# 验证用户rabbitmqctl authentiçate_user {username} {passWord}# 新增用户rabbitmqctl add_user {username} {password}# 给用户受权rabbitmqctl set_user_tags {username} {roles}# 分明用户对某个虚拟机的权限。rabbitmqctl clear_permissions [-p vhostName] {username}# 用来显示虚拟主机上的权限。rabbitmqctl list_permissions [-p vhost] # 用来显示用户在已调配虚拟机上的权限。rabbitmqctl list_user_permissions {username}命令实战用户操作# 能够创立管理员用户,负责整个MQ的运维rabbitmqctl add_user admin adminpasspord# 赋予其administrator角色rabbitmqctl set_user_tags admin administrator# 创立RabbitMQ监控用户,负责整个MQ的监控rabbitmqctl add_user user_monitoring passwd_monitor # 赋予其monitoring角色rabbitmqctl set_user_tags user_monitoring monitoring

December 6, 2020 · 2 min · jiezi

关于rabbitmq:RabbitMQ一RabbitMQ简介

RabbitMQ 应用场景服务解耦假如有这样一个场景, 服务A产生数据, 而服务B,C,D须要这些数据, 那么咱们能够在A服务中间接调用B,C,D服务,把数据传递到上游服务即可 然而,随着咱们的利用规模不断扩大,会有更多的服务须要A的数据,如果有几十甚至几百个上游服务,而且会一直变更,再加上还要思考上游服务出错的状况,那么A服务中调用代码的保护会极为艰难 这是因为服务之间耦合度过于严密 再来思考用RabbitMQ解耦的状况 A服务只须要向音讯服务器发送音讯,而不必思考谁须要这些数据;上游服务如果须要数据,自行从音讯服务器订阅音讯,不再须要数据时则勾销订阅即可 流量削峰假如咱们有一个利用,平时访问量是每秒300申请,咱们用一台服务器即可轻松应答 而在高峰期,访问量霎时翻了十倍,达到每秒3000次申请,那么单台服务器必定无奈应答,这时咱们能够思考减少到10台服务器,来扩散拜访压力 但如果这种刹时顶峰的状况每天只呈现一次,每次只有半小时,那么咱们10台服务器在少数工夫都只分担每秒几十次申请,这样就有点浪费资源了 这种状况,咱们就能够应用RabbitMQ来进行流量削峰,顶峰状况下,霎时呈现的大量申请数据,先发送到音讯队列服务器,排队期待被解决,而咱们的利用,能够缓缓的从音讯队列接管申请数据进行解决,这样把数据处理工夫拉长,以加重刹时压力 这是音讯队列服务器十分典型的利用场景 异步调用思考定外卖领取胜利的状况 领取后要发送领取胜利的告诉,再寻找外卖小哥来进行配送,而寻找外卖小哥的过程十分耗时,尤其是高峰期,可能要期待几十秒甚至更长 这样就造成整条调用链路响应十分迟缓 而如果咱们引入RabbitMQ音讯队列,订单数据能够发送到音讯队列服务器,那么调用链路也就能够到此结束,订单零碎则能够立刻失去响应,整条链路的响应工夫只有200毫秒左右 寻找外卖小哥的利用能够以异步的形式从音讯队列接管订单音讯,再执行耗时的寻找操作 rabbitmq 基本概念RabbitMQ是一种消息中间件,用于解决来自客户端的异步音讯。服务端将要发送的音讯放入到队列池中。接收端能够依据RabbitMQ配置的转发机制接管服务端发来的音讯。RabbitMQ根据指定的转发规定进行音讯的转发、缓冲和长久化操作,次要用在多服务器间或单服务器的子系统间进行通信,是分布式系统规范的配置。 Exchange承受生产者发送的音讯,并依据Binding规定将音讯路由给服务器中的队列。ExchangeType决定了Exchange路由音讯的行为。在RabbitMQ中,ExchangeType罕用的有direct、Fanout和Topic三种。 Message Queue音讯队列。咱们发送给RabbitMQ的音讯最初都会达到各种queue,并且存储在其中(如果路由找不到相应的queue则数据会失落),期待消费者来取。 Binding Key它示意的是Exchange与Message Queue是通过binding key进行分割的,这个关系是固定。 Routing Key生产者在将音讯发送给Exchange的时候,个别会指定一个routing key,来指定这个音讯的路由规定。这个routing key须要与Exchange Type及binding key联结应用能力生,咱们的生产者只须要通过指定routing key来决定音讯流向哪里。 rabbitmq装置离线装置下载离线安装包文件 https://download.csdn.net/download/weixin_38305440/12265906上传离线安装包 rabbitmq-install 目录上传到 /root切换到rabbitmq-install目录 cd rabbitmq-install装置 rpm -ivh *.rpmYum在线装置以下内容来自 RabbitMQ 官网手册 rpm --import https://github.com/rabbitmq/signing-keys/releases/download/2.0/rabbitmq-release-signing-key.asc# centos7 用这个cat <<EOF > /etc/yum.repos.d/rabbitmq.repo[bintray-rabbitmq-server]name=bintray-rabbitmq-rpmbaseurl=https://dl.bintray.com/rabbitmq/rpm/rabbitmq-server/v3.8.x/el/7/gpgcheck=0repo_gpgcheck=0enabled=1EOF# centos6 用这个cat <<EOF > /etc/yum.repos.d/rabbitmq.repo[bintray-rabbitmq-server]name=bintray-rabbitmq-rpmbaseurl=https://dl.bintray.com/rabbitmq/rpm/rabbitmq-server/v3.8.x/el/6/gpgcheck=0repo_gpgcheck=0enabled=1EOFyum makecacheyum install socatwget https://github.com/rabbitmq/erlang-rpm/releases/download/v21.3.8.12/erlang-21.3.8.12-1.el7.x86_64.rpmrpm -ivh erlang-21.3.8.12-1.el7.x86_64.rpm --force --nodepsyum install rabbitmq-server启动rabbitmq服务器# 设置服务,开机主动启动systemctl enable rabbitmq-server# 启动服务systemctl start rabbitmq-serverrabbitmq治理界面启用治理界面# 开启治理界面插件rabbitmq-plugins enable rabbitmq_management# 防火墙关上 15672 治理端口firewall-cmd --zone=public --add-port=15672/tcp --permanentfirewall-cmd --reload重启RabbitMQ服务systemctl restart rabbitmq-server拜访拜访服务器的15672端口,例如:http://192.168.64.140:15672 ...

December 5, 2020 · 12 min · jiezi

关于rabbitmq:工作队列-rabbitmq

Work Queues In the first tutorial we wrote programs to send and receive messages from a named queue. In this one we'll create a Work Queue that will be used to distribute time-consuming tasks among multiple workers. 在第一个教程中,咱们编写了从命名队列发送和接管音讯的程序。在这个示例中,咱们将创立一个工作队列,用于在多个worker之间调配耗时的工作。 The main idea behind Work Queues (aka: Task Queues) is to avoid doing a resource-intensive task immediately and having to wait for it to complete. Instead we schedule the task to be done later. We encapsulate a task as a message and send it to a queue. A worker process running in the background will pop the tasks and eventually execute the job. When you run many workers the tasks will be shared between them. ...

November 20, 2020 · 3 min · jiezi

关于rabbitmq:RabbitMQ简介

RabbitMQ is a message broker: it accepts and forwards messages. You can think about it as a post office: when you put the mail that you want posting in a post box, you can be sure that Mr. or Ms. Mailperson will eventually deliver the mail to your recipient. In this analogy, RabbitMQ is a post box, a post office and a postman. The major difference between RabbitMQ and the post office is that it doesn't deal with paper, instead it accepts, stores and forwards binary blobs of data‒messages. ...

November 20, 2020 · 4 min · jiezi

关于rabbitmq:119

rabbitmq六种模式发送音讯的程序就是生产者队列就代表一个邮箱。消费者期待从队列接管音讯ConnectionFactory f = new ConnectionFactory(); f.setHost("192.168.64.140"); f.setPort(5672);//可选,5672是默认端口 f.setUsername("admin"); f.setPassword("admin");工作模式一个生产者,两个消费者rabbitmq在所有消费者中轮询散发音讯,把音讯平均地发送给所有消费者 正当的散发abbitmq会一次把多个音讯分发给消费者, 这样可能造成有的消费者十分忙碌, 而其它消费者闲暇. 而rabbitmq对此无所不知, 依然会平均的散发音讯 咱们能够应用 basicQos(1) 办法, 这通知rabbitmq一次只向消费者发送一条音讯, 在返回确认回执前, 不要向消费者发送新音讯. 而是把音讯发给下一个闲暇的消费者 音讯长久化当rabbitmq敞开时, 咱们队列中的音讯依然会失落, 除非明确要求它不要失落数据 要求rabbitmq不失落数据要做如下两点: 把队列和音讯都设置为可长久化(durable) 队列设置为可长久化, 能够在定义队列时指定参数durable为true 第二个参数是长久化参数durablech.queueDeclare("helloworld", true, false, false, null);公布和订阅模式咱们将做一些齐全不同的事件——咱们将向多个消费者传递同一条音讯。这种模式称为“公布/订阅”。 Exchanges交换机RabbitMQ消息传递模型的核心思想是,生产者永远不会将任何音讯间接发送到队列。实际上,通常生产者甚至不晓得音讯是否会被传递到任何队列。有几种可用的替换类型:direct、topic、header和fanout。咱们将关注最初一个——fanout。让咱们创立一个这种类型的交换机,并称之为 logs: ch.exchangeDeclare("logs", "fanout"); 主动生成队列名非长久,独占,主动删除String queueName = ch.queueDeclare().getQueue(); 4.路由模式

November 9, 2020 · 1 min · jiezi

关于rabbitmq:rabbitmq

装置rpm -ivh *.rpm 启动rabbitmq服务器 rabbitmq治理界面启动治理界面 重启RabbitMQ服务systemctl restart rabbitmq-server 增加用户 凋谢客户端连贯端口 rabbitmq六种工作模式1.简略模式>>>只有一个消费者2.工作模式3.公布订阅模式4.路由模式5.主题模式6.RPC模式

October 31, 2020 · 1 min · jiezi

关于rabbitmq:vivo-基于原生-RabbitMQ-的高可用架构实践

一、背景阐明vivo 在 2016 年引入 RabbitMQ,基于开源 RabbitMQ 进行扩大,向业务提供消息中间件服务。 2016~2018年,所有业务均应用一个集群,随着业务规模的增长,集群负载越来越重,集群故障频发。 2019年,RabbitMQ 进入高可用建设阶段,实现了高可用组件 MQ 名字服务以及 RabbitMQ 集群的同城双活建设。 同时进行业务应用集群的物理拆分,严格依照集群负载状况和业务流量进行业务应用集群的调配以及动静调整。 在 2019 年高可用建设后至今,业务流量减少了十倍,集群未呈现过重大故障。 RabbitMQ 是实现了 AMQP 协定的开源音讯代理软件,起源于金融零碎。 具备丰盛的个性: 音讯可靠性保障,RabbitMQ 通过发送确认保障音讯发送牢靠、通过集群化、音讯长久化、镜像队列的形式保障音讯在集群的牢靠、通过生产确认保障音讯生产的可靠性。RabbitMQ 提供了多种语言的客户端。提供了多种类型的 exchange,音讯发送到集群后通过exchange路由到具体的queue中。RabbitMQ 提供了欠缺的治理后盾和治理 API,通过治理API能够疾速与自建监控零碎整合。RabbitMQ 在具体实际中发现的问题: 为保障业务高可用应用多套集群进行物理隔离,多套集群无对立平台进行治理。原生RabbitMQ客户端应用集群地址连贯,应用多套集群时业务须要关怀集群地址,应用凌乱。原生RabbitMQ仅有简略的用户名/明码验证,不对应用的业务利用方进行鉴权,不同业务容易混用exchange/queue信息,造成业务利用应用异样。应用的业务利用方较多,无平台保护音讯发送方、生产方的关联信息,多个版本迭代后无奈确定对接方。客户端有限流,业务突发异样流量冲击甚至击垮集群。客户端无异样音讯重发策略,须要应用方实现。集群呈现内存溢出等造成集群阻塞时无奈疾速主动转移到其它可用集群。应用镜像队列,队列的master节点会落在具体某个节点上,在集群队列数较多时,容易呈现节点负载不平衡的状况。RabbitMQ无队列主动均衡能力,在队列较多时容易呈现集群节点负载不均问题。二、整体架构 1、MQ-Portal--反对利用应用申请过往业务团队实用RabbitMQ时,利用申请的流量以及对接的利用等信息都在线下表格记录,较为零散,更新不及时,无奈精确理解业务以后实在的应用状况,因而通过一个接入申请的流程可视化、平台化建设利用应用的元数据信息。 通过MQ-Portal的申请流程(如上图),确定了音讯发送利用、生产利用、应用exchange/queue、发送流量等信息应用申请提交后将进入vivo外部工单流程进行审批。 工单流程审批通过后,通过工单的接口回调,调配利用具体应用的集群,并在集群上创立exchange/queue曾经绑定关系。 因为采纳多集群物理隔离的形式保障业务在正式环境的高可用,无奈简略通过一个exchange/queue的名称定位到应用的集群。 每一个exchange/queue与集群之间通过惟一的一对rmq.topic.key与rmq.secret.key进行关联,这样SDK启动过程中即可定位到具体应用的集群。 rmq.topic.key与rmq.secret.key将在工单的回调接口中进行调配。 2、客户端SDK能力概述客户端SDK基于spring-message和spring-rabbit进行封装,并在此基础上提供了利用应用鉴权、集群寻址、客户端限流、生产生产重置、阻塞转移等能力。 2.1、利用应用鉴权开源RabbitMQ仅通过用户名明码的形式判断是否容许连贯集群,然而利用是否容许应用exchange/queue是未进行校验的。 为了防止不同业务混用exchange/queue,须要对利用进行应用鉴权。 利用鉴权由SDK和MQ-NameServer协同实现。 利用启动时首先会上报利用配置的rmq.topic.key信息到MQ-NameServer,由MQ-NameServer判断应用利用与申请利用是否统一,并且在SDK发送音讯过程中还会进行二次校验。 /** * 发送前校验,并且获取真正的发送factory,这样业务能够申明多个, * 然而用其中一个bean就能够发送所有的音讯,并且不会导致任何异样 * @param exchange 校验参数 * @return 发送工厂*/public AbstractMessageProducerFactory beforeSend(String exchange) { if(closed || stopped){ //上下文曾经敞开抛出异样,阻止持续发送,缩小发送临界状态数据 throw new RmqRuntimeException(String.format("producer sending message to exchange %s has closed, can't send message", this.getExchange())); } if (exchange.equals(this.exchange)){ return this; } if (!VIVO_RMQ_AUTH.isAuth(exchange)){ throw new VivoRmqUnAuthException(String.format("发送topic校验异样,请勿向无权限exchange %s 发送数据,发送失败", exchange)); } //获取真正的发送的bean,防止发送谬误 return PRODUCERS.get(exchange);}2.2、集群寻址前文说过,利用应用RabbitMQ严格依照集群的负载状况和业务流量进行集群的调配,因而具体某个利用应用的的不同的exchange/queue可能是调配在不同的集群上的。 ...

October 26, 2020 · 1 min · jiezi

关于rabbitmq:RabbitMQ2-死信队列延迟队列优先队列

1. 前言在《RabbitMQ(1)-根底开发利用》中,咱们曾经介绍了RabbitMQ的根底开发利用。本文基于这些根底再做一些扩大,延长出一些高级的用法,如:死信队列、提早队列和优先队列。不过还是以死信队列为主,因为提早队列是死信队列的衍生概念,而且优先队列也比较简单,所以先还是在代码层面上,把死信队列搞透。 1.1. 创立队列、交换机咱们在应用RabbitMQ之前,须要先创立好相干的队列和交换机,并且设置一些绑定关系。因为几篇文章都是联合springboot来开发,上面就联合springboot介绍几种创立形式: 间接拜访 RabbitMQ Management 治理页面,在页面上创立;或者应用 RabbitMQ其余的客户端来创立治理。在springboot上基于生产端开发时,@RabbitListener 注解的 bindings属性,能够简略实现相似性能。@RabbitListener(bindings = @QueueBinding( value = @Queue(value = "direct.queue.d", durable = "true"), exchange = @Exchange(value = "direct.exchange.a", durable = "true", type = ExchangeTypes.DIRECT, ignoreDeclarationExceptions = "true"), key = "direct.routingKey.a" ) )在配置类下定义@Bean,即向Ioc容器中注册Queue、Exchange、Binding的实例。package pers.kerry.exercise.rabbitmq.rabbitmqproducera.config;import org.springframework.amqp.core.*;import org.springframework.amqp.rabbit.connection.ConnectionFactory;import org.springframework.amqp.rabbit.core.RabbitTemplate;import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;/** * @description: * @date: 2020/7/12 11:26 下午 * @author: kerry */@Configurationpublic class RabbitConfig { public static final String NORMAL_EXCHANGE_A="demo.direct.exchange.a"; public static final String NORMAL_ROUTING_KEY_A="demo.direct.routingKey.a"; public static final String NORMAL_QUEUE_A="demo.direct.queue.a"; /** * NORMAL 交换机 * @return */ @Bean public Exchange ExchangeA(){ return ExchangeBuilder .directExchange(NORMAL_EXCHANGE_A) .durable(true) .build(); } /** * NORMAL 队列 * @return */ @Bean public Queue QueueA(){ return QueueBuilder .durable(NORMAL_QUEUE_A) .build(); } /** * 绑定 NORMAL队列 和 NORMAL交换机 * @return */ @Bean public Binding normalBinding(){ return new Binding(NORMAL_QUEUE_A, Binding.DestinationType.QUEUE, NORMAL_EXCHANGE_A, NORMAL_ROUTING_KEY_A, null); }}我集体举荐第三种,而且倡议是在生产者端定义,消费者应该更关注生产的逻辑。然而如果用代码来创立,有一个很大的毛病,就是不能删除和批改,至多我目前还没找到方法。 ...

October 7, 2020 · 3 min · jiezi

关于rabbitmq:RabbitMQ-05-主题模式RPC模式

5.主题模式在路由模式中,应用Direct交换机,从而能够选择性接管日志。 尽管应用Direct交换机改良了咱们的零碎,但它不能基于多个规范进行路由。 这是不足灵活性的,要在日志零碎中实现这一点,咱们须要理解更简单的Topic交换机。 主题交换机 Topic exchange发送到Topic交换机的音讯,它的的routingKey,必须是由点分隔的多个单词。单词能够是任何货色,但通常是与音讯相干的一些个性。 routingKey能够有任意多的单词,最多255个字节。 bindingKey也必须采纳雷同的模式。Topic交换机的逻辑与直连交换机相似——应用特定routingKey发送的音讯将被传递到所有应用匹配bindingKey绑定的队列。bindingKey有两个重要的非凡点: * 能够通配单个单词。# 能够通配零个或多个单词。如图所示: 如上图中,将routingKey设置为"quick.orange.rabbit"的音讯将被发送到两个队列。音讯 "lazy.orange.elephant“也发送到它们两个。另外”quick.orange.fox“只会发到第一个队列,”lazy.brown.fox“只发给第二个。”lazy.pink.rabbit“将只被传递到第二个队列一次,即便它匹配两个绑定。”quick.brown.fox"不匹配任何绑定,因而将被抛弃。 生产者public class Test1 { public static void main(String[] args) throws Exception { ConnectionFactory f = new ConnectionFactory(); f.setHost("192.168.64.140"); f.setPort(5672); f.setUsername("admin"); f.setPassword("admin"); Connection c = f.newConnection(); Channel ch = c.createChannel(); //参数1: 交换机名 //参数2: 交换机类型 ch.exchangeDeclare("topic_logs", BuiltinExchangeType.TOPIC); while (true) { System.out.print("输出音讯: "); String msg = new Scanner(System.in).nextLine(); if ("exit".contentEquals(msg)) { break; } System.out.print("输出routingKey: "); String routingKey = new Scanner(System.in).nextLine(); //参数1: 交换机名 //参数2: routingKey, 路由键,这里咱们用日志级别,如"error","info","warning" //参数3: 其余配置属性 //参数4: 公布的音讯数据 ch.basicPublish("topic_logs", routingKey, null, msg.getBytes()); System.out.println("音讯已发送: "+routingKey+" - "+msg); } c.close(); }}消费者public class Test2 { public static void main(String[] args) throws Exception { ConnectionFactory f = new ConnectionFactory(); f.setHost("192.168.64.140"); f.setUsername("admin"); f.setPassword("admin"); Connection c = f.newConnection(); Channel ch = c.createChannel(); ch.exchangeDeclare("topic_logs", BuiltinExchangeType.TOPIC); //主动生成对列名, //非长久,独占,主动删除 String queueName = ch.queueDeclare().getQueue(); System.out.println("输出bindingKey,用空格隔开:"); String[] a = new Scanner(System.in).nextLine().split("\\s"); //把该队列,绑定到 topic_logs 交换机 //容许应用多个 bindingKey for (String bindingKey : a) { ch.queueBind(queueName, "topic_logs", bindingKey); } System.out.println("期待接收数据"); //收到音讯后用来解决音讯的回调对象 DeliverCallback callback = new DeliverCallback() { @Override public void handle(String consumerTag, Delivery message) throws IOException { String msg = new String(message.getBody(), "UTF-8"); String routingKey = message.getEnvelope().getRoutingKey(); System.out.println("收到: "+routingKey+" - "+msg); } }; //消费者勾销时的回调对象 CancelCallback cancel = new CancelCallback() { @Override public void handle(String consumerTag) throws IOException { } }; ch.basicConsume(queueName, true, callback, cancel); }}6.RPC模式该模式不常应用,也较为简单,理解即可.RPC模式顾名思义也就是近程调用模式. ...

September 30, 2020 · 1 min · jiezi