调试 .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。一些可能有用的设置是 HeartbeatInterval
和 HeartbeatTimeout
。通过将这些设置设置为一分钟(例如),您将有足够的时间在连接关闭之前进行调试。但是不要在生产中使用这些值。
也可以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);
问题:当我从 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。一些可能有用的设置是 HeartbeatInterval
和 HeartbeatTimeout
。通过将这些设置设置为一分钟(例如),您将有足够的时间在连接关闭之前进行调试。但是不要在生产中使用这些值。
也可以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);