如何让SimpleRpcClient.Call()成为阻塞调用以实现与RabbitMQ的同步通信?

时间:2011-05-10 07:54:57

标签: .net rabbitmq synchronous

在RabbitMQ的.NET版本(2.4.1)中, RabbitMQ.Client.MessagePatterns.SimpleRpcClient 有一个带有这些签名的Call()方法:

    public virtual object[] Call(params object[] args);
    public virtual byte[] Call(byte[] body);
    public virtual byte[] Call(IBasicProperties requestProperties, byte[] body, out IBasicProperties replyProperties);

问题:

通过各种尝试,该方法仍然继续不阻止我期望的位置,因此它无法处理响应。

问题:

SimpleRpcClient 的设置中明显遗漏,或者早先使用 IModel IConnection ,甚至 PublicationAddress

更多信息:

我也尝试过QueueDeclare()方法的各种参数配置,但没有运气。

string QueueDeclare(string queue, bool durable, bool exclusive, bool autoDelete, IDictionary arguments);

我的设置的更多参考代码:

IConnection conn = new ConnectionFactory{Address = "127.0.0.1"}.CreateConnection());
using (IModel ch = conn.CreateModel())
{
     var client = new SimpleRpcClient(ch, queueName);
     var queueName = ch.QueueDeclare("t.qid", true, true, true, null);

     ch.QueueBind(queueName, "exch", "", null);

     //HERE: does not block?
     var replyMessageBytes = client.Call(prop, msgToSend, out replyProp);
}

寻找其他地方:

或者我的“服务器端”代码中是否存在问题?无论使用和不使用BasicAck(),客户端都会继续执行。

1 个答案:

答案 0 :(得分:3)

- 简短回答 -

你做错了”......

  

检查 IBasicProperties ,您应该将 SimpleRpcServer HandleSimpleCall()

一起使用

如果你偶然发现了这个问题,你或者采取了错误的方法,并且可能会犯一个类似的错误,即错误地操纵 IBasicProperties ,从而损害 SimpleRpcServer <的能力/ em>正常运行。

- LONG ANSWER -

.NET的工作示例:   在BitBucket上找到我的工作示例:

  

https://bitbucket.org/NickJosevski/synchronous-rabbitmq-sample-.net

或者这是一个快速的样本...

客户端:

IConnection conn = new ConnectionFactory{Address = "127.0.0.1"}.CreateConnection();
using (IModel ch = conn.CreateModel())
{
    ch.ExchangeDeclare(Helper.ExchangeName, "direct");

    var queueName = ch.EnsureQueue();

    var client = new SimpleRpcClient(ch, queueName);

    var msgToSend = new Message(/*data*/).Serialize();

    IBasicProperties replyProp;

    var reply = client.Call(new BasicProperties(), msgToSend, out replyProp);
}

服务器端:

IConnection conn = new ConnectionFactory{Address = "127.0.0.1"}.CreateConnection();
using (IModel ch = conn.CreateModel())
{
    ch.ExchangeDeclare(Helper.ExchangeName, "direct");
    var queuename = ch.EnsureQueue();

    var subscription = new Subscription(ch, queuename);

    new MySimpleRpcServerSubclass(subscription).MainLoop();
}

internal class MySimpleRpcServerSubclass : SimpleRpcServer
{
    public MySimpleRpcServerSubclass(Subscription subscription) 
        : base(subscription) { }

    public override byte[] HandleSimpleCall(
        bool isRedelivered, IBasicProperties requestProperties, 
        byte[] body, out IBasicProperties replyProperties)
    {
        replyProperties = requestProperties;
        replyProperties.MessageId = Guid.NewGuid().ToString();

        var m = Message.Deserialize(body);
        var r = 
            new Response
            {
                Message = String.Format("Got {0} with {1}", m.Name, m.Body)
            };

        return r.Serialize();
    }
}

<强>共享:

//helper:
public static string EnsureQueue(this IModel ch)
{
    var queueName = ch.QueueDeclare(QueueId, false, false, false, null);

    ch.QueueBind(queueName, ExchangeName, "", null);

    return queueName;
}

//NOTE: 
not all extension methods are explained here, such as *.Serialize()* 
as they're not relevant and just make for a cleaner example.