Datastax C# 驱动程序 3.3.0 在连接到集群时死锁?
Datastax C# driver 3.3.0 deadlocking on connect to cluster?
致Datastax C#驱动工程师:
C# 驱动程序 3.3.0 在调用 Connect()
时出现死锁。 Windows 表单上的以下代码片段将在尝试连接时出现死锁:
public void SimpleConnectTest()
{
const string ip = "127.0.0.1";
const string keyspace = "somekeyspace";
QueryOptions queryOptions = new QueryOptions();
queryOptions.SetConsistencyLevel(ConsistencyLevel.One);
Cluster cluster = Cluster.Builder()
.AddContactPoints(ip)
.WithQueryOptions(queryOptions)
.Build();
var cassandraSession = cluster.Connect(keyspace);
Assert.AreNotEqual(null, cassandraSession);
cluster.Dispose();
}
此处发生死锁:
Cluster.cs ->
private void Init()
{
...
TaskHelper.WaitToComplete(_controlConnection.Init(), initialAbortTimeout);
...
}
我已经在 Cassandra 3.9.0 上测试了这个,本地机器上的 CQL 规范 3.4.2。
在此处调用此方法 _controlConnection.Init() 时一切都陷入僵局:
task = Id = 11, Status = WaitingForActivation, Method = "{null}", Result = "{Not yet computed}"
然后这只运行了 30000 毫秒并抛出这个:
throw new TimeoutException(
"Cluster initialization was aborted after timing out. This mechanism is put in place to" +
" avoid blocking the calling thread forever. This usually caused by a networking issue" +
" between the client driver instance and the cluster.", ex);
运行同样在3.2.0上测试无此问题。其他人可以测试这个吗?也许这只是发生在我身上。
编辑:
这是死锁的屏幕截图:
我无法重现问题,但我怀疑问题可能出在 recent change to make the connection process asynchronous internally. I don't know for sure, but tracing through the Connect
code, I suspect it might be a missing ConfigureAwait(false)
. In particular, it looks like the Reconnect
method (which could definitely get hit as part of that Init
code path) is missing one after that commit 上。我可能无法重现它,因为由于某种原因你在你的环境中,我没有点击 Reconnect
代码路径。
我不是 100% 确定那是罪魁祸首,但我 opened a PR to fix it. Stephen Cleary wrote a great explanation on why this can happen in Forms/Web apps. You could try building the driver from my fork to see if that change fixes the problem, or wait and see what happens with the PR and a new release. If it's still happening, I'd suggest opening an issue on the JIRA。
希望对您有所帮助!
问题已在此处解决并解决:
https://datastax-oss.atlassian.net/projects/CSHARP/issues/CSHARP-579
对于遇到同样情况的任何人 - 只需将您的连接代码包装到一个新任务中即可。
Task.Run(() =>
{
SimpleConnectTest();
});
感谢您评论中的详细信息,我们能够确定根本问题。
,缺少 ConfigureAwait()
个电话。
此问题会影响在具有 SynchonizationContext
的环境中调用 Cluster.Connect()
的用户,这不是常见的用例:
- 对于 Windows 表单,它不太可能直接与数据库通信(中间没有服务)。此外,用户应在创建表单(没有
SynchonizationContext
)之前调用 Connect()
以在所有表单之间共享相同的 Session 实例。
- 对于 ASP.NET,用户应该在任何端点操作之外调用
Connect()
,在创建 HttpContext 之前(没有 SynchonizationContext
)。
请注意,此问题仅影响 Connect()
个调用。 Execute()
等其他阻塞调用没有此问题。
无论如何,对于开始使用该驱动程序的用户来说,这个问题可能是一个障碍,例如,用户创建一个简单的 windows 表单应用程序来尝试一个概念。
我已经提交了一个带有修复的拉取请求,其中还包含一个测试,该测试查看源代码以了解 await
的使用情况,而无需 ConfigureAwait()
调用,以避免在未来:
https://github.com/datastax/csharp-driver/pull/309
您可以期待下一个补丁版本中的修复。
致Datastax C#驱动工程师:
C# 驱动程序 3.3.0 在调用 Connect()
时出现死锁。 Windows 表单上的以下代码片段将在尝试连接时出现死锁:
public void SimpleConnectTest()
{
const string ip = "127.0.0.1";
const string keyspace = "somekeyspace";
QueryOptions queryOptions = new QueryOptions();
queryOptions.SetConsistencyLevel(ConsistencyLevel.One);
Cluster cluster = Cluster.Builder()
.AddContactPoints(ip)
.WithQueryOptions(queryOptions)
.Build();
var cassandraSession = cluster.Connect(keyspace);
Assert.AreNotEqual(null, cassandraSession);
cluster.Dispose();
}
此处发生死锁:
Cluster.cs ->
private void Init()
{
...
TaskHelper.WaitToComplete(_controlConnection.Init(), initialAbortTimeout);
...
}
我已经在 Cassandra 3.9.0 上测试了这个,本地机器上的 CQL 规范 3.4.2。
在此处调用此方法 _controlConnection.Init() 时一切都陷入僵局:
task = Id = 11, Status = WaitingForActivation, Method = "{null}", Result = "{Not yet computed}"
然后这只运行了 30000 毫秒并抛出这个:
throw new TimeoutException(
"Cluster initialization was aborted after timing out. This mechanism is put in place to" +
" avoid blocking the calling thread forever. This usually caused by a networking issue" +
" between the client driver instance and the cluster.", ex);
运行同样在3.2.0上测试无此问题。其他人可以测试这个吗?也许这只是发生在我身上。
编辑:
这是死锁的屏幕截图:
我无法重现问题,但我怀疑问题可能出在 recent change to make the connection process asynchronous internally. I don't know for sure, but tracing through the Connect
code, I suspect it might be a missing ConfigureAwait(false)
. In particular, it looks like the Reconnect
method (which could definitely get hit as part of that Init
code path) is missing one after that commit 上。我可能无法重现它,因为由于某种原因你在你的环境中,我没有点击 Reconnect
代码路径。
我不是 100% 确定那是罪魁祸首,但我 opened a PR to fix it. Stephen Cleary wrote a great explanation on why this can happen in Forms/Web apps. You could try building the driver from my fork to see if that change fixes the problem, or wait and see what happens with the PR and a new release. If it's still happening, I'd suggest opening an issue on the JIRA。
希望对您有所帮助!
问题已在此处解决并解决:
https://datastax-oss.atlassian.net/projects/CSHARP/issues/CSHARP-579
对于遇到同样情况的任何人 - 只需将您的连接代码包装到一个新任务中即可。
Task.Run(() =>
{
SimpleConnectTest();
});
感谢您评论中的详细信息,我们能够确定根本问题。
ConfigureAwait()
个电话。
此问题会影响在具有 SynchonizationContext
的环境中调用 Cluster.Connect()
的用户,这不是常见的用例:
- 对于 Windows 表单,它不太可能直接与数据库通信(中间没有服务)。此外,用户应在创建表单(没有
SynchonizationContext
)之前调用Connect()
以在所有表单之间共享相同的 Session 实例。 - 对于 ASP.NET,用户应该在任何端点操作之外调用
Connect()
,在创建 HttpContext 之前(没有SynchonizationContext
)。
请注意,此问题仅影响 Connect()
个调用。 Execute()
等其他阻塞调用没有此问题。
无论如何,对于开始使用该驱动程序的用户来说,这个问题可能是一个障碍,例如,用户创建一个简单的 windows 表单应用程序来尝试一个概念。
我已经提交了一个带有修复的拉取请求,其中还包含一个测试,该测试查看源代码以了解 await
的使用情况,而无需 ConfigureAwait()
调用,以避免在未来:
https://github.com/datastax/csharp-driver/pull/309
您可以期待下一个补丁版本中的修复。