Datastax C#驱动3.3.0死锁连接到集群?

时间:2017-06-13 21:05:02

标签: c# cassandra datastax datastax-enterprise

到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}"

然后只运行30000ms并抛出:

                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上运行相同的测试没有这样的问题。其他人可以测试一下吗?也许这恰好发生在我身上。

编辑:

以下是死锁的屏幕截图:

Deadlocked tasks with blocking awaiting ()

3 个答案:

答案 0 :(得分:2)

感谢您的评论中的详细信息,我们能够确定潜在的问题。

Similar to what was proposed by Luke,有一些ConfigureAwait()次来电失踪。

此问题会影响在Cluster.Connect()环境中调用SynchonizationContext的用户,这不是常见用例:

  • 对于Windows Forms,它不太可能直接与数据库通信(中间没有服务)。此外,用户应在创建表单(没有Connect()之前)之前调用SynchonizationContext以在所有表​​单中共享同一个Session实例。
  • 对于ASP.NET,用户应在创建HttpContext之前(在没有Connect()的情况下)在任何端点操作之外调用SynchonizationContext

请注意,此问题仅影响Connect()次来电。其他阻止调用如Execute()没有此问题。

在任何情况下,这个问题都可能是用户开始使用驱动程序的一个停顿,例如,用户创建一个简单的Windows窗体应用程序来尝试一个概念。

我已经提交了一个带有修复程序的pull请求,该请求还包含一个测试,该测试会查看使用await而没有ConfigureAwait()调用的源代码,以避免将来出现此问题: https://github.com/datastax/csharp-driver/pull/309

您可以预期修复程序将在下一个修补程序版本中登陆。

答案 1 :(得分:1)

我无法重现此问题,但我怀疑问题可能出在recent change,以使连接过程在内部异步。我不确定,但通过Connect代码进行追踪,我怀疑它可能缺少ConfigureAwait(false)。特别是,它看起来像Reconnect方法(它肯定会成为Init代码路径的一部分)is missing one after that commit。我可能无法重现它,因为我没有按下Reconnect代码路径,因为某些原因你在你的环境中。

我不是100%确定是罪魁祸首,但我opened a PR要解决它。 Stephen Cleary写了一篇关于为什么会在Forms / Web应用程序中发生这种情况的great explanation。您可以尝试从我的fork构建驱动程序,以查看该更改是否解决了问题,或者等待,看看PR和新版本会发生什么。如果它还在发生,我建议在JIRA上打开一个问题。

希望有所帮助!

答案 2 :(得分:0)

已在此处打开问题,解决方法:

https://datastax-oss.atlassian.net/projects/CSHARP/issues/CSHARP-579

对于任何遇到相同问题的人 - 只需将连接代码包装到新任务中即可。

Task.Run(() =>
    {
        SimpleConnectTest();
    });