Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Producer fails if exchange is durable #281

Open
gvmw opened this issue Nov 29, 2021 · 11 comments
Open

Producer fails if exchange is durable #281

gvmw opened this issue Nov 29, 2021 · 11 comments
Assignees

Comments

@gvmw
Copy link

gvmw commented Nov 29, 2021

I needed a single producer publishing into amq.direct exchange. I do not have any queues or consumers.
I was not expecting this to fail:

pwd
/Users/gerhard/github.com/rabbitmq/rabbitmq-perf-test

make run ARGS="--producers 1 --rate 1 --consumers 0 --exchange amq.direct --auto-delete false --flag persistent"
Main thread caught exception: java.io.IOException
14:57:06.751 [com.rabbitmq.perf.PerfTest.main()] ERROR com.rabbitmq.perf.PerfTest - Main thread caught exception
java.io.IOException: null
	at com.rabbitmq.client.impl.AMQChannel.wrap(AMQChannel.java:129)
	at com.rabbitmq.client.impl.AMQChannel.wrap(AMQChannel.java:125)
	at com.rabbitmq.client.impl.AMQChannel.exnWrappingRpc(AMQChannel.java:147)
	at com.rabbitmq.client.impl.ChannelN.exchangeDeclare(ChannelN.java:783)
	at com.rabbitmq.client.impl.recovery.AutorecoveringChannel.exchangeDeclare(AutorecoveringChannel.java:252)
	at com.rabbitmq.client.impl.recovery.AutorecoveringChannel.exchangeDeclare(AutorecoveringChannel.java:242)
	at com.rabbitmq.client.impl.recovery.AutorecoveringChannel.exchangeDeclare(AutorecoveringChannel.java:222)
	at com.rabbitmq.perf.MulticastParams.createProducer(MulticastParams.java:463)
	at com.rabbitmq.perf.MulticastSet.createProducers(MulticastSet.java:347)
	at com.rabbitmq.perf.MulticastSet.run(MulticastSet.java:186)
	at com.rabbitmq.perf.PerfTest.main(PerfTest.java:388)
	at com.rabbitmq.perf.PerfTest.main(PerfTest.java:508)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:564)
	at org.codehaus.mojo.exec.ExecJavaMojo$1.run(ExecJavaMojo.java:282)
	at java.base/java.lang.Thread.run(Thread.java:832)
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 'amq.direct' in vhost '/': received 'false' but current is 'true', class-id=40, method-id=10)
	at com.rabbitmq.utility.ValueOrException.getValue(ValueOrException.java:66)
	at com.rabbitmq.utility.BlockingValueOrException.uninterruptibleGetValue(BlockingValueOrException.java:36)
	at com.rabbitmq.client.impl.AMQChannel$BlockingRpcContinuation.getReply(AMQChannel.java:502)
	at com.rabbitmq.client.impl.AMQChannel.privateRpc(AMQChannel.java:293)
	at com.rabbitmq.client.impl.AMQChannel.exnWrappingRpc(AMQChannel.java:141)
	... 15 common frames omitted
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 'amq.direct' in vhost '/': received 'false' but current is 'true', class-id=40, method-id=10)
	at com.rabbitmq.client.impl.ChannelN.asyncShutdown(ChannelN.java:517)
	at com.rabbitmq.client.impl.ChannelN.processAsync(ChannelN.java:341)
	at com.rabbitmq.client.impl.AMQChannel.handleCompleteInboundCommand(AMQChannel.java:182)
	at com.rabbitmq.client.impl.AMQChannel.handleFrame(AMQChannel.java:114)
	at com.rabbitmq.client.impl.AMQConnection.readFrame(AMQConnection.java:739)
	at com.rabbitmq.client.impl.AMQConnection.access$300(AMQConnection.java:47)
	at com.rabbitmq.client.impl.AMQConnection$MainLoop.run(AMQConnection.java:666)
	... 1 common frames omitted

How can I configure PerfTest to publish into a durable exchange?

@michaelklishin
Copy link
Member

PerfTest declares it as transient:

