【问题标题】:C# SSH.NET - one SSH connection vs multiple SSH connectionsC# SSH.NET - 一个 SSH 连接与多个 SSH 连接
【发布时间】:2019-06-04 17:59:05
【问题描述】:

我有一个 C# 应用程序,它使用 SSH.NET 库连接到服务器。应用通过多种方式对数据库执行SQL命令。

拥有一个包含所有 SQL 命令的长时间运行的 SSH 连接是否更好,例如:

using (var sshClient = getSshClient()))
{
    sshClient.Connect();

    if (sshClient.IsConnected)
    {
        using (var portForward = setupPortForward()))
        {
            sshClient.AddForwardedPort(setupPortForward());
            portForward.Start();

            // Start SQL commands

            if (!sshClient.IsConnected) {
                sshClient.Connect();
            }
            else {
                executeSQLCommand1();
            }

            if (!sshClient.IsConnected) {
                sshClient.Connect();
            }
            else {
                executeSQLCommand2();
            }

            // End SQL commands

            portForward.Stop();
            sshClient.Disconnect();
        }
    }
}

或者在每个 SQL 语句的开头打开一个 SSH 连接?

using (var sshClient = setupSshClient()))
{
    sshClient.Connect();

    if (sshClient.IsConnected)
    {
        using (var portForward = setupPortForward()))
        {
            sshClient.AddForwardedPort(portForward);
            portForward.Start();

            executeSQLCommand1();

            portForward.Stop();
            sshClient.Disconnect();
        }
    }
}

using (var sshClient = setupSshClient()))
{
    sshClient.Connect();

    if (sshClient.IsConnected)
    {
        using (var portForward = setupPortForward()))
        {
            sshClient.AddForwardedPort(portForward);
            portForward.Start();

            executeSQLCommand2();

            portForward.Stop();
            sshClient.Disconnect();
        }
    }
}

众所周知,服务器有时会断开连接,所以我想第二种方法在重新建立连接的“更清洁”逻辑方面更好?或者还有其他更好的重新连接方式吗?

【问题讨论】:

  • 如果服务器倾向于断开连接,它甚至可以在某个命令的中间断开一个。所以无论如何你都必须处理重新连接。
  • setup+setup+forward+start+stop+disconnect需要多长时间?您的第二个选择是将 MySQL 的每秒查询数限制在此范围内。
  • 是否有理由让您在 SSH 连接之后执行 sql 命令,而不是使用相关数据库客户端库?当连接断开时,整个方法(无论是长时间运行还是单个命令)都可能会导致您出现问题,并且如果您使用数据库客户端,这将更容易处理。一些难以处理的问题是,如果连接断开,最后一个 SQL 命令是否成功完成?即使连接保持活动状态,解析输出流中的错误也会很麻烦。
  • 您的交易要求是什么?每个 sql 命令是原子的还是需要包装在事务中,如果是,那么您需要第一个长时间运行的连接方法。

标签: c# mysql database ssh ssh.net


【解决方案1】:

第 1 部分:最小化连接寿命。

SQL 连接 的一个常见“最佳实践”是您希望最小化连接打开时间 - 这意味着您在执行查询之前打开连接并在此之后关闭它。 SSH 连接也是如此。

您在使用后不处置的悬空资源有一个名称,它们被称为内存泄漏。

第 2 部分:使用事务确保数据库状态一致性

如果您的 SQL 查询事务中的单个语句失败,则该事务将失败。如果您想失败,请回滚错误前 DB 所处的状态,例如:连接已断开并稍后重试。

如果您不需要记录错误,那么您可以在事务之前使用set xact_abort on 自动回滚以防出现错误,例如:超时或断开连接。

更多信息

第 3 部分:创建重试策略

一般来说,最好的做法是你不想避免失败,而是接受它,快速失败并有办法再试一次。您为重试选择哪种策略取决于您。

如果您想做比手动重试更复杂的事情,那么我建议您看看 Rx observable(反应式扩展)或 Polly。它确实有一点学习曲线,但你会习惯的。

 // Policy to retry 5 times, waiting {2, 4, 8, 16, 32} seconds between retries.
 var policy = Policy
   .Handle<SqlException>()
   .WaitAndRetry(5, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)));

 policy.Execute(() => UpdateDatabase1(obj1));

【讨论】:

    猜你喜欢
    • 2014-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多