I use activemq with spring boot.
I wanted send topic only to specific subscribers. I know that to achieve it I can specify selectors on JMSListener but this mean that I already sent message to subscriber. What I want to do is to dispatch messages on broker level.
Currently I have below code:
public Broker broker() throws Exception {
BrokerService broker = new BrokerService();
broker.setBrokerName(BROKER_NAME);
broker.addConnector(BROKER_URL);
policy.setTopic(USER_TOPIC);
broker.start();
return broker.getBroker();
}
Let say I have messages which are able to send two subject BOOKS and FOOD.
For subscriber A only BOOKS are available and for subscriber B BOOKS and FOOD.
Question:
Is it possible to achieve it on broker level? If so how. I know that there is something like destination policy but I don't know how to use it :(
Messages can be routed and secured to different topic or queue destinations in a variety of ways:
Separate topics per subscribers (topic://BOOKS, topic://FOOD)
Single topic, but use a message header (topic://EVENTS)
a. Message header "EVENT_TYPE='FOOD'" or "EVENT_TYPE='BOOKS'"
You can secure the destinations so only the 'books' user can subscribe to the topic://BOOKS and only the 'food' user can subscribe to the topic://FOOD
Use a Virtual Topic which is publish to a topic, subscribe to a queue and get the best of all the above. For example publish to: topic://EVENTS and then subscribe from: queue://vConsumer.BOOKS.EVENTS, queue://vConsumer.FOOD.EVENTS
Links:
ActiveMQ Authorization: http://activemq.apache.org/security.html
ActiveMQ Virtual Topics: http://activemq.apache.org/virtual-destinations.html
Related
any body can help me finding how can I send the message to differents queues (depending on business logic) to differents queues in RabbitMQ, using Masstransit
I have read the documentation I didn't found how I can specify the queue destination name
thank you
You might want to read the documentation again. If you want to send to a specific queue, you actually have to send to the exchange for that queue created by MassTransit.
Use the ISendEndpointProvider (or ConsumeContext):
Call await GetSendEndpoint(new Uri("exchange:name")) or await GetSendEndpoint(new Uri("queue:name")) to get the ISendEndpoint.
Call Send(...) to send the message to the exchange or queue.
Is it possible to publish message to a specific client id ?
I want to publish two things using mqtt:
1- General informations like users scores, stats etc ... and can be viewable by everyone.
2- Sensitive informations reserved for private user like own score, name etc ...
Is there any clean way to do it using Paho MQTT ?
By the way, using: https://github.com/eclipse/paho.mqtt.golang
No, with the MQTT protocol messages are published to topics, not clients there can be anywhere between 0 and many clients subscribed to a given topic. Also there is no where in the message header to specify the target client id.
All clients subscribed to a topic will receive all messages published to that topic. But clients can subscribe to any number of topics so there is nothing to stop each client subscribing to a topic general topic and one that includes their clientid as an element in the topic. You can then use topic ACLs to ensure that only the client with the matching client id can subscribe to that topic.
I am thinking how to remove duplicacy for subscriber cluster in pubsub, for example:
There is a service called email, which should send welcome emails after user signing up. By using pub/sub, email service shall listen a event called "signedUp" which will be triggered each time user sign up. However, how about if I have 2 email services to balance? Without any special efforts, I think two welcome emails will be sent out. So how to solve this issue?
I prefer redis as pubsub server for simplicity, or rabbitmq if redis doesn't work out.
I don't think it is possible to do it in redis. But in rabbitmq, it can, let me explain below:
Rabbitmq has a separate stuff called 'exchange' from queue. So server publish a message to exchange, client can create queues to bind to the exchange. Therefore, instances from one services can create the same queue to bind with exchange, by doing that exchange will delivery message to the queue once and handled by only one instance once.
Account service:
channel.assertExchange(‘signedUp’, 'fanout')
channel.publish(ex, '', new Buffer(message)
Email service:
let queue = channmel.assertQueue(‘email’);
channel.bindQueue(queue, 'signedUp'); // bind this queue to exchange
ch.consume(queue, logMessage)
By given a queue name in email service, no matter how many email services started, the published message (signedUp in this case) will be handled by one and ONLY ONE email service.
I am trying to connect from my Android app to one queue called "messages".
The producer (one webservices under AMQP protocol) is already connected, it can be check through RabbitMQ admin panel.
To connect from my Android device I am coding like this.
private void connect() throws Exception {
this.sampleClient = new MqttClient(this.broker, this.clientId);
MqttConnectOptions connOpts = new MqttConnectOptions();
connOpts.setUserName("user");
connOpts.setPassword("user".toCharArray());
/*connOpts.setConnectionTimeout(60 * 10);
connOpts.setKeepAliveInterval(60 * 5);*/
connOpts.setCleanSession(true);
this.sampleClient.connect(connOpts);
this.sampleClient.setCallback(this);
this.sampleClient.subscribe("messages");
if(!this.sampleClient.isConnected()){
System.out.println("Not Connected");
return;
}
System.out.println("Connected");
}
I have tried with "amq.topic", "amq.topic.*", "amq.topic.messages", etc... But when I look in the RabbitMQ queue section "messages" is with 0 consumers, and have been set one new queue called "mqtt-subscription-Sampleqos1" automatically.
What's happening? How can I susbscribe to "messages" queue?
There are two important points about this question.
According with the RabbitMQ MQTT documentation: http://www.rabbitmq.com/mqtt.html
Firstly, every queues are bound automatically to amq.topic exchange by the mqtt-plugin.
Secondly, every subscriber has his own queue which look like this, mqtt-subscription-{cliend_id}{qosX} (where X is the qos level of the subscription)
Therefore, producer must to publish the message to "amq.topic" exchange, and "amq.topic.." routing-key, and receiver must to subscribe to "amq.topic.." routing-key.
First, make sure MQTT plugin is enabled: rabbitmq-plugins enable rabbitmq_mqtt
From the client side (here is you Android app), you need subscriber to a topic, lets say, topic my/android/app/messages
this.sampleClient.subscribe("my/android/app/messages");
Then, from the server side, because of RabbitMQ's implementation, you need send the message to a special exchange 'amq.topic' with appropriate route key my.android.app.messages (notice the mapping between '/' and '.', MQTT use / and AMQP use .). For example if you publish by pika AMQP Python lib, the code will looks like following:
channel.basic_publish(
exchange='amq.topic',
routing_key='my.android.app.messages',
body='hello world'
)
In your case, you want to receive message from queue "messages", basically there is no way to directly subscriber message from that AMQP queue on your MQTT client. The work around is create a service running on your server side, work as AMQP subscriber, receive message from "messages" queue, and transparent forward message to exchange amq.topic with proper routing key.
Hope my answer helpful.
Is it possible to bind a single queue to many topics using RabbitMQ STOMP client?
Each time a client sending SUBSCRIBE frame server creates a new queue for it, it makes usage of "prefetch-count" useless for me, because it applies to each subscription individually.
I am just looking for any way to get messages with many topics in the single queue via RabbitMQ Web-STOMP. Any ideas?
See Documentation:User generated queue names for Topic and Exchange destinations
The header x-queue-name specified queue name should binding to same queue if there exist, but will exist multiple subscription on client.
The different between AMQP and STOMP concept not compatible in some ways.