zeromq / netmq

A 100% native C# implementation of ZeroMQ for .NET
Other
2.95k stars 744 forks source link

DealerSocket stops sending messages after system restart #856

Closed kadralievr closed 2 years ago

kadralievr commented 4 years ago

Environment

NetMQ Version: 4.0.0.207
Operating System: Ubuntu 16.04.4 LTS
.NET Version: netcoreapp3.1
Base Docker Image: mcr.microsoft.com/dotnet/core/runtime:3.1-alpine3.10

Expected behavior

DealerSocket continues to send messages to RouterSocket (on another machine) after a system restart.

Actual behavior

DealerSocket stops sending messages after some system restart. (not constantly) But if I send a message with RouterSocket (will not be delivered) and then restart а docker container with DealerSocket, the Router-Dealer connection will restore and Dealer socket will send messages. If I only restart the container with DealerSocket, it won't happen, the problem will still exist.

Steps to reproduce the behavior

Restart system

Details

I have

Each Client has a unique ClientID. Server identifies addressee and addresser by ClientID

On Server side we use RouterSocket

services.AddSingleton<NetMQSocket>(provider =>
{
    var options = provider.GetRequiredService<Options>();
    var result = new RouterSocket();
    result.Bind(options.Endpoint);
    return result;
});

On Client side we use DealerSocket

services.AddSingleton<NetMQSocket>(provider =>
{
    var options = provider.GetRequiredService<Options>();
    var connectionString = options.ServerUrl;

    var result = new DealerSocket();
    result.Options.Identity = options.ClientD.ToByteArray();
    result.Options.TcpKeepalive = true;
    result.Options.TcpKeepaliveIdle = TimeSpan.FromMinutes(1);
    result.Options.ReconnectInterval = TimeSpan.FromMilliseconds(500);
    result.Connect(connectionString);

    return result;
});

On each side we use our own class SocketClient to sync reading and writing to socket

public class SocketClient : IDisposable
{
    private const Int32 MessageFrameCount = 2;
    private readonly NetMQSocket _socket;

    public SocketClient(
        NetMQSocket socket
    )
    {
        _socketOptions = socketOptions;
    }

    ...

    public void Send(NetMQMessage message)
    {
        try
        {
            lock (_socket)
            {
                _socket.SendMultipartMessage(message);
            }
        }
        catch (Exception e)
        {
            ...
        }
    }

    public IEnumerable<NetMQMessage> ReceiveAll()
    {
        try
        {
            var result = new List<NetMQMessage>(_capacity);

            lock (_socket)
            {
                while (true)
                {
                    try
                    {
                        NetMQMessage message = null;

                        if (!_socket.TryReceiveMultipartMessage(TimeSpan.Zero, ref message, MessageFrameCount))
                        {
                            break;
                        }

                        result.Add(message);
                    }
                    catch (Exception e)
                    {
                        ...
                    }
                }
            }

            return result;
        }
        catch (Exception e)
        {
            ...
        }
    }
}

I have a few questions:

  1. Am I right to use Router-Dealer pattern?
  2. Do I set up it right? Options are defined on DI description
  3. Why DealerSockets stops sending messages after some restarts?
  4. What happens if 2 Clients with the same ClientID connect to Server? It may happen while the Client is updating. Docker container with old version stops and another one with the new version starts.
stale[bot] commented 3 years ago

This issue has been automatically marked as stale because it has not had activity for 365 days. It will be closed if no further activity occurs within 56 days. Thank you for your contributions.