1. java 原生客户端问题总结
在这一篇中,我们将使用java原生客户端,来验证我们的一些猜想。
2. 如果服务器存在了交换机,客户端还可以创建?
不知道大家有没有关心过,之前,我们在编写代码时,生产者或者消费者里面都有创建交换机的代码。
我们通过启动代码,向rabbitMQ服务器中创建了一个交换机。
如果这个交换机是持久化的,那么我们关闭代码,这个交换机依旧在rabbitMQ服务器上存在。
这时候,我们再重新启动代码,相当于我们要重新创建一次交换机。
这时候会发生什么事情?
会报错?
还是会重新创建一个同名的Exchange?
还是说复用rabbitMQ服务器上已经存在的Exchange?
如果我们第二次启动前,更改了这个同名Exchange的属性,比如之前是持久化的,现在改为暂时的,又会出现什么情况?
下来我们测试一下。
rabbitMQ.demo05.RabbitMqConstants
public class RabbitMqConstants {
// 交换机名称
public static final String EXCHANGE_NAME = "create_exchange_01";
// 队列名称
public static final String QUEUE_NAME = "create_queue_01";
// 路由键名称
public static final String ROUTING_KEY_NAME = "create_routing_key_01";
}
rabbitMQ.demo05.ExchangeCreator
package rabbitMQ.demo05;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import java.io.IOException;
import java.util.concurrent.TimeoutException;
// 创建 Exchange
public class ExchangeCreator {
public static void main(String[] args) throws IOException, TimeoutException {
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("127.0.0.1");
Connection connection = connectionFactory.newConnection();
Channel channel = connection.createChannel();
// 创建一个交换机,direct类型,非持久化、非内部交换机、非连接独占、空参数
channel.exchangeDeclare(RabbitMqConstants.EXCHANGE_NAME, "direct", false, false, false, null);
channel.close();
connection.close();
}
}
通过channel去创建一个名称为 create_exchange_01 的交换机。
运行后观察web端:
发现交换机被成功创建。
我们再次运行上面的程序,发现程序依旧能成功运行。
我们尝试修改下上面Exchange的属性,比如将非持久化改为持久化:
channel.exchangeDeclare(RabbitMqConstants.EXCHANGE_NAME, "direct", true, false, false, null);
然后重新运行:
C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\bin\java.exe "-javaagent:C:\D\soft\soft_application\onlyou-app\intellij-idea\IntelliJ IDEA 2018.2.5\lib\idea_rt.jar=63244:C:\D\soft\soft_application\onlyou-app\intellij-idea\IntelliJ IDEA 2018.2.5\bin" -Dfile.encoding=UTF-8 -classpath C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\charsets.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\deploy.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\ext\access-bridge-64.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\ext\cldrdata.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\ext\dnsns.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\ext\jaccess.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\ext\jfxrt.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\ext\localedata.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\ext\nashorn.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\ext\sunec.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\ext\sunjce_provider.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\ext\sunmscapi.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\ext\sunpkcs11.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\ext\zipfs.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\javaws.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\jce.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\jfr.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\jfxswt.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\jsse.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\management-agent.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\plugin.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\resources.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\rt.jar;C:\D\gitsource\zhaoehcode-java\rabbitmq-java\target\classes;C:\D\soft\soft_application\maven\repo\com\rabbitmq\amqp-client\3.6.5\amqp-client-3.6.5.jar rabbitMQ.demo05.ExchangeCreator
Exception in thread "main" java.io.IOException
at com.rabbitmq.client.impl.AMQChannel.wrap(AMQChannel.java:105)
at com.rabbitmq.client.impl.AMQChannel.wrap(AMQChannel.java:101)
at com.rabbitmq.client.impl.AMQChannel.exnWrappingRpc(AMQChannel.java:123)
at com.rabbitmq.client.impl.ChannelN.exchangeDeclare(ChannelN.java:702)
at com.rabbitmq.client.impl.ChannelN.exchangeDeclare(ChannelN.java:60)
at rabbitMQ.demo05.ExchangeCreator.main(ExchangeCreator.java:32)
Caused by: com.rabbitmq.client.ShutdownSignalException: channel error; protocol method: #method<channel.close>(reply-code=406, reply-text=PRECONDITION_FAILED - inequivalent arg 'durable' for exchange 'create_exchange_01' in vhost '/': received 'true' but current is 'false', class-id=40, method-id=10)
at com.rabbitmq.utility.ValueOrException.getValue(ValueOrException.java:66)
at com.rabbitmq.utility.BlockingValueOrException.uninterruptibleGetValue(BlockingValueOrException.java:32)
at com.rabbitmq.client.impl.AMQChannel$BlockingRpcContinuation.getReply(AMQChannel.java:360)
at com.rabbitmq.client.impl.AMQChannel.privateRpc(AMQChannel.java:225)
at com.rabbitmq.client.impl.AMQChannel.exnWrappingRpc(AMQChannel.java:117)
... 3 more
Caused by: com.rabbitmq.client.ShutdownSignalException: channel error; protocol method: #method<channel.close>(reply-code=406, reply-text=PRECONDITION_FAILED - inequivalent arg 'durable' for exchange 'create_exchange_01' in vhost '/': received 'true' but current is 'false', class-id=40, method-id=10)
at com.rabbitmq.client.impl.ChannelN.asyncShutdown(ChannelN.java:483)
at com.rabbitmq.client.impl.ChannelN.processAsync(ChannelN.java:320)
at com.rabbitmq.client.impl.AMQChannel.handleCompleteInboundCommand(AMQChannel.java:143)
at com.rabbitmq.client.impl.AMQChannel.handleFrame(AMQChannel.java:90)
at com.rabbitmq.client.impl.AMQConnection$MainLoop.run(AMQConnection.java:559)
at java.lang.Thread.run(Thread.java:745)
我们惊奇的发现,启动报错了。
下面是关键的报错信息:
inequivalent arg 'durable' for exchange 'create_exchange_01' in vhost '/': received 'true' but current is 'false', class-id=40, method-id=10)
翻译下就是:对虚拟机 / 中的交换机 create_exchange_01 而言有一个不等价的参数 durable :接收到的是true,但是最近运行的是 false。
所以说,当我们尝试在rabbitMQ服务器上重复创建同名的交换机时,它底层复用的是服务器上已经存在的交换机。如果我们的代码修改了Exchange的属性,然后尝试重新创建,这时候就会报错,因为你尝试修改一个服务器上已经存在的交换机属性,这是不被允许的。
3. 如果重复创建同名的Queue呢?
下来我们以同样的方式测试下Queue。
rabbitMQ.demo05.QueueCreator
package rabbitMQ.demo05;
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 QueueCreator {
public static void main(String[] args) throws IOException, TimeoutException {
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("127.0.0.1");
Connection connection = connectionFactory.newConnection();
Channel channel = connection.createChannel();
// 创建一个名称为 create_queue_01 的队列,非持久化、非连接独占、非自动阐述、空参数
channel.queueDeclare(RabbitMqConstants.QUEUE_NAME, false, false, false, null);
channel.close();
connection.close();
}
}
运行程序后,观察web端:
发现队列 create_queue_01 已经被重新创建。
我们重复运行上面的代码,发现正常运行。
当我们修改了上面队列的属性后:
channel.queueDeclare(RabbitMqConstants.QUEUE_NAME, true, false, false, null);
我们将队列的非连接独占,修改为true,重启后报错了。
C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\bin\java.exe "-javaagent:C:\D\soft\soft_application\onlyou-app\intellij-idea\IntelliJ IDEA 2018.2.5\lib\idea_rt.jar=63607:C:\D\soft\soft_application\onlyou-app\intellij-idea\IntelliJ IDEA 2018.2.5\bin" -Dfile.encoding=UTF-8 -classpath C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\charsets.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\deploy.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\ext\access-bridge-64.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\ext\cldrdata.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\ext\dnsns.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\ext\jaccess.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\ext\jfxrt.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\ext\localedata.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\ext\nashorn.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\ext\sunec.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\ext\sunjce_provider.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\ext\sunmscapi.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\ext\sunpkcs11.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\ext\zipfs.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\javaws.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\jce.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\jfr.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\jfxswt.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\jsse.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\management-agent.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\plugin.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\resources.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\rt.jar;C:\D\gitsource\zhaoehcode-java\rabbitmq-java\target\classes;C:\D\soft\soft_application\maven\repo\com\rabbitmq\amqp-client\3.6.5\amqp-client-3.6.5.jar rabbitMQ.demo05.QueueCreator
Exception in thread "main" java.io.IOException
at com.rabbitmq.client.impl.AMQChannel.wrap(AMQChannel.java:105)
at com.rabbitmq.client.impl.AMQChannel.wrap(AMQChannel.java:101)
at com.rabbitmq.client.impl.AMQChannel.exnWrappingRpc(AMQChannel.java:123)
at com.rabbitmq.client.impl.ChannelN.queueDeclare(ChannelN.java:843)
at com.rabbitmq.client.impl.ChannelN.queueDeclare(ChannelN.java:60)
at rabbitMQ.demo05.QueueCreator.main(QueueCreator.java:32)
Caused by: com.rabbitmq.client.ShutdownSignalException: channel error; protocol method: #method<channel.close>(reply-code=405, reply-text=RESOURCE_LOCKED - cannot obtain exclusive access to locked queue 'create_queue_01' in vhost '/'. It could be originally declared on another connection or the exclusive property value does not match that of the original declaration., class-id=50, method-id=10)
at com.rabbitmq.utility.ValueOrException.getValue(ValueOrException.java:66)
at com.rabbitmq.utility.BlockingValueOrException.uninterruptibleGetValue(BlockingValueOrException.java:32)
at com.rabbitmq.client.impl.AMQChannel$BlockingRpcContinuation.getReply(AMQChannel.java:360)
at com.rabbitmq.client.impl.AMQChannel.privateRpc(AMQChannel.java:225)
at com.rabbitmq.client.impl.AMQChannel.exnWrappingRpc(AMQChannel.java:117)
... 3 more
Caused by: com.rabbitmq.client.ShutdownSignalException: channel error; protocol method: #method<channel.close>(reply-code=405, reply-text=RESOURCE_LOCKED - cannot obtain exclusive access to locked queue 'create_queue_01' in vhost '/'. It could be originally declared on another connection or the exclusive property value does not match that of the original declaration., class-id=50, method-id=10)
at com.rabbitmq.client.impl.ChannelN.asyncShutdown(ChannelN.java:483)
at com.rabbitmq.client.impl.ChannelN.processAsync(ChannelN.java:320)
at com.rabbitmq.client.impl.AMQChannel.handleCompleteInboundCommand(AMQChannel.java:143)
at com.rabbitmq.client.impl.AMQChannel.handleFrame(AMQChannel.java:90)
at com.rabbitmq.client.impl.AMQConnection$MainLoop.run(AMQConnection.java:559)
at java.lang.Thread.run(Thread.java:745)
重要信息是:
cannot obtain exclusive access to locked queue 'create_queue_01' in vhost '/'. It could be originally declared on another connection or the exclusive property value does not match that of the original declaration., class-id=50, method-id=10)
无法获得对虚拟主机“/”中锁定队列“create_queue_01”的独占访问权限。 它最初可能是在另一个连接上声明的,或者独占属性值与原始声明的不匹配。(class-id=50,method-id=10)
即我们这次尝试启动创建的同名队列的属性和原始的不匹配。
由此可见,对于队列而言,也是相同的原理。
因此,当我们修改了同名队列的属性值,启动将报错,这是不被允许的。
4. 如果重复创建重复的绑定呢?
rabbitMQ.demo05.BindingCreator
package rabbitMQ.demo05;
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 BindingCreator {
public static void main(String[] args) throws IOException, TimeoutException {
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("127.0.0.1");
Connection connection = connectionFactory.newConnection();
Channel channel = connection.createChannel();
// 创建一个binding,将之前创建的queue和exchange通过routing key进行绑定
channel.queueBind(RabbitMqConstants.QUEUE_NAME, RabbitMqConstants.EXCHANGE_NAME, RabbitMqConstants.ROUTING_KEY_NAME, null);
channel.close();
connection.close();
}
}
运行程序后,观察web端:
发现之前创建的queue和exchange通过routing key成功绑定了。
我们再运行一次,发现代码成功运行,绑定关系也没有发生变化。
我们修改下routing key,然后重新运行:
package rabbitMQ.demo05;
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 BindingCreator {
public static void main(String[] args) throws IOException, TimeoutException {
ConnectionFactory connectionFactory = new ConnectionFactory();
connectionFactory.setHost("127.0.0.1");
Connection connection = connectionFactory.newConnection();
Channel channel = connection.createChannel();
// 创建一个binding,将之前创建的queue和exchange通过routing key进行绑定
channel.queueBind(RabbitMqConstants.QUEUE_NAME, RabbitMqConstants.EXCHANGE_NAME, RabbitMqConstants.ROUTING_KEY_NAME, null);
// 搞一个新的routing key去创建绑定关系
channel.queueBind(RabbitMqConstants.QUEUE_NAME, RabbitMqConstants.EXCHANGE_NAME, "create_routing_key_02", null);
channel.close();
connection.close();
}
}
观察控制台:
发现新的rouging key创建的绑定关系也成功创建了,而且重复的绑定关系也是复用服务器上已有的绑定。
接下来我们在创建一个绑定关系,尝试绑定一个不存在Exchange和存在的Queue.
// 创建一个binding,将之前创建的queue和exchange通过routing key进行绑定
channel.queueBind(RabbitMqConstants.QUEUE_NAME, RabbitMqConstants.EXCHANGE_NAME, RabbitMqConstants.ROUTING_KEY_NAME, null);
// 搞一个新的routing key去创建绑定关系
channel.queueBind(RabbitMqConstants.QUEUE_NAME, RabbitMqConstants.EXCHANGE_NAME, "create_routing_key_02", null);
// 创建一个关系,一个不存在Exchange和一个存在的queue
channel.queueBind(RabbitMqConstants.QUEUE_NAME, "create_exchange_02", "create_routing_key_02", null);
启动发现报错了:
C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\bin\java.exe "-javaagent:C:\D\soft\soft_application\onlyou-app\intellij-idea\IntelliJ IDEA 2018.2.5\lib\idea_rt.jar=63849:C:\D\soft\soft_application\onlyou-app\intellij-idea\IntelliJ IDEA 2018.2.5\bin" -Dfile.encoding=UTF-8 -classpath C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\charsets.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\deploy.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\ext\access-bridge-64.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\ext\cldrdata.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\ext\dnsns.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\ext\jaccess.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\ext\jfxrt.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\ext\localedata.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\ext\nashorn.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\ext\sunec.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\ext\sunjce_provider.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\ext\sunmscapi.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\ext\sunpkcs11.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\ext\zipfs.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\javaws.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\jce.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\jfr.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\jfxswt.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\jsse.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\management-agent.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\plugin.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\resources.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\rt.jar;C:\D\gitsource\zhaoehcode-java\rabbitmq-java\target\classes;C:\D\soft\soft_application\maven\repo\com\rabbitmq\amqp-client\3.6.5\amqp-client-3.6.5.jar rabbitMQ.demo05.BindingCreator
Exception in thread "main" java.io.IOException
at com.rabbitmq.client.impl.AMQChannel.wrap(AMQChannel.java:105)
at com.rabbitmq.client.impl.AMQChannel.wrap(AMQChannel.java:101)
at com.rabbitmq.client.impl.AMQChannel.exnWrappingRpc(AMQChannel.java:123)
at com.rabbitmq.client.impl.ChannelN.queueBind(ChannelN.java:944)
at com.rabbitmq.client.impl.ChannelN.queueBind(ChannelN.java:60)
at rabbitMQ.demo05.BindingCreator.main(BindingCreator.java:35)
Caused by: com.rabbitmq.client.ShutdownSignalException: channel error; protocol method: #method<channel.close>(reply-code=404, reply-text=NOT_FOUND - no exchange 'create_exchange_02' in vhost '/', class-id=50, method-id=20)
at com.rabbitmq.utility.ValueOrException.getValue(ValueOrException.java:66)
at com.rabbitmq.utility.BlockingValueOrException.uninterruptibleGetValue(BlockingValueOrException.java:32)
at com.rabbitmq.client.impl.AMQChannel$BlockingRpcContinuation.getReply(AMQChannel.java:360)
at com.rabbitmq.client.impl.AMQChannel.privateRpc(AMQChannel.java:225)
at com.rabbitmq.client.impl.AMQChannel.exnWrappingRpc(AMQChannel.java:117)
... 3 more
Caused by: com.rabbitmq.client.ShutdownSignalException: channel error; protocol method: #method<channel.close>(reply-code=404, reply-text=NOT_FOUND - no exchange 'create_exchange_02' in vhost '/', class-id=50, method-id=20)
at com.rabbitmq.client.impl.ChannelN.asyncShutdown(ChannelN.java:483)
at com.rabbitmq.client.impl.ChannelN.processAsync(ChannelN.java:320)
at com.rabbitmq.client.impl.AMQChannel.handleCompleteInboundCommand(AMQChannel.java:143)
at com.rabbitmq.client.impl.AMQChannel.handleFrame(AMQChannel.java:90)
at com.rabbitmq.client.impl.AMQConnection$MainLoop.run(AMQConnection.java:559)
at java.lang.Thread.run(Thread.java:745)
关键报错信息如下:
no exchange 'create_exchange_02' in vhost '/', class-id=50, method-id=20)
也就是我们创建binding时,要求exchange必须存在,否则报错。
接下来在创建一个绑定关系,去绑定一个存在的Exchange和一个不存在的Queue.
// 创建一个binding,将之前创建的queue和exchange通过routing key进行绑定
channel.queueBind(RabbitMqConstants.QUEUE_NAME, RabbitMqConstants.EXCHANGE_NAME, RabbitMqConstants.ROUTING_KEY_NAME, null);
// 搞一个新的routing key去创建绑定关系
channel.queueBind(RabbitMqConstants.QUEUE_NAME, RabbitMqConstants.EXCHANGE_NAME, "create_routing_key_02", null);
// 创建一个关系,一个不存在Exchange和一个存在的queue
// channel.queueBind(RabbitMqConstants.QUEUE_NAME, "create_exchange_02", "create_routing_key_02", null);
// 创建一个关系,一个存在的Exchange和一个不存在的Queue
channel.queueBind("create_queue_02", RabbitMqConstants.EXCHANGE_NAME, "create_routing_key_02", null);
启动发现同样报错:
C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\bin\java.exe "-javaagent:C:\D\soft\soft_application\onlyou-app\intellij-idea\IntelliJ IDEA 2018.2.5\lib\idea_rt.jar=63898:C:\D\soft\soft_application\onlyou-app\intellij-idea\IntelliJ IDEA 2018.2.5\bin" -Dfile.encoding=UTF-8 -classpath C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\charsets.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\deploy.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\ext\access-bridge-64.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\ext\cldrdata.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\ext\dnsns.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\ext\jaccess.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\ext\jfxrt.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\ext\localedata.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\ext\nashorn.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\ext\sunec.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\ext\sunjce_provider.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\ext\sunmscapi.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\ext\sunpkcs11.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\ext\zipfs.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\javaws.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\jce.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\jfr.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\jfxswt.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\jsse.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\management-agent.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\plugin.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\resources.jar;C:\D\soft\soft_application\jdk\jdk_window\jdk1.8\jre\lib\rt.jar;C:\D\gitsource\zhaoehcode-java\rabbitmq-java\target\classes;C:\D\soft\soft_application\maven\repo\com\rabbitmq\amqp-client\3.6.5\amqp-client-3.6.5.jar rabbitMQ.demo05.BindingCreator
Exception in thread "main" java.io.IOException
at com.rabbitmq.client.impl.AMQChannel.wrap(AMQChannel.java:105)
at com.rabbitmq.client.impl.AMQChannel.wrap(AMQChannel.java:101)
at com.rabbitmq.client.impl.AMQChannel.exnWrappingRpc(AMQChannel.java:123)
at com.rabbitmq.client.impl.ChannelN.queueBind(ChannelN.java:944)
at com.rabbitmq.client.impl.ChannelN.queueBind(ChannelN.java:60)
at rabbitMQ.demo05.BindingCreator.main(BindingCreator.java:38)
Caused by: com.rabbitmq.client.ShutdownSignalException: channel error; protocol method: #method<channel.close>(reply-code=404, reply-text=NOT_FOUND - no queue 'create_queue_02' in vhost '/', class-id=50, method-id=20)
at com.rabbitmq.utility.ValueOrException.getValue(ValueOrException.java:66)
at com.rabbitmq.utility.BlockingValueOrException.uninterruptibleGetValue(BlockingValueOrException.java:32)
at com.rabbitmq.client.impl.AMQChannel$BlockingRpcContinuation.getReply(AMQChannel.java:360)
at com.rabbitmq.client.impl.AMQChannel.privateRpc(AMQChannel.java:225)
at com.rabbitmq.client.impl.AMQChannel.exnWrappingRpc(AMQChannel.java:117)
... 3 more
Caused by: com.rabbitmq.client.ShutdownSignalException: channel error; protocol method: #method<channel.close>(reply-code=404, reply-text=NOT_FOUND - no queue 'create_queue_02' in vhost '/', class-id=50, method-id=20)
at com.rabbitmq.client.impl.ChannelN.asyncShutdown(ChannelN.java:483)
at com.rabbitmq.client.impl.ChannelN.processAsync(ChannelN.java:320)
at com.rabbitmq.client.impl.AMQChannel.handleCompleteInboundCommand(AMQChannel.java:143)
at com.rabbitmq.client.impl.AMQChannel.handleFrame(AMQChannel.java:90)
at com.rabbitmq.client.impl.AMQConnection$MainLoop.run(AMQConnection.java:559)
at java.lang.Thread.run(Thread.java:745)
关键报错信息如下:
no queue 'create_queue_02' in vhost '/', class-id=50, method-id=20)
即不存在这个Queue。
5. 总结同名Exchange,同名Queue,重复Binding的问题
1.通过channel对象就可以创建Exchange、Queue、Binding,而不一定非得发送消息才创建。
2.重复创建同名的Exchange,实际上是复用rabbitMQ服务器上已经存在的Exchange,因此不能够更改Exchange的属性值,否则报错。
3.重复创建同名的Queue,实际上也是复用rabbitMQ服务器上已经存在的Queue,因此不能更改Queue的属性值,否则报错。
4.重复创建Binding,要求Exchange和Queue必须已经存在,否则创建Binding失败。当两者存在的时候,可以使用同一个Routing key反复创建Binding,这时候复用的是服务器上已经存在的Binding;也可以修改为新的Routing key去创建一个新的Binding,这时候相当于新创建了一个绑定关系。
文档信息
- 本文作者:Marshall