PRECONDITION_FAILED - inequivalent arg 'durable' for exchange 'amq.direct' in vhost '/': received 'false' but current is 'true'

@gvmw
Copy link
Author

gvmw commented Nov 29, 2021

That's right. How can PerfTest be configured to declare the exchange as durable?

@michaelklishin
Copy link
Member

I don't see a way. Exchanges are declared like so:

channel.exchangeDeclare(exchangeName, exchangeType);

but you don't have to declare amq.direct, you can avoid this by passing --predeclared since it's always there.

@gvmw
Copy link
Author

gvmw commented Nov 29, 2021

While that is a nice workaround, it is not currently possible to declare a durable exchange with PerfTest. Not sure if we want to add this feature, but it's a limitation that I've hit today.

@acogoluegnes
Copy link
Collaborator

acogoluegnes commented Nov 30, 2021

PerfTest should not try to declare an exchange that starts with amq. anyway, I'll change this.

We can add yet another flag to create durable exchanges. I think it's not there because the durability of exchanges is not critical for benchmarks, but this is not a reason not to add it.

@acogoluegnes acogoluegnes added this to the 2.17.0 milestone Nov 30, 2021
@acogoluegnes acogoluegnes self-assigned this Nov 30, 2021
@acogoluegnes
Copy link
Collaborator

@gerhard any suggestions for the flag?

@gerhard
Copy link
Contributor

gerhard commented Nov 30, 2021

I'm thinking --durable true.

I don't want to make this bigger than it needs to be, but it would make sense if this new flag applied to queues too. --auto-delete true --flag persistent always felt like a long way of achieving this with queues.

@acogoluegnes
Copy link
Collaborator

--durable true (or just --durable I don't remember how PerfTest handles flags off the top of my head) for the whole chain (exchange, queue, messages) is opinionated but handy indeed. Are you sure want to go down this path? :)

@gerhard
Copy link
Contributor

gerhard commented Nov 30, 2021

The presence of the --durable flag will work too.

My use-case is declaring and publishing into a durable exchange. As long as I can do that with PerfTest, I'm good.

The context is knative-extensions/eventing-rabbitmq#522 and the requirement is to generate some load on RabbitMQ that the RabbitmqSource (a Knative Eventing primitive) can consume and send to a Sink (another Knative Eventing primitive) as CloudEvents. While this used to be done differently before I joined - https://github.com/knative-sandbox/eventing-rabbitmq/blob/f36e482a04fcbe91108ce5b984a71e1abe9e6ac9/samples/source/example/simple_producer.go - there is no reason to not use the official benchmarking tool for this purpose. It would also work for this durable Exchange to be declared via https://github.com/rabbitmq/messaging-topology-operator - #282 blocks this - so either option will work.

From a K8s perspective, declaring an Exchange via the topology operator that PerfTest will then use would be ideal, so #282 would be sufficient, but I think that PerfTest should support the declaration of durable exchanges.

Now you have all the context 🙂

@acogoluegnes
Copy link
Collaborator

@gerhard I fixed #281, so it should work in your case, as PerfTest will not try to create the amq.direct exchange. You can try the pivotalrabbitmq/perf-test:dev Docker image, it contains the fix.

@acogoluegnes
Copy link
Collaborator

acogoluegnes commented Nov 30, 2021

Even though it won't help for your case until we decide to change PerfTest behavior in #282, I think we can add the --durable flag if you think it'll help, but we need to define the semantics.

My suggestion is that it does the same as --auto-delete true --flag persistent AND makes PerfTest create everything it creates durable (exchange and queues).

Note the --quorum-queue flag does the same thing as --auto-delete true --flag persistent (queues are durable, messages are persistent).

Basically --auto-delete true and --flag persistent are independent: you can have durable queues and persistent messages without --auto-delete true, and the --durable flag would "reunite" them.

Note also the durable terminology is not clear here, because it applies to resources usually, but we choose here to apply it to the whole chain. Just saying but, we could use --persistent instead (not to be confused with --flag persistent), that would make more sense I think.

@acogoluegnes acogoluegnes removed this from the 2.17.0 milestone Jan 4, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants