Nicolas Verducou
Nicolas Verducou

Reputation: 79

Artemis message routing

I'm using ActiveMQ Artemis 2.17.0 and I'm facing routing issues.

I've implementing a plugin that logs the before message route and I see that some message are routed from topic.private.abc.task.V1 to topic.abc.rawmessage.V1.

There is no divert setup and topic and queue are created dynamically by the producers and consumers. There is a setup to map destination clustered.*.> to virtual topics

private TransportConfiguration getServerTransportConfiguration() {
    Map<String, Object> extraProps = new HashMap<>();
    extraProps.put("virtualTopicConsumerWildcards", "clustered.*.>;2");
    Map<String, Object> params = new HashMap<>();
    params.put("scheme", "tcp");
    params.put("port", port);
    params.put("host", hostname);
    return new TransportConfiguration("org.apache.activemq.artemis.core.remoting.impl.netty.NettyAcceptorFactory", params, "netty-acceptor", extraProps);
}

Both topic.private.abc.task.V1 and topic.abc.rawmessage.V1 are valid topics but they are not supposed to be linked.

What could explain that behavior?

Here is the plugin code:

    @Override
    public void beforeMessageRoute(Message message, RoutingContext context, boolean direct, boolean rejectDuplicates) throws ActiveMQException {
        Map<String, Object> map = new HashMap<>();
        map.put("RoutingContext", new RoutingContextLogView(context));
        logger.info(mapper.writeValueAsString(map));
        ActiveMQServerPlugin.super.beforeMessageRoute(message, context, direct, rejectDuplicates);
    }
public class RoutingContextLogView {
    private RoutingContext routingContext;

    public RoutingContextLogView(RoutingContext routingContext) {
        this.routingContext = routingContext;
    }

    public String getAddress() {
        return routingContext.getAddress() != null ? routingContext.getAddress().toString() : null;
    }

    public String getPreviousAddress() {
        return routingContext.getPreviousAddress() != null ? routingContext.getPreviousAddress().toString() : null;
    }

    public String getRoutingType() {
        return routingContext.getRoutingType() != null ? routingContext.getRoutingType().name() : null;
    }

    public String getPreviousRoutingType() {
        return routingContext.getPreviousRoutingType() != null ? routingContext.getPreviousRoutingType().name() : null;
    }
}

Despite the odd logging the flow followed by the message seems to be OK (i.e. the message is produced to topic.abc.rawmessage.V1 and consumed from topic.abc.rawmessage.V1). I'm just wandering why there is message routing and why the previousAddress in the RoutingContext is wrong.

Upvotes: 0

Views: 388

Answers (1)

Justin Bertram
Justin Bertram

Reputation: 34973

The RoutingContext object, which is used internally by the broker, is reusable. This is done for performance reasons to prevent having to re-create the RoutingContext for every routing operation no matter what. As one might guess, routing messages is a very common operation in the broker so it pays to optimize it as much as possible. Reusing the RoutingContext means fewer objects are created and thrown away which means less garbage needs to be cleaned up which means fewer pauses and better overall performance by the broker.

The fact that the previousAddress is different here from the address where the current message is going to be routed is not a problem. It just means that the context won't be re-used for this routing operation and therefore will be cleared. As the name suggests, the beforeMessageRoute method is invoked before any routing logic is performed (e.g. clearing the RoutingContext). If you inspect the RoutingContext using afterMessageRoute then you should see that it was cleared and populated with the proper details.

Message "sending" and message "routing" (both of which have plugin hooks) are related but distinct operations. A message is "sent" in response to a client operation. Sends always result in a route. However, not all routes are the results of sends. A message can be routed due to internal broker operations which do not involve a send (e.g. moving messages around a cluster, expiring a message, cancelling an undeliverable message to a dead-letter address, using a divert, etc.).

I would caution you against inspecting internal broker state (which can be subtle and nuanced) and assuming a problem exists when everything else indicates that the broker is functioning normally. In this case you said that you were "facing routing issues" and that "some message are routed from topic.private.abc.task.V1 to topic.abc.rawmessage.V1" when, in fact, there was no routing issue and messages were not actually being routed from topic.private.abc.task.V1 to topic.abc.rawmessage.V1. From what I can see everything is in fact functioning normally.

Upvotes: 1

Related Questions