C # SSH.NET - одно соединение SSH против нескольких соединений SSH - PullRequest
0 голосов
/ 10 января 2019

У меня есть приложение C #, которое использует библиотеку SSH.NET для подключения к серверу. Приложение выполняет команды SQL для базы данных несколькими способами.

Лучше ли иметь одно продолжительное SSH-соединение, которое охватывает все команды SQL, например:

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();
        }
    }
}

Или открыть SSH-соединение в начале каждого оператора SQL?

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();
        }
    }
}

Известно, что сервер иногда сбрасывает соединения, поэтому я полагаю, что второй метод лучше с точки зрения «более чистой» логики для восстановления соединения? Или есть какие-нибудь другие лучшие способы повторного подключения?

1 Ответ

0 голосов
/ 19 января 2019

Часть 1. Минимизируйте время жизни соединения.

Распространенная «лучшая практика» с соединениями SQL заключается в том, что вы хотите минимизировать время открытия соединения - это означает, что вы открываете соединение непосредственно перед выполнением запроса и закрываете это только после этого. То же относится и к SSH-соединениям .

У висящих ресурсов, которыми вы не избавляетесь после их использования, есть имя, и они называются утечки памяти .

Часть 2. Использование транзакций для обеспечения согласованности состояния БД

Если в одной транзакции SQL-запроса произойдет сбой одного оператора, транзакция завершится неудачей. Если вы хотите потерпеть неудачу, откатите состояние, в котором находилась БД до появления ошибки ex: соединение разорвано, и повторите попытку позже.

Если вам не нужно регистрировать ошибку, вы можете использовать set xact_abort on до того, как ваша транзакция автоматически откатится в случае ошибки ex: timeout или прервать соединение.

Для получения дополнительной информации

Часть 3. Создание политики повторных попыток

Как правило, лучшая практика заключается в том, что вы не хотите избегать неудачи, а вместо этого принимаете ее, быстро терпите неудачу и имеете возможность повторить попытку. Какую политику вы выбираете для повторной попытки, зависит от вас.

Если вы хотите сделать что-то более сложное, чем ручная повторная попытка, то я бы порекомендовал вам взглянуть на Rx наблюдаемый (реактивное расширение) или Полли. У этого есть немного кривой обучения, но вы привыкаете к этому.

 // 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));
...