smallrye / smallrye-reactive-messaging

SmallRye Reactive Messaging
http://www.smallrye.io/smallrye-reactive-messaging/
Apache License 2.0
235 stars 176 forks source link

Emitter's send method does not NACK messages sent to Apache Artemis broker #2216

Closed enicolaescu closed 1 year ago

enicolaescu commented 1 year ago

I'm facing an issue when using the AMQP connector and an Apache Artemis broker

Problem: I send a message to the broker using an emitter, if the target address does not have a queue the broker will log the error: Couldn't find any bindings for address=random-address on message=AMQPStandardMessage...... The message is never sent to any queue and is lost, but the emitter does not NACK the message nor it reports any error on the quarkus CLI

How to reproduce:

Start the apache artemis container:

docker pull quay.io/artemiscloud/activemq-artemis-broker:artemis.2.27.1
docker run -d -p 8161:8161 -p 61616:61616 -e AMQ_USER=artemis -e AMQ_PASSWORD=artemis -e AMQ_EXTRA_ARGS="--host 0.0.0.0 --http-host 0.0.0.0 --relax-jolokia" quay.io/artemiscloud/activemq-artemis-broker:artemis.2.27.1

The console is accessible at localhost:8161 with credentials artemis/artemis You should also go to JMX -> org.apache.logging.log4j2 -> org.apache.activemq logger and set the log level to DEBUG

Run the message producer: clone https://github.com/quarkusio/quarkus-quickstarts cd .\amqp-quickstart update the properties file .\amqp-quickstart\amqp-quickstart-producer\src\main\resources\application.properties by adding these properties:

amqp-host=localhost
amqp-port=61616
amqp-username=artemis
amqp-password=artemis

mp.messaging.outgoing.quote-requests.connector=smallrye-amqp
mp.messaging.outgoing.quote-requests.address=random-address
mp.messaging.outgoing.quote-requests.durable=true

Run the producer: mvn -f amqp-quickstart-producer quarkus:dev

Now you can send a message to the artemis broker by sending a post request to http://localhost:8080/quotes/request

You could also update the QuotesResource.java class by checking the emitter result like this:

CompletionStage<Void> completionStage = quoteRequestEmitter.send(uuid.toString()); // <2>
completionStage.toCompletableFuture().join();

but it's the same thing, no error is reported

cescoffier commented 1 year ago

I've difficulties to launch the broker:

  1. Wrong architecture for me - it may lead to unexpected issue. Do you know if there are multi-arch images available?

    WARNING: The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested
  2. It fails to launch:

docker logs 584bc0581c11fc532d2f14d119222c4d9f9b5cbfaab82525c033b8ba0a34c5b5
Creating Broker with args --user XXXXX --password XXXXX --role admin --name broker --allow-anonymous --http-host 172.17.0.2 --host 172.17.0.2   --force --host 0.0.0.0 --http-host 0.0.0.0 --relax-jolokia
Cannot initialize queue:Function not implemented

usage: artemis <command> [<args>]

The most commonly used artemis commands are:
    address    Address tools group (create|delete|update|show) (example ./artemis address create)
    browser    It will browse messages on an instance
    check      Check tools group (node|queue) (example ./artemis check node)
    consumer   It will consume messages from an instance
    create     creates a new broker instance
    data       data tools group (print|recover) (example ./artemis data print)
    help       Display help information
    mask       mask a password and print it out
    perf       Perf tools group (example ./artemis perf client)
    producer   It will send messages to an instance
    queue      Queue tools group (create|delete|update|stat|purge) (example ./artemis queue create)
    transfer   Moves Messages from one destination towards another destination
    upgrade    Update an artemis instance to the current artemis.home, keeping all the data and broker.xml. Warning: backup your instance before using this command and compare the files.
    version    print version information

See 'artemis help <command>' for more information on a specific command.

Running Broker
/opt/amq/bin/launch.sh: line 47: /home/jboss/broker/bin/artemis: No such file or directory
enicolaescu commented 1 year ago

@cescoffier I'm not sure I can help with your platform, I read that one possible solution might be adding the "--nio" flag to AMQ_EXTRA_ARGS like this:

AMQ_EXTRA_ARGS: "--nio --host 0.0.0.0 --http-host 0.0.0.0 --relax-jolokia"

I have also realized I made an error in the docker run, it should be AMQ_EXTRA_ARGS="..." with the equal sign, not the colon

cescoffier commented 1 year ago

Thanks, I was able to start the broker.

Unfortunately, the broker "accept" the message (we receive an acknowledgment of type ACCEPTED) - so we don't see the problem on the client side. So, the emitter does not nack, because the broker accepted the message.

I can see only one way to work around this. We could use a job that ensures queues/addresses are created before running the application. I'm currently trying to do that for Kafka, but that would work here, too (when deployed on kubernetes).

enicolaescu commented 1 year ago

Thanks for checking, could you tell me how did you check the acknowledgement? I assume you enabled DEBUG logging for a specific vert.x package?

I have been working with AMQP and brokers for a short time, but I wouldn't expect a broker to just acknowledge a message and then silently destroy it. Do other brokers also have this behavior?

In the end I tried the JMS connector instead with the artemis jms client and it appears to have the behavior I expected, with the application failing at startup if the queue/address doesn't exist and also failing at runtime if I try sending a message to a queue/address that doesn't exist

cescoffier commented 1 year ago

Exactly, I debugged the sendAndAck method.

It works with JMS because JMS expects the message to be consumed , and only acked when this is done. The amqp connector follows the amqp semantic - which is to let the broker accept/reject... the message.