2015-01-14 2 views
1

Я пытаюсь понять, как запрос шаблон/ответ был реализован в ServiceStack/MQServersЗапрос/Ответ объяснение

предполагая случай использования от wiki

mqClient.Publish(new Hello { Name = "World" }); 

var responseMsg = mqClient.Get<HelloResponse>(QueueNames<HelloResponse>.In); 
mqClient.Ack(responseMsg); 
responseMsg.GetBody().Result //= Hello, World! 

Скажем, фрагмент кода имеет был вызван в методе обслуживания проживающих в веб-приложения, размещенного в IIS

// web api - IIS hosts the service 
public class WebRequestService : Service 
{ 
    public IMessageService MessageService { get; set; } 

    public object Any(MyWebRequest request) 
    { 
     using (var mqClient = MessageService.CreateMessageQueueClient()) 
     { 
      var id = Guid.NewGuid().ToString(); 

      mqClient.Publish(new Hello { Id = id }); 
      var msgCopy = mqClient.Get<HelloResponse>(QueueNames<HelloResponse>.In); 

      mqClient.Ack(msgCopy); 
      var response = msgCopy.GetBody(); 
      Logger.DebugFormat("Request for '{0}' replied '{1}'.", id, response.Result); 

     } 

     return new MyWebRequestResponse 
     { 
      Result = "result" 
     }; 
    } 
} 

Опубликовать способ отправить запрос привет middletier, на котором размещена Hello Услуги

// middletier - winservice hosts the service 
public class HelloService : Service 
{ 
    public object Any(Hello req) 
    { 
     return new HelloResponse 
     { 
      Result = req.Id 
     }; 
    } 
} 

С WebAPI/WebRequestService получает несколько одновременных запросов, как я могу achive «mqClient.Get», после публикации вызова получает ответ, выданный из-за соответствующей Hello Request? Другими словами, как я могу быть уверен, в этом примере фиктивного метода Hello.Id (отправленный методом Publish) совпадает с HelloResponse.Result (полученным через mqClient.Get)? Как можно обеспечить корреляцию с опубликованным запросом и его ответом? Как предотвратить mqClient.Get просматривает сообщение, не относящееся к тому, которое было опубликовано в предыдущей строке кода?

Единственный способ, которым я выяснить до сих пор использовать опцию REPLYTO поэтому создать очередь за каждый запрос WebAPI, но я не думаю, что это вариант

var uid = Guid.NewGuid().ToString(); 
string replyToMq = "mq:Hello.replyto." + uid; 
mqClient.Publish(new Message<Hello>(new Hello { Id = id }) 
{ 
    ReplyTo = replyToMq 
}); 
var msgCopy = mqClient.Get<HelloResponse>(replyToMq); 

ответ

1

Если вы хотите, чтобы получить ответ который соотносится с конкретным запросом вам нужно specify a ReplyTo address, например:

const string replyToMq = mqClient.GetTempQueueName(); 
mqClient.Publish(new Message<Hello>(new Hello { Name = "World" }) { 
    ReplyTo = replyToMq 
}); 

IMessage<HelloResponse> responseMsg = mqClient.Get<HelloResponse>(replyToMq); 
mqClient.Ack(responseMsg); 
responseMsg.GetBody().Result //= Hello, World! 

Вам не нужно будет указать ReplyTo для длительных (апатридов) процессов, которые могут в общем процессе какой-либо ответ, то есть для выполнения каких-либо дополнительный обработка после ea ch запрос завершен.

+0

mqClient.GetTempQueueName() создает очередь, которая будет удалена после того, как сообщение заглянет из этой очереди tmp mqClient.Get + mqClient.Ack. Это верно? Другим словом, что происходит под капотом, является то, что я предложил в качестве решения, а также автоматическую очистку очереди tmp? – Crixo

+0

'GetTempQueueName()' объявляет ** эксклюзивный ** и ** autoDelete ** RabbitMQ Queue, который автоматически очищается, когда соединение mqClient закрывается. – mythz

+0

Получил! Большое спасибо за объяснение! – Crixo