调试 .NET 应用程序时未维护连接到本地 EventStore

Connecting to local EventStore is not being maintained when debugging .NET application

问题:当我从 Visual Studio 调试我的 .NET 应用程序时,我与本地存储的 EventStore 的连接没有得到维护。

我收到一个错误:

Connection 'ES-6ab8f860-e44b-40ca-93fa-7370b72547d8' was closed.

当前设置:我的事件存储位于我的解决方案中,应用程序由 PATH 变量引用。

//Path to the local EventStore in solution
private const string Path = @"..\..\EventStore-OSS-Win-v5.0.8\EventStore.ClusterNode.exe";

以下代码设置与 EventStore 的新连接:

public static void SetupEventStore(StartConflictOption opt = StartConflictOption.Connect) //set default to Connect
{
    // Save the EventStore process in a variable for later use
    var runningEventStores = Process.GetProcessesByName("EventStore.ClusterNode");
    // if a process was found, check the parameter options on what to do with the process
    if (runningEventStores.Length != 0)
    {
        switch (opt)
        {
            case StartConflictOption.Connect:
                _process = runningEventStores[0]; //set the process to the EventStore.ClusterNode
                break;

            case StartConflictOption.Kill:
                foreach (var es in runningEventStores) //makes sure that all running processes are killed
                {
                    es.Kill();
                }
                break;

            case StartConflictOption.Error: 
                throw new Exception("Conflicting EventStore running."); //Will be thrown if there is already a running EventStore process

            default:
                throw new ArgumentOutOfRangeException(nameof(opt), opt, null);
        }
    }

    if (_process == null)
    {
        _process = new Process
                {
                    StartInfo =
                    {
                        UseShellExecute = false, CreateNoWindow = true, FileName = Path, Arguments = Args, Verb = "runas"
                    }
                };
        _process.Start();
    }

    //set default IP endpoint and port (localhost:1113). HTTP uses port 2113, while TCP uses port 1113
    var tcp = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 1113);
    var http = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 2113);

    //Connect to the Event Store
    Connection = EventStoreConnection.Create(new Uri("tcp://admin:changeit@localhost:1113"));
    Connection.ConnectAsync().Wait();
}

当我调试应用程序时,它启动时没有问题,但是当我尝试为 EventStore 创建新流时,它因前面提到的错误而崩溃。

我注意到 EventStore 进程在调试应用程序时被终止之前有一瞬间处于活动状态。

问题:为什么在应用程序 运行 时我的事件存储进程没有得到维护,我可以采取什么步骤来解决这个问题?

您的问题的答案如下,但首先,让我表达一下我对您的设置的担忧。我无法想象应用程序会以类似的方式执行它使用的数据库。从您的应用程序启动 Event Store 的原因是什么,为什么它不能以不同的方式启动?在 任何 数据库上使用 process.Kill,不仅是事件存储,也不是最好的主意。

如果您必须将 Event Store 作为应用程序的一部分,我建议您改用 embedded version(但不保证它会在未来的版本中继续存在)。

您观察到的是正常行为。任何实时始终在线的连接都会发生同样的情况,例如 gRPC 流。

当您逐步调试您的应用程序并停在断点处时,整个应用程序的世界都停止了。当您到达断点并且不继续前进时,没有多线程或其他任何工作。

实际上,您应该准备应用程序来处理连接失败。分布式计算的谬误之一是"the network is reliable"。它不是。 IEventStoreConnection 实例有一些事件,例如

_connection.Disconnected += (sender, args) =>
{
    log.Warning("Connection closed");
    Task.Run(() => Reconnect()); // Reconnect is some place when you try to connect again
};

我建议避免整体调试,尤其是在使用始终在线通信的应用程序中。您可以通过编写涵盖您的用例和的测试来获得更多价值。日志也很有用。

如果您绝对必须使用断点进行调试,您可以更改本地环境设置,使连接字符串更能容忍断开连接。检查 list of settings in the docs。一些可能有用的设置是 HeartbeatIntervalHeartbeatTimeout。通过将这些设置设置为一分钟(例如),您将有足够的时间在连接关闭之前进行调试。但是不要在生产中使用这些值。

也可以instruct the connection保持重连(KeepReconnecting()。需要在创建连接的代码中使用ConnectionSettingsBuilder参数,有调整心跳间隔的方法还有超时,您可以使用它而不是更改连接字符串。使用不同的连接字符串更容易,因为在 .NET Core 中每个环境可以有不同的配置文件。

一个例子:

var connectionString = $"ConnectTo=tcp://{user}:{password}@{host}:1113; HeartBeatTimeout=500";

var settingsBuilder = ConnectionSettings
    .Create()
    .KeepReconnecting()
    .LimitReconnectionsTo(10);

_connection = EventStoreConnection.Create(connectionString, settingsBuilder);