Подтвердить что ты не робот

Как улучшить производительность FtpWebRequest?

У меня есть приложение, написанное на .NET 3.5, которое использует FTP для загрузки/загрузки файлов с сервера. Приложение работает нормально, но есть проблемы с производительностью:

  • Для подключения к FTP-серверу требуется много времени. FTP-сервер находится в другой сети и имеет Windows 2003 Server (IIS FTP). Когда несколько файлов загружаются в очередь для загрузки, изменение из одного файла в другое создает новое соединение с использованием FTPWebRequest, и это занимает много времени (около 8-10 секунд).

  • Возможно ли повторное использование соединения? Я не очень уверен в свойстве KeepAlive. Какие соединения поддерживаются в живых и повторно используются.

  • IIS-FTP в Windows Server 2003 не поддерживает SSL, поэтому каждый может легко увидеть имя пользователя/пароль с помощью анализатора пакетов, например WireShark. Я обнаружил, что Windows Server 2008 поддерживает SSL через FTP в своей новой версии, если IIS 7.0.

В основном я хочу улучшить производительность загрузки/загрузки своего приложения. Любые идеи будут оценены.

** Обратите внимание, что 3 не является проблемой, но я бы хотел, чтобы у людей были комментарии к ней.

4b9b3361

Ответ 1

Я провел несколько экспериментов (загружая около 20 файлов разных размеров) в FtpWebRequest со следующими факторами

KeepAlive= true/false

ftpRequest.KeepAlive = isKeepAlive;

Имя группы подключений= UserDefined или null

ftpRequest.ConnectionGroupName = "MyGroupName";

Лимит подключения= 2 (по умолчанию) или 4 или 8

ftpRequest.ServicePoint.ConnectionLimit = ConnectionLimit;

Режим= Синхронный или Async

см. этот пример

Мои результаты:

  • Используйте ConnectionGroupName, KeepAlive = true (21188.62 мс)

  • Используйте ConnectionGroupName, KeepAlive = false took (53449.00 мс)

  • Нет ConnectionGroupName, KeepAlive = false принят (40335.17 мс)

  • Используйте ConnectionGroupName, KeepAlive = true, async = true, connections = 2 занял (11576.84 мс)

  • Используйте ConnectionGroupName, KeepAlive = true, async = true, connections = 4 занял (10572,56 мс)

  • Использовать ConnectionGroupName, KeepAlive = true, async = true, connections = 8 занял (10598.76 мс)

Выводы

  • FtpWebRequest был разработан для поддержки внутреннего пула подключений. Чтобы убедиться, что пул соединений используется, мы должны убедиться, что установлен ConnectionGroupName.

  • Настройка соединения стоит дорого. Если мы подключаемся к одному и тому же ftp-серверу с использованием тех же учетных данных, если флаг keep alive установлен в true, это уменьшит количество настроек соединений.

  • Асинхронный режим рекомендуется, если у вас много файлов на ftp.

  • Число подключений по умолчанию - 2. В моей среде ограничение соединения в 4 даст мне наиболее общий прирост производительности. Увеличение количества подключений может или не может повысить производительность. Я бы рекомендовал, чтобы у вас был лимит соединения в качестве параметра конфигурации, чтобы вы могли настроить этот параметр в своей среде.

Надеюсь, вы найдете это полезным.

Ответ 2

Не имеет значения, если отдельные соединения занимают много времени, чтобы подключаться, пока вы можете запускать многие параллельно. Если у вас есть много предметов для передачи (скажем, сотен), тогда имеет смысл запускать десятки и даже сотни WebRequests параллельно, используя асинхронные методы, такие как BeginGetRequestStream и BeginGetResponse. Я работал над проектами, которые сталкивались с аналогичными проблемами (длительное время соединения/аутентификации), но, выдавая много вызовов параллельно, общая пропускная способность была на самом деле очень хорошей.

Также очень важно, если вы используете методы асинхронизации или синхронные, как только у вас будет много (десятков, сотен) запросов. Это относится не только к вашим методам WebRequests, но также к вашему потоку read/write, которые вы будете использовать после получения потока загрузки/загрузки. Улучшенная производительность и масштабируемость .Net немного устарела, но большая часть ее рекомендаций по-прежнему стоит и доступна для чтения в Интернете.

Следует учитывать, что класс ServicePointManager сидит там в рамках проекта Framwework с единственной целью: разрушить вашу производительность. Убедитесь, что получите ServicePoint вашего URL-адреса и измените ConnectionLimit к разумному значению (по крайней мере, как много одновременных запросов, которые вы намерены).

Ответ 3

Отладка сети

Несколько трюков для простой отладки сети:

  • Проверьте время ответа при отправке FTP-сервера с сервера приложений.
  • Проверьте время ответа для маршрута трассировки (tracert из оболочки DOS).
  • Перенесите файл из командной строки с помощью команды ftp.
  • Подключитесь к FTP-серверу через Telnet: telnet server 21.

Результаты предоставят ключ к решению проблемы.

Сетевое оборудование

