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

您可以期待下一个补丁版本中的修复。