1
votes

I'm working in Java with RabbitMQ.
I have two RabbitMQ servers, with same configurations, one is the developing environment and the other one is the production environment.
This is the consumer declaration:

    /*
     * Connection and channel declaration
     */
    ConnectionFactory factory = new ConnectionFactory();
    factory.setUri(prop.getProperty("ConnectionURI"));
    connection = factory.newConnection();
    channel = connection.createChannel();

    /*
     * Queue declaration and exchange binding
     */
    channel.exchangeDeclare(prop.getProperty("printExchange"), "topic", false, false, false, new HashMap<>());
    queueName = prop.getProperty("printQueue");
    routing_key = "print." + codCliente + "." + idCassa;
    channel.queueDeclare(queueName, false, false, false, null);
    channel.queueBind(queueName, prop.getProperty("printExchange"), routing_key);

And here it starts to listen on the queue:

JAyronPOS.LOGGER.info("Waiting for a message on the queue -> " + queueName + " with routingkey -> " + routing_key);
Consumer consumer = new DefaultConsumer(channel) {
    @Override
    public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException {
        JAyronPOS.LOGGER.info("This is the received message -> " + queueName + ": " + new String(body, "UTF-8"));
        Map<String, Object> headers = properties.getHeaders();
        if (envelope.getRoutingKey().equals(routing_key)) {
            JAyronPOS.LOGGER.info("Message is for me, because it has my routing key");
            channel.basicAck(envelope.getDeliveryTag(), false);
            if (headers != null) {
                if (headers.containsKey("command")) {
                    JAyronPOS.LOGGER.info("It's a command!");
                    JAyronPOS.LOGGER.info(headers.get("command").toString());
                    if ("requestClose".equals(headers.get("command").toString())) {
                        ChiusuraFiscaleConfirm confirm = gson.fromJson(new String(body, "UTF-8"), ChiusuraFiscaleConfirm.class);
                        if (confirm.isCanClose()) {
                            eseguiChiusuraFiscale();
                        } else {
                            JOptionPane.showMessageDialog(null, "Can't close", "Error", JOptionPane.ERROR_MESSAGE);
                        }
                    } else {
                        JAyronPOS.LOGGER.info("Can't handle the message");
                    }
                }
            } else {
                System.out.println("It's a ticket");
                TicketWrapper ticket = gson.fromJson(new String(body, "UTF-8"), TicketWrapper.class);
                printTicket(ticket);
            }
        }else{
            JAyronPOS.LOGGER.info("The message isn't for me, because it has the routingkey: "+envelope.getRoutingKey());
        }
    }
};
channel.basicConsume(queueName, false, consumer);

In the development environment, I have max 5 queues, while in the production environment i have between 150-200 queues.
The messages are sent by the exchange, with a personal routing_key. The number of sent messages is not high (no more than 10 msg/s while stressed).
When I test the consumer on the developing environment, everything is OK:
- I send an RPC call, the server process it and reply. The consumer read the reply and call the proper method. All in about 1-2 seconds.
When I use the software in production environment (I change the environment only by commenting/decommenting a line in a config.properties file), it doesn't work:
- I send the RPC call, the server process it and send the reply on the queue. The consumer never receive the message (but I can see the message developed on the queue by the web administration panel).

Which can be the problem?

EDIT: I noticed that if I send the RPC call, in the RabbitMQ web panel, on the reply queue there is a message under "Deliver" (light blue), while if I send 3-4 RPC calls (same of previous one), after some call, on the reply queue there is a message under Publish (yellow), and the consumer receive the reply.

1

1 Answers

0
votes

You haven't provided publish code or topology, so it's hard to guess how your topology works.

But it's bad idea to match routing key on consumer, exchanges should do it for you. Consumer can create and bind queues for required routing keys. In your code else branch in consumer do not acknowledge or reject message, this can cause it to hang in delivered state and never be received by another consumer.

Rabbitmq tutorials have useful RPC section https://www.rabbitmq.com/tutorials/tutorial-six-java.html