Для медленного маршрута трассировки:

  • Определите, почему на двух компьютерах возникают проблемы с сетью.
  • Обновите сетевое оборудование между самой медленной ссылкой.

Конфигурация сети

Для медленного пинга:

  • Проверьте конфигурацию сети на каждом компьютере.
  • Убедитесь, что настройки оптимальны.

Проверить API

Медленная сессия FTP в командной строке скажет вам, что проблема не изолирована от API FTP, который вы используете. Он не устраняет API как потенциальную проблему, но, безусловно, делает его менее вероятным.

Сетевые ошибки

Если пакеты отправляются между источником и получателем, ping скажет вам. Возможно, вам придется увеличить размер пакета до 1500 байтов, чтобы увидеть какие-либо ошибки.

Сервер очереди FTP

Если у вас нет контроля над FTP-сервером назначения, попросите посреднический сервер получать загруженные файлы. Затем посредник отправляет файлы на удаленный сервер с любой скоростью. Это дает иллюзию, что файлы отправляются быстро. Однако, если файлы должны существовать на удаленном сервере, как только они будут загружены, это решение может оказаться нецелесообразным.

Программное обеспечение FTP-сервера

Использовать другой FTP-демон на FTP-сервере, например ProFTPd как Служба Windows. (ProFTPd имеет плагины для различных баз данных, которые позволяют аутентификацию с использованием SQL-запросов.)

Операционная система FTP-сервера

Операционная система на основе Unix может быть лучшим вариантом, чем Microsoft.

Программное обеспечение FTP-клиента

Существует множество различных API-интерфейсов для отправки и получения файлов по FTP. Может потребоваться некоторая работа, чтобы сделать ваше приложение достаточно модульным, чтобы вы могли просто подключить новую службу передачи файлов. Здесь перечислены несколько различных API-интерфейсов.

Альтернативный протокол

Если FTP не является абсолютным требованием, попробуйте:

  • сетевой диск Windows
  • HTTPS
  • scp, rsync или аналогичные программы (Cygwin может потребоваться)

Ответ 5

Вы должны обязательно проверить BITS, что является большим улучшением по сравнению с FTP. Явные текстовые пароли не являются единственной слабостью в FTP. Там также проблема прогнозирования порта, который он откроет для пассивной загрузки или загрузки, и просто общая сложность, когда клиенты используют NAT или брандмауэры.

BITS работает через HTTP/HTTPS с использованием расширений IIS и поддерживает загрузку и загрузку в очереди, которые могут быть запланированы с низким приоритетом. В общем, он намного более гибкий, чем FTP, если вы используете Windows на клиенте и сервере.

BITS для PowerShell

BITS для .NET

Ответ 6

Лично я перенес все наши приложения от использования FTP для загрузки/загрузки файлов и вместо этого развернул решение на основе XML Web Services в ASP.NET.

Производительность значительно улучшена, безопасность - столько же или меньше, сколько вы хотите закодировать (и вы можете использовать материал, встроенный в .NET), и он может переходить через SSL без проблем.

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

Ответ 7

Посмотрите на эту страницу - http://www.ietf.org/rfc/rfc959.txt

Он говорит об использовании другого порта при подключении для повторного использования соединения.
Это работает?

Ответ 8

Я настоятельно рекомендую Starksoft FTP/FTPS Component для .NET и Mono. Он имеет объект соединения, который можно кэшировать и повторно использовать.

Ответ 9

Я бы рекомендовал переключиться на rsync.
Плюсы:
Оптимизирован для сокращения времени передачи.
Поддержка SSH для безопасного перевода
Использует TCP, поэтому ваши ребята из отдела ИТ/брандмауэров счастливы

Минусы:
Нет поддержки на родной .NET
Исправлена ​​установка Linux-сервера - хотя есть приличные порты Windows, такие как DeltaCopy

В целом, хотя это гораздо лучший выбор, чем FTP

Ответ 11

Чтобы решить проблему производительности, вам просто нужно установить:

ftpRequest.ConnectionGroupName = "MyGroupName"; ftpRequest.KeepAlive = false; ftpRequest.ServicePoint.CloseConnectionGroup("MyGroupName");

Ответ 12

Я знаю, что это старый поток, но мне недавно пришлось пройти аналогичную ситуацию.

Нам нужно было загрузить 70 + XML файлов с ftp-сервера менее чем за 25 минут, не открывая более 5 подключений в течение этого временного кадра.

Это были все альтернативы, которые мы пробовали:

  • wget - это было быстро, но каждый GET означал новое соединение. Мы должны были остановиться из-за количества созданных соединений. У нас были некоторые проблемы с GETM, которые хорошо документированы в Интернете, так что это не вариант.
  • FtpWebRequest - каждый вызов Create будет регистрировать новое соединение, даже если мы использовали свойства KeepAlive и ConnectionGroupName. Плюс это было очень медленно.
  • Webclient - Мы не проверяли, создало ли оно новое соединение для каждого файла (хотя я предполагаю, что он это делает), но он скопировал 1 файл/минуту. Так что это был не вариант.

