I am building a website which receives real-time updates about soccer matches. I am using RabbitMQ to send the updates to the clients (JS website and Android/iOS apps).
The clients should only receive real-time updates. In other words, a client should only receive updates when the user is logged in. No history is kept.
To achieve this behavior, I was thinking about the following architecture:
A fanout exchange in RabbitMQ.
Each user has a dedicated queue, which is bound to the exchange. This queue is created when the user account is created.
For these queues, the queue property x-message-ttl with value of 0 is set. See below.
When the user logs in, the client consumes the queue of the corresponding user.
Messages are sent to the exchange by the backend, and forwarded to all queues. When a user is not logged in, the message will be discarded immediately, as x-message-ttl is set to 0.
Is this a correct usage of AMQP/RabbitMQ to achieve real-time notifications?
Yes and no - some of your premises are wrong.
In other words, a client should only receive updates when the user is logged in. When the user is not logged in, simply drop the connection to RMQ and that's it.
Each user has a dedicated queue, which is bound to the exchange. This queue is created when the user account is created. The queue should be created only after the connection to RMQ is established, in that way you are also covering the When a user is not logged in, the message will be discarded immediately part.
No need to set TTL to 0.
Messages are sent to the exchange by the backend, and forwarded to all queues Just to be clear, it's the RabbitMQ that does "forwarding" from exchange to queues.
Related
I am building my application on a microservice model.
Lets says
There is one database on server D1
There is a user service hosted on server U1
There is a notification service on server N1
There is a rabbitmq service on server R1
The notification service publishes a message to the rabbitmq service, which then dispatches the message to the user service, the user service that listens to the rabbitmq service, receives the message and writes some data to the database.
This works perfectly!
The problem is if I scale the user service to another server say U2, meaning the user service is now running on both servers i.e. U1 and U2 (backed by an nginx load balancer) and both the user service now listening to the rabbitmq service, will receive the message dispatched from the notification service and both will write to the database (which I don't want). I want only one of the user service i.e. either U1 or U2 to write the data to the database.
So, i was wondering if rabbitmq can dispatch the message to any one user service instead of both? or am I using a wrong approach altogether?
I think you can use Single Active Consumer option
"Single active consumer allows to have only one consumer at a time consuming from a queue and to fail over to another registered consumer in case the active one is cancelled or dies."
Register U1 and U2 on the same queue
U1 will be registered as Single Active Consumer
If U1 dies/canceled, it will be replaced by U2 as Single Active Consumer, and vice versa
To use this option pass x-single-active-consumer argument when declaring the queue
Please read the documentation for more information.
Reference: RabbitMQ Consumers Single Active Consumer
Is it possible to disallow topic subscriptions to wildcards in ActiveMQ 5 (classic)?
E.g. subscribing to > will broadcast all messages to all consumers even if a consumer should not be able to subscribe to all topics (and isn't even aware of all topics).
I already tried to create <authorizationEntries> with the <authorizationPlugin>, but wasn't able to prohibit wildcard subscription.
Do you have any ideas how to completely wildcard subscription or message forwarding to wildcards for specific / all users?
As hashed out in the comments you are approaching this problem from the wrong direction. Rather than trying to disable wildcard subscriptions the correct approach is to limit what topics will actually be delivered regardless of what is subscribed to.
This is done by setting an appropriate ACL for each user (reusing the same credentials for 500k clients is a REALLY bad idea).
ActiveMQ uses a plugin based system to supply Authentication and Authorisation control based on the Java standard called JAAS. With JAAS you can plug nearly any storage mechanism (e.g. database, LDAP,...) into ActiveMQ to store your user/password details and the ACL of what topics they can access. Details of how to use JAAS with ActiveMQ can be found here
I wrote application which uses GCM topic massaging to receive push notifications from server. Applications works fine on iOS 8.1 but on 9.1 it registers for registerUserNotificationSettings and registerForRemoteNotifications successfully, gets APNs token and GGLInstanceID token successfully, Subscribes to topic successfully. But it doesnt receives messages sent on topics but it does receives messages sent directly to its registration token. I have spent a whole day debugging this but i am unable to reach any conclusion because some times it receives messages when app is running in debug mode but when i make package and transfer ipa file to device it never receives topic messages.
I have few things to be clarified in BlackBerry push client applications. I have developed an push-enabled application which can receive push messages from the sample push initiator application installed on a publicly accessible location (through BIS). I have now run into a question about sending personalized messages to each device. For that matter I need to use subscription API that comes with BlackBerry push SDK. This question is similar to what has been posted here, but it contains no information for me. My questions are,
I used the registration API for BlackBerry client app registration to receive push messages from PPG. It requires only app-ID, device-port and push URL(not push initiator URL). Client app registers itself when the application UI starts up(this is how I register with push API). Is this all I need to do to get a subscription for that client with push initiator or does client need to contact push initiator directly for a subscription?
Why do I need to provide subscribe/unsubscribe URLs in the push initiator application (I don't provide any unsubscribe/subscribe facility in the client push application ) or is there a way to achieve this through application manager/operating system? or do I need to get unsubscribed users from the PushResult object and process them?
How does push initiator come to know about clients initially when there is no mechanism for the push client to subscribe with push initiator?
Is there a blog post or tutorial describing each and every step involved in the entire communication process apart from the documentation materials provided by RIM?
Currently I am using Push Essentials but might migrate to Push Plus service later(in the distance future).
Kindly appreciate your quick response.
Ok, so there are 2 things to keep in mind:
1) The BlackBerry Infrastructure (Push Proxy Gateway or PPG) needs to have your device listed as subscribed for your specific application ID in order for pushes to be delivered to your device. Subscribing from the device registers it with the PPG and tells the PPG "I would like to allow pushes from this App ID to be delivered to me". If your device is not subscribed to the PPG then your pushes from the initiator will be sent, accepted by the PPG but never allowed to be delivered to the target device.
2) Even if the device is registered with the PPG, how does your server sending the pushes keep track of what devices are registered? This is done by registering with the Push Initiator. The client sample application included with the Push SDK has a mechanism to show how this can be done. As well the server sample is set to receive these requests and add the client to the database so that it can be included for future pushes.
With all that in mind what happens if:
1) The user un-installs the application
2) The user switches devices
In the above cases there needs to be a mechanism to de-register the device from receiving pushes both from the PPG and from your server Push Initiator. Again the client sample application shows how this can be done.
I have a service hosted in a Worker Role in Azure. Clients connect over NetTcp bindings using certificates for mutual client/service authentication and with a custom username password validation.
Clients also receive event notifications that are broadcast through the Azure service bus using shared secret authentication.
I want this to be secure and not allow one person to share his/her login information with friends or anyone else - their login is for their use only. Similarly, a user that forgets to log off at one machine and then logs in to the service from another machine (i.e. tablet, work computer etc.) should trigger a automatic shutdown of the application that was not logged off from.
I am using a per-call serivce, and to have implement a solution using sessions would require alot of rewiring.
I figure I need to keep track of the users' context when they make a operation call and track which IPs are currently using that login/credential. I would like to be able to have some kind of "death touch" whereby the service can send a kill command to a client when multiple logins are detected.
Any suggestions or pointers to patterns that deal with this issue would be appreciated.
Thanks.
Even if you did go with PerSession you would still need to determine if the same user was in more than one session and you have the overhead of session.
I have only tested this over WSHttpBinding and not hosted in an Azure Role so please don't vote it down if it does not work on NetTcp Azure Role - comment and I will delete it. Even with PerCall the SessionID is durable and SessionID is available on both the client and server. More than one user could have the same IP address but SessionID is unique to the session. Clearly you would need to record the userID, SessionID but table storage is cheap.
Maybe update license model for concurrent usage. By recording userID and sessionID you could write an algorithm to calculate max concurrent usage.