Rabbit - RPC - Synchronicznie

Rabbit - RPC - Synchronicznie
S9
  • Rejestracja:prawie 11 lat
  • Ostatnio:około 20 godzin
  • Postów:123
0

Cześć, implementuję Rabbitowe RPC w kodzie, który nie ma asynchroniczności z poziomu kodu projekt sprzed C# 5.0. W przykładach rabbita jest wykorzystane BlockingCollection, które blokuje wywołanie do momentu wyciągnięcia interesującej nas wiadomości. Ogólnie by nie blokować głównego wątku, integracja będzie odpalana w osobnym zadaniu HF, natomiast spotkaliście się może z lepszym rowiązaniem niż BlockingCollection. Wcześniej nigdy nie korzystałem z takiej kolekcji, jesteście w stanie polecieć jakieś materiały, blogi jak ogarnąć powyższy przypadek, nic ciekawego nie znalazłem dla kodu bez async. https://www.rabbitmq.com/tutorials/tutorial-six-dotnet.html

Kopiuj
public class RpcClient
{
    private readonly IConnection connection;
    private readonly IModel channel;
    private readonly string replyQueueName;
    private readonly EventingBasicConsumer consumer;
    private readonly BlockingCollection<string> respQueue = new BlockingCollection<string>();
    private readonly IBasicProperties props;
public RpcClient()
{
        var factory = new ConnectionFactory() { HostName = "localhost" };
        connection = factory.CreateConnection();
        channel = connection.CreateModel();
        replyQueueName = channel.QueueDeclare().QueueName;
        consumer = new EventingBasicConsumer(channel);
        props = channel.CreateBasicProperties();
        var correlationId = Guid.NewGuid().ToString();
        props.CorrelationId = correlationId;
        props.ReplyTo = replyQueueName;
        consumer.Received += (model, ea) =>
        {
            var body = ea.Body.ToArray();
            var response = Encoding.UTF8.GetString(body);
            if (ea.BasicProperties.CorrelationId == correlationId)
            {
                respQueue.Add(response);
            }
        };
    }
    public string Call(string message)
    {
        var messageBytes = Encoding.UTF8.GetBytes(message);
        channel.BasicPublish(
            exchange: "",
            routingKey: "rpc_queue",
            basicProperties: props,
            body: messageBytes);
        channel.BasicConsume(
            consumer: consumer,
            queue: replyQueueName,
            autoAck: true);
        return respQueue.Take();
    } 

Pipes
Kolejki nie są po to, by komunikacja była synchroniczna.
S9
@Pipes: Platforma z która musimy się zintegrować wykorzystuje RPC po rabbicie, my musimy się do niej podpiąć jako client.
Pipes
No tak, ale to nie jest synchroniczne ;) To działa jak wielka taśma produkcyjna - jeden coś kładzie, a drugi podnosi i vice versa. Podłączenie do kolejek rabbita to nic trudnego - sam zarzuciłeś do tego link :) Taka tego natura, że jest async - nie wiesz, kiedy ktoś przeczyta i zareaguje, ale dzięki temu nie masz całego tematu z przeciążeniem IO po waszej lub ich stronie - jak ktoś może zacząć przetwarzanie, bierze z kolejki i tak w koło :)
SO
Ale za pomocą kolejki możesz zrobić też request-response, na siłę bo na siłę ale niektóre nawet coś takiego udostępniają. Nie wiem jak dokładnie Rabbit bo na nim tego nie robiłem, ale na pewno coś takiego da się zrobić na Azure Service Bus (tam to się chyba nazywało sesje).
SO
  • Rejestracja:ponad 10 lat
  • Ostatnio:około rok
0

Może da się to zrobić za pomocą Direct reply-to?

https://www.rabbitmq.com/direct-reply-to.html

To rozwiązanie ze zbieraniem wiadomości w kolekcji w pamięci jak dla mnie bez sensu :P

Pipes
Niby można, ale to wtedy lepiej chyba bezpośrednio bez żadnego rabbita ;)
SO
Platforma z która musimy się zintegrować wykorzystuje RPC po rabbicie, my musimy się do niej podpiąć jako client.
Pipes
Ja rozumiem, niemniej to wtedy tylko takie proxy i nie ma wyraźnej korzyści nad zwykłym request / response bezpośrednim.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.