Continuing the discussion from Supporting Multiple SQS Queues for the same message type across different instances:
I have the same requirement of supporting queues with the same message type for different services as discussed in the above question.
The answer with regards to queueprefix worked perfectly for SQS, I'm trying to work out how to get this working for Redis.
If I set the queueprefix to "instance-service" with redis I see a pubsub channel created called "instance-service-mq:topic:in
If I publish a message using this approach: mqClient.Publish(ob1) I receive the object and can process it.
However, if I need the object to go to service2, I have tried the following:
none of which appear to reach the destination.
What am I missing here, and what is the correct way to publish / consume to a queue in the format "instance-service-messagename"
What's your Queue Names configuration?
The Queue Names are static so they're only configurable to use a single prefix. Are you trying to send them to 2 different prefixes within the same App?
The QueuePrefix is only set to one value, each service only reads from one set of queues (and each queue belongs to only one service), however, I need a Service to post both to its own queue and to the queue of another service so I need to be able to post to two different queue prefixes.
I have the following services
[ Service A ] < - > [ Service B ] < - > [ Service C ]
Service A has the following queue interactions
- Posts and Reads to Dev-A-Inbound
- Posts to Dev-B-Processing
- Reads from Dev-A-Outbound
Service B has the following queue interactions
- Reads from Dev-B-Processing
- Posts to Dev-A-Outbound
- Posts to Dev-C-Outbound
Service C has the following queue interactions
- Posts and Reads from Dev-C-Inbound
- Reads from Dev-C-Outbound
- Posts to Dev-B-Processing
With SQS this works as I could set QueuePrefix as follows for the purpose of reading:
and then when publishing a message I could use
where qUrl uses the format
<add key="QueueUrlPattern" value="https://sqs.us-west-1.amazonaws.com/xxxxxxx/[INSTANCE]-[SERVICE]-mq-[TYPE]-inq" />
and I fill the parameters accordingly depending on the destination
Without the ability to set a destination queue in this way, it severely limits scalability options and/or I'd have to have a different message model per service, and that really goes against how the architecture design is intended.
Think I found the solution, I can do the following:
This achieves the same approach I had with SQS I believe.
I'm unable to repro this issue. I've added a new test that uses a QueueName prefix in MqServerQueueNameTests.cs and both Redis and RabbitMQ have the same behavior of using the prefix in each of the Topic Queue Names as well as the Request/Response Queue Names.
Can you provide a stand-alone integration test that we can run that shows where the Prefix isn't being used?
Hi mythz, sorry about the brevity of my response above. I don't think there is a bug here, I think the issue was that if I wanted to post to a seperate channel e.g. post to queue for service B from service A, I had to use the Publish method with the correct queue path as above.
I didn't have this formatted quite right, but I managed to work it out by using the ToQueueNameIn provided by the producer class.
So I think all is good here provided this is the correct way to post to another services channel ?
Yeah that's how to override the default Queue Name.
I have got this to work in the following Configuration
With two services
Service A puts X in dev-A-X queue
Service A reads X from dev-A-X queue
Service A puts Y in dev-B-Y queue
Service B reads Y from dev-B-Y queue
The problem I have is that the consumer thread in service B appears to die, it runs once, processes one message, returns and is never seen again. I should mention that this is using multiple test harness host applications and I'm yet to test it fully with the individual windows services, so I was wondering if something screwy was happening with visual studio somehow.
I do not appear to be having any exceptions, I am returning null from the method and messages appear to be flowing correctly between the queues from the redis perspective with the message ending up in the out queue.
Initially i thought it might have been a race condition with the queuenames prefix somehow (resulting in message ending up in wrong queue), but i traced everything through and it is all correct. It is just that the Service B consumer thread never fires a second time.
If I restart the Service B host, it picks up the second message, processes again and then fails to deliver a third.
Any thoughts on this or how I may debug it?
I was going to try to send X to B just to see if that object sent fine as it appears to work always no problem with service A
Declaring a prefix is akin to specifying a "namespace" for your MQ Services where you should only be using a single namespace which all your Services should be using.
The issue is that Redis MQ sends the Message to the Queue but then needs to "notify the MQ topic" to tell any
RedisMqServer listening that a new message is available.
The name of this topic is
QueueNames.TopicIn which is used for all messages.
You can manually notify the topic of a different prefix with something like:
var mqClient = (RedisMessageQueueClient)mqServer.CreateMessageQueueClient();
var queueName = MessageFactory.Create(request).ToInQueueName();
But using internal impl details like this is ugly, ideally you should be avoiding sending messages in different namespaces entirely. Can you just not send a different Request DTO to publish a Message to Service B?
var requestB = request.ConvertTo<RequestB>();
Thanks very much for the information.
The problem I have is with this structure:
A <-> B <-> C1
Where B will send to 0 or more C services.
Yes I can have a Cx request DTO, but it removes the genericity of the code and means that I can't run with an adapter pattern.
With SQS I was able to achieve this genericity as the namespace prefix used was data driven so I just sent a single request DTO type to 0 or more queues
For now I'll go with inheriting the DTO model as you have suggested, its not quite what I wanted but I'll compromise for now.
Another alternative is to use RabbitMq which as it's a push-based purpose-built MQ Server doesn't require subscribing to a Pub/Sub topic like RedisMq does.
Thanks for the information. Just a question on the Pub/Sub handling for Redis.
With SQS, if i have two services subscribe to the same queue, the message will be delivered only once (to one of the services which has implemented the registerhandler)
Is this the same with RedisMQ implementation, or will the Pub/Sub broadcast ?
All MQ Servers have the same behavior where messages are published to an "In Queue" and only delivered/processed by a single worker. The Pub/Sub topic is an implementation detail to notify the
RedisMqServer that they have pending messages, the Pub/Sub topic isn't sent the message itself, just a notification that they have messages in their Message
Great thanks that's perfect.