Мы закончили использование старомодной партии ftp script. Это быстро, и я использую только одно соединение для загрузки всех файлов. Он не является гибким, но он намного быстрее, чем все, что я пробовал (75 файлов менее чем за 20 минут).

Ответ 13

KeepAlive работает. FtpWebRequest кэширует соединения внутри, поэтому их можно повторно использовать через некоторое время. Для получения подробной информации и объяснения этого механизма вы можете посмотреть ServicePoint.

Другим хорошим источником информации является поиск источника FtpWebRequest (вы можете сделать это на VS2008).

Ответ 14

AFAIK, каждый FtpWebRequest должен установить новое соединение - включая вход на сервер. Если вы хотите ускорить передачу FTP, я бы рекомендовал вместо этого использовать альтернативный FTP-клиент. Некоторые из этих альтернативных клиентов могут войти в систему, а затем выполнить несколько действий с использованием того же командного соединения.

Примеры таких клиентов включают: http://www.codeproject.com/KB/IP/FtpClient.aspx, который также содержит хорошее объяснение того, почему эти библиотеки могут работать быстрее, чем стандартный FtpWebRequest и http://www.codeproject.com/KB/macros/ftp_class_library.aspx, который также выглядит довольно простой.

Лично я включил собственную реализацию FTP в .NET за 1.1 дней до появления FtpWebRequest, и это все еще хорошо работает для .NET 2.0 и далее.

Ответ 15

Единый совет:

НИЖНИЙ БУФЕР/ЧУН-РАЗМЕРЫ ЗНАЧИТЕЛЬНО СОКРАЩАЮТСЯ РЕЗУЛЬТАТЫ РАБОТЫ

Причина: еще много дисковых операций ввода-вывода, ввода-вывода памяти, потока ftp-потоков и многих других факторов.

Ответ 16

Попробуйте этот ниже код, вы получите лучшую производительность:

private void Upload144_Click(object sender, EventArgs e)
{
    OpenFileDialog fileobj = new OpenFileDialog();
    fileobj.InitialDirectory = "C:\\";
    //fileobj.Filter = "Video files (*.mp4)";
    //fileobj.ShowDialog();

    if (fileobj.ShowDialog() == DialogResult.OK)
    {
        if (fileobj.CheckFileExists)
        {
            string test = Properties.Settings.Default.Connection;
            SqlConnection con = new SqlConnection(test);
            con.Open();
            string correctfilename = System.IO.Path.GetFileName(fileobj.FileName);
            SqlCommand cmd = new SqlCommand("Insert into Path(ID,Path5) VALUES   ((select isnull(MAX(id),0) + 1 from Path),'\\Videos\\" + correctfilename + "')", con);

            cmd.ExecuteNonQuery();

            string path = Application.StartupPath.Substring(0, Application.StartupPath.Length - 10);
            con.Close();

            //For Progressbar
            DataTable dt = new DataTable();
       //   SqlDataAdapter da = new SqlDataAdapter(cmd);
       //   da.Fill(dt);

            timer5.Enabled = true;

            // FOR FtpServer File Upload::
            string uploadfile = fileobj.FileName;
            string uploadFileName = new FileInfo(uploadfile).Name;

            string uploadUrl = "ftp://ftp.infotech.com/";
            FileStream fs = new FileStream(uploadfile, FileMode.Open, FileAccess.Read);
            try
            {
                long FileSize = new FileInfo(uploadfile).Length; // File size of file being uploaded.
                Byte[] buffer = new Byte[FileSize];

                fs.Read(buffer, 0, buffer.Length);

                fs.Close();
                fs = null;
                string ftpUrl = string.Format("{0}/{1}", uploadUrl, uploadFileName);
                FtpWebRequest requestObj = FtpWebRequest.Create(ftpUrl) as FtpWebRequest;
                requestObj.Method = WebRequestMethods.Ftp.UploadFile;
                requestObj.Credentials = new NetworkCredential("[email protected]", "[email protected]");
                Stream requestStream = requestObj.GetRequestStream();
                requestStream.Write(buffer, 0, buffer.Length);

                requestStream.Flush();
                requestObj = null;
            }
            catch (Exception ex)
            {
                //MessageBox.Show("File upload/transfer Failed.\r\nError Message:\r\n" + ex.Message, "Succeeded", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }
    }
}

Ответ 17

Я работал несколько дней с этим... и скорость была действительно низкой, ничего не сравнивалось с FileZilla... наконец, я решил с помощью multithreads. 10 потоков, создающих соединения для загрузки, дают мне хорошую скорость, возможно, даже можно улучшить больше.. с стандартной конфигурацией ftprequest

PeticionFTP.ConnectionGroupName = "MyGroupName"
PeticionFTP.ServicePoint.ConnectionLimit = 4
PeticionFTP.ServicePoint.CloseConnectionGroup("MyGroupName")

PeticionFTP.KeepAlive = False 
PeticionFTP.UsePassive = False

PeticionFTP.UseBinary = True

PeticionFTP.Credentials = New NetworkCredential(lHost.User, lHost.Password)