SignalR + RabbitMQ背板:SignalR客户端重复接收相同的消息

时间:2016-06-16 17:44:10

标签: c# rabbitmq signalr signalr-backplane

https://github.com/mdevilliers/SignalR.RabbitMq/issues/43

我真的很难让这个工作起来,有人可以看一下这个,看看设置中是否有问题吗?

这是我的测试:

我启动了两个自托管服务器,配置为相同的RabbitMqScaleoutConfiguration

[Test]
    public void BasicBackplaneTest()
    {
        SubsciberTestServerNode nodeA = null;
        SubsciberTestServerNode nodeB = null;

        string messageA = null;
        string messageB = null;
        try
        {
            Log("Given I have a WorkCenter Dispatch Publisher");
            var publisher = new WcDispatchPublisher(ConnectionString);

            Log("And I have multiple server nodes subscribed to the backplane");
            nodeA = new SubsciberTestServerNode("nodeA").Start().Result;
            nodeB = new SubsciberTestServerNode("nodeB").Start().Result;

            Log("And I wait 5 seconds");
            Thread.Sleep(5000);

            Log("When I publish a message: {0}", TestPayload);
            publisher.Publish(TestPayload);

            Log("And I wait 60 seconds");
            Thread.Sleep(TimeSpan.FromSeconds(60));

            messageA = nodeA.Message;
            messageB = nodeB.Message;
        }
        catch (AggregateException exception)
        {
            Log("Exception Occurred: {0}", exception.Flatten().Message);
            Exception = exception;
        }
        catch (Exception exception)
        {
            Log("Exception Occurred: {0}", exception.Message);
            Exception = exception;
        }
        finally
        {
            nodeA?.Dispose();
            nodeB?.Dispose();

            Log("Then no exceptions should have been thrown.");
            Exception.Should().BeNull();

            Log("Then the message should have been added to the Message Queue");
            messageA.Should().NotBeNullOrWhiteSpace();
            messageB.Should().NotBeNullOrWhiteSpace();
        }

服务器:

internal class SubsciberTestServerNode : IDisposable
{
    private readonly string _nodeName;
    private readonly string _url;
    private WcDispatchSubscriber _subscriber;
    private IDisposable _webApp;

    public SubsciberTestServerNode(string nodeName)
    {
        _nodeName = nodeName;
        _url = $"http://localhost:9999/{nodeName}";
        MessageList = new List<string>();
    }

    public string Message { get; set; }
    public List<string> MessageList { get; set; }

    public void Dispose()
    {
        if (_webApp != null)
        {
            _webApp.Dispose();
            _webApp = null;
            _subscriber.Dispose();
            _subscriber = null;
        }
    }

    public async Task<SubsciberTestServerNode> Start()
    {
        _webApp = WebApp.Start(_url, app =>
        {
            new Startup(_nodeName).Configuration(app);
            Thread.Sleep(TimeSpan.FromSeconds(5));
            //Place this code into your Application_Start() method.
            var factory = new ConnectionFactory
            {
                UserName = "guest",
                Password = "guest",
                HostName = "localhost"
            };

            var exchangeName = "WC_LeadDispatch_Exchange";

            var configuration = new RabbitMqScaleoutConfiguration(factory, exchangeName);
            GlobalHost.DependencyResolver.UseRabbitMq(configuration);
            GlobalHost.Configuration.TransportConnectTimeout = TimeSpan.FromSeconds(10);


            Thread.Sleep(TimeSpan.FromSeconds(5));
        });

        _subscriber = new WcDispatchSubscriber();
        await _subscriber.Subscribe(_url, msg =>
        {
            string message = $"Message received at Node: {_nodeName}. Message: {msg}.";
            Console.WriteLine(message);
            Message = message;
            MessageList.Add(message);
        });
        return this;
    }
}

订户:

public class WcDispatchSubscriber : IDisposable
{
    private const string HubName = "DispatchUpdateHub";
    private const string MessageEventName = "addMessage";
    private readonly int _connectionLimitInt;
    private IDisposable _hubProxySubscription;

    public WcDispatchSubscriber()
    {
        string connectionLimit = ConfigurationManager.AppSettings.Get("SignalRConnectionLimit");
        int.TryParse(connectionLimit, out _connectionLimitInt);
        _connectionLimitInt = _connectionLimitInt == 0 ? 100 : _connectionLimitInt;
    }

    public void Dispose()
    {
        _hubProxySubscription.Dispose();
    }

    public async Task Subscribe(string hubConnectionString, Action<string> messageReceived)
    {
        var hubConnection = new HubConnection(hubConnectionString);
        IHubProxy dispatchHubProxy = hubConnection.CreateHubProxy(HubName);
        _hubProxySubscription = dispatchHubProxy.On(MessageEventName, messageReceived);
        ServicePointManager.DefaultConnectionLimit = _connectionLimitInt;
        await hubConnection.Start();
    }
}

出版商:

public class WcDispatchPublisher
{
    private const string ExchangeName = "WC_LeadDispatch_Exchange";
    private readonly IHubContext _hubContext;

    public WcDispatchPublisher(string connectionString)
    {
        //actual string will look like this.  we may need to overload the other constructors in the Rabbit/SigR.
        //_rabbitConnectionString =
        //  "host=cprmqsrvt02vn01:5672;publisherConfirms=true;username=unittest;password=Un1t735t;virtualhost=UnitTest-NotificationService";
        var configuration = new RabbitMqScaleoutConfiguration(connectionString, ExchangeName);
        GlobalHost.DependencyResolver.UseRabbitMq(configuration);

        _hubContext = GlobalHost.ConnectionManager.GetHubContext<DispatchUpdateHub>();
    }

    /// <summary>
    /// </summary>
    /// <param name="payload"></param>
    public void Publish(string payload)
    {
        Task.Factory.StartNew(() =>
        {
            _hubContext.Clients.All.addMessage(payload);
        }).Wait();
    }
}

每次说第12次左右都会有效,通常是我得到的结果:

Given I have a WorkCenter Dispatch Publisher
And I have multiple server nodes subscribed to the backplane
And I wait 5 seconds
When I publish a message: test-payload
And I wait 60 seconds
Message received at Node: nodeA. Message: test-payload.
Message received at Node: nodeB. Message: test-payload.
Message received at Node: nodeB. Message:         {"LeadId":37252,"DispatchId":153595,"NotificationTypeId":1,"NotificationTitle":"    Leads Dispatch","DispatchDateTime":"2016-06-  16T17:16:26.187","AlertMessage":"Lead number 37252 dispatched 6/16/2016 at 7:16   AM CST","DispatchedToFranchise":5576,"FranchiseOpsId":130}.
Message received at Node: nodeB. Message:  {"LeadId":37252,"DispatchId":153595,"NotificationTypeId":1,"NotificationTitle":"  Leads Dispatch","DispatchDateTime":"2016-06- 16T17:16:26.187","AlertMessage":"Lead number 37252 dispatched 6/16/2016 at 7:16  AM CST","DispatchedToFranchise":5576,"FranchiseOpsId":130}.
 Message received at Node: nodeB. Message:  {"LeadId":37252,"DispatchId":153595,"NotificationTypeId":1,"NotificationTitle":" Leads Dispatch","DispatchDateTime":"2016-06- 16T17:16:26.187","AlertMessage":"Lead number 37252 dispatched 6/16/2016 at 7:16   AM CST","DispatchedToFranchise":5576,"FranchiseOpsId":130}.
 Message received at Node: nodeB. Message:  {"LeadId":37252,"DispatchId":153595,"NotificationTypeId":1,"NotificationTitle":" Leads Dispatch","DispatchDateTime":"2016-06- 16T17:16:26.187","AlertMessage":"Lead number 37252 dispatched 6/16/2016 at 7:16  AM CST","DispatchedToFranchise":5576,"FranchiseOpsId":130}.
 Message received at Node: nodeB. Message: {"LeadId":37252,"DispatchId":153595,"NotificationTypeId":1,"NotificationTitle":"Leads Dispatch","DispatchDateTime":"2016-06-16T17:16:26.187","AlertMessage":"Lead number 37252 dispatched 6/16/2016 at 7:16 AM CST","DispatchedToFranchise":5576,"FranchiseOpsId":130}.
 Message received at Node: nodeB. Message: {"LeadId":37252,"DispatchId":153595,"NotificationTypeId":1,"NotificationTitle":"Leads Dispatch","DispatchDateTime":"2016-06-16T17:16:26.187","AlertMessage":"Lead number 37252 dispatched 6/16/2016 at 7:16 AM CST","DispatchedToFranchise":5576,"FranchiseOpsId":130}.

......继续像这样永远

1 个答案:

答案 0 :(得分:1)

在我的脑海中,我会说尝试:

nodeA = new SubsciberTestServerNode("nodeA").Start().Wait();
nodeB = new SubsciberTestServerNode("nodeB").Start().Wait();

nodeA = await new SubsciberTestServerNode("nodeA").Start();
nodeB = await new SubsciberTestServerNode("nodeB").Start();

结果是一个线程阻塞调用,因此可能会阻止nodeA触发。