2009-06-19 38 views
33

Tôi có một ứng dụng được viết bằng .NET 3.5 sử dụng FTP để tải lên/tải xuống tệp từ máy chủ. Ứng dụng hoạt động tốt nhưng có các vấn đề về hiệu suất:Làm thế nào để cải thiện hiệu suất của FtpWebRequest?

  1. Phải mất rất nhiều thời gian để kết nối với máy chủ FTP. Máy chủ FTP nằm trên một mạng khác và có Windows 2003 Server (IIS FTP). Khi nhiều tệp được xếp hàng để tải lên, thay đổi từ tệp này sang tệp khác sẽ tạo kết nối mới bằng FTPWebRequest và mất nhiều thời gian (khoảng 8-10 giây).

  2. Có thể tái sử dụng kết nối không? Tôi không chắc lắm về tài sản KeepAlive. Những kết nối nào được giữ lại và sử dụng lại.

  3. IIS-FTP trên Windows Server 2003 không hỗ trợ SSL để mọi người có thể dễ dàng nhìn thấy tên người dùng/mật khẩu thông qua gói sniffer như WireShark. Tôi thấy rằng Windows Server 2008 hỗ trợ SSL qua FTP trong phiên bản mới của nó nếu IIS 7.0.

Tôi về cơ bản muốn cải thiện hiệu suất tải lên/tải xuống của ứng dụng của mình. Bất cứ ý tưởng sẽ được đánh giá cao.

** Xin lưu ý rằng 3 không phải là một vấn đề nhưng tôi muốn mọi người có ý kiến ​​về nó

+3

3 không thực sự là một vấn đề hiệu suất (mặc dù nó vẫn là một vấn đề); Tôi muốn đề nghị giải quyết một cách riêng biệt. –

Trả lời

2

Cá nhân tôi đã di chuyển tất cả các ứng dụng của chúng tôi đi từ việc sử dụng FTP cho file upload/download, và thay vào đó lăn một giải pháp dựa trên XML Web Services trong ASP.NET.

Hiệu suất được cải thiện nhiều, bảo mật nhiều hay ít như bạn muốn mã (và bạn có thể sử dụng công cụ được tích hợp vào .NET) và tất cả có thể đi qua SSL mà không gặp vấn đề gì.

Tỷ lệ thành công của chúng tôi nhận được kết nối của khách hàng của chúng tôi thông qua tường lửa của riêng họ là FAR tốt hơn so với chạy FTP.

0

KeepAlive đang hoạt động. FtpWebRequest lưu trữ các kết nối bên trong, vì vậy chúng có thể được tái sử dụng sau một thời gian. Để biết chi tiết và giải thích về cơ chế này, bạn có thể xem ServicePoint.

Một nguồn thông tin khác là xem xét nguồn FtpWebRequest (bạn có thể làm điều đó trên VS2008).

3

Bạn chắc chắn nên xem BITS là một cải tiến lớn so với FTP. Các mật khẩu rõ ràng không phải là điểm yếu duy nhất trong FTP. Ngoài ra còn có vấn đề dự đoán cổng nó sẽ mở cho một tải lên thụ động hoặc tải về và chỉ khó khăn tổng thể khi khách hàng đang sử dụng NAT hoặc tường lửa.

BITS hoạt động qua HTTP/HTTPS bằng cách sử dụng tiện ích mở rộng IIS và hỗ trợ tải lên hàng đợi và tải xuống có thể được lên lịch ở mức độ ưu tiên thấp. Đó là tổng thể linh hoạt hơn rất nhiều so với FTP nếu bạn đang sử dụng Windows trên máy khách và máy chủ.

BITS for PowerShell

BITS for .NET

17

Nó không quan trọng nếu các kết nối cá nhân mất nhiều thời gian để kết nối miễn là bạn có thể khởi động nhiều song song. Nếu bạn có nhiều mục để chuyển (nói hàng trăm) thì có nghĩa là khởi chạy hàng chục và thậm chí hàng trăm WebRequests song song, sử dụng các phương thức không đồng bộ như BeginGetRequestStreamBeginGetResponse.Tôi đã làm việc trên các dự án phải đối mặt với các vấn đề tương tự (thời gian kết nối/xác thực lâu) nhưng bằng cách phát hành nhiều cuộc gọi song song với thông lượng tổng thể thực sự rất tốt.

Ngoài ra, điều này tạo ra sự khác biệt lớn nếu bạn use the async methods hoặc thiết bị đồng bộ, ngay khi bạn có nhiều (hàng chục, hàng trăm) yêu cầu. Điều này không chỉ áp dụng cho các phương pháp WebRequests của bạn mà còn áp dụng cho các phương pháp Luồng read/write mà bạn sẽ sử dụng sau khi tải luồng tải lên/tải xuống. The Improving .Net Performance and Scalability cuốn sách là một chút lỗi thời, nhưng nhiều lời khuyên của nó vẫn đứng, và là miễn phí để đọc trực tuyến.

Một điều cần xem xét là lớp học ServicePointManager ngồi ẩn nấp trong Framwework với một mục đích duy nhất: để hủy hoại hiệu suất của bạn. Đảm bảo bạn obtain the ServicePoint URL của mình và thay đổi ConnectionLimit thành giá trị hợp lý (ít nhất là bao nhiêu yêu cầu đồng thời bạn dự định).

+0

ServiceManager phải làm gì khi tôi chỉ sử dụng một kết nối duy nhất. Ứng dụng của tôi tải lên nhiều tệp một. Tôi nên đặt ConnectionLimit thành gì? Ngoài ra tôi quan sát thấy phải mất rất nhiều thời gian để tạo kết nối khi kết nối đã hoạt động. Thông thường phải mất 4,5 giây để FTP GetRequestStream đầu tiên() trả về. Sau đó tất cả các kết nối tiếp theo mất 1,3 giây nhưng nếu các kết nối chồng lên nhau, phải mất 12 giây để tạo kết nối. – A9S6

+1

Nếu kết nối đã hoạt động, kết nối thứ hai sẽ không kết nối cho đến khi kết nối đầu tiên kết thúc, đó là điều điều khiển ServiceManager (điều chỉnh kết nối thay cho bạn). Nếu bạn được dành riêng để sử dụng một kết nối và serialize tất cả các yêu cầu sau đó ServiceManager sẽ làm cho không có sự khác biệt. Quan điểm của tôi là làm tất cả các yêu cầu song song. –

+0

Đây là câu trả lời rất tốt, miễn là các tập tin được truy xuất không quá quan trọng, các yêu cầu sẽ được xử lý theo thứ tự chúng được tạo, nhưng rõ ràng chúng có thể hoàn thành vào các thời điểm khác nhau tùy thuộc vào kích thước của chuyển khoản. Nếu bạn yêu cầu chuyển giao nhất định hoàn thành trước khi những người khác (chẳng hạn như để kiểm soát thứ tự các tập tin được truy xuất được xử lý), đây có thể không phải là phương pháp lý tưởng. –

0

AFAIK, mỗi FtpWebRequest phải thiết lập kết nối mới - bao gồm đăng nhập vào máy chủ. Nếu bạn muốn tăng tốc độ truyền FTP, tôi khuyên bạn nên sử dụng một máy khách FTP thay thế. Một số khách hàng thay thế này có thể đăng nhập và sau đó thực hiện nhiều hành động bằng cách sử dụng cùng một kết nối lệnh.

Ví dụ về các khách hàng như vậy: http://www.codeproject.com/KB/IP/FtpClient.aspx cũng giải thích lý do tại sao các thư viện này có thể hoạt động nhanh hơn chuẩn FtpWebRequest và http://www.codeproject.com/KB/macros/ftp_class_library.aspx.

Cá nhân, tôi đã triển khai thực hiện FTP của riêng mình trong .NET 1.1 ngày trước khi FtpWebRequest được giới thiệu và điều này vẫn hoạt động tốt cho .NET 2.0 trở đi.

+0

http://msdn.microsoft.com/en-us/library/system.net.ftpwebrequest.keepalive.aspx – TheXenocide

1

Tôi khuyên bạn nên chuyển sang rsync.
Ưu điểm:
Được tối ưu hóa để giảm thời gian truyền.
Hỗ trợ SSH cho an toàn chuyển
Sử dụng TCP để làm cho CNTT của bạn dept/tường lửa chàng trai hạnh phúc hơn

Nhược điểm:
Không NET bản địa hỗ trợ
Geared hướng lắp đặt các máy chủ Linux - mặc dù có những cửa sổ đàng hoàng cổng như DeltaCopy

Nhìn chung mặc dù đó là một lựa chọn tốt hơn nhiều so với FTP

+0

FTP cũng sử dụng TCP – TheXenocide

5

gỡ lỗi mạng

Một vài thủ thuật để gỡ lỗi mạng đơn giản:

  1. Kiểm tra thời gian đáp ứng khi bạn ping máy chủ FTP từ máy chủ ứng dụng.
  2. Kiểm tra thời gian phản hồi cho tuyến đường theo dõi (tracert từ vỏ hệ điều hành DOS).
  3. Chuyển tệp từ dòng lệnh bằng cách sử dụng lệnh ftp.
  4. Kết nối với máy chủ FTP qua Telnet: telnet server 21.

Kết quả sẽ cung cấp manh mối để giải quyết vấn đề.

Mạng Phần cứng

Đối với một traceroute chậm:

  • Xác định lý do tại sao hai máy tính đang gặp vấn đề mạng.
  • Nâng cấp phần cứng mạng giữa liên kết chậm nhất.

Cấu hình mạng

Đối với một ping chậm:

  • Kiểm tra cấu hình mạng trên mỗi máy.
  • Đảm bảo cài đặt tối ưu.

Validate API

Một dòng lệnh chậm phiên FTP sẽ cho bạn biết rằng vấn đề không được cô lập để API FTP mà bạn đang sử dụng. Nó không loại bỏ các API như là một vấn đề tiềm năng, nhưng chắc chắn làm cho nó ít có khả năng.

lỗi Mạng

Nếu gói dữ liệu đang được giảm giữa nguồn và đích, ping sẽ cho bạn biết. Bạn có thể phải tăng kích thước gói lên 1500 byte để xem bất kỳ lỗi nào.

FTP server Queue

Nếu bạn không có quyền kiểm soát máy chủ đích FTP, có một máy chủ trung gian nhận file được tải lên. Các trung gian sau đó sẽ gửi các tập tin đến máy chủ từ xa ở tốc độ bất kỳ nó có thể. Điều này cho phép ảo tưởng rằng các tập tin đang được gửi một cách nhanh chóng. Tuy nhiên, nếu các tệp phải tồn tại trên máy chủ từ xa ngay sau khi chúng được tải lên, thì giải pháp này có thể không khả thi.

FTP Server Software

Sử dụng một daemon FTP khác nhau trên máy chủ FTP, như ProFTPd như một Windows service. (ProFTPD có plug-in cho cơ sở dữ liệu khác nhau mà cho phép xác thực sử dụng các truy vấn SQL.)

FTP Server Hệ điều hành

Một Unix dựa trên hệ điều hành có thể là một lựa chọn tốt hơn so với một Microsoft dựa trên.

FTP Client Software

Có một số các API khác nhau cho việc gửi và nhận file qua FTP. Nó có thể mất một số công việc để làm cho ứng dụng của bạn đủ mô-đun mà bạn có thể chỉ cần cắm vào một dịch vụ chuyển tập tin mới. Một vài API khác nhau được liệt kê dưới dạng câu trả lời ở đây.

Nghị định thư thay thế

Nếu FTP không phải là một yêu cầu tuyệt đối, hãy thử:

  • một mạng Windows ổ
  • HTTPS
  • scp, rsync, hoặc các chương trình tương tự (Cygwin có thể bắt buộc)
35

Tôi đã thực hiện một số thử nghiệm (tải lên khoảng 20 tập tin trên kích cỡ khác nhau) trên FtpWebRequest với các yếu tố sau

KeepAlive = true/false

ftpRequest.KeepAlive = isKeepAlive; 

connnection Group Name = UserDefined hoặc null

ftpRequest.ConnectionGroupName = "MyGroupName"; 

giới hạn kết nối = 2 (mặc định) hoặc 4 hoặc 8

ftpRequest.ServicePoint.ConnectionLimit = ConnectionLimit; 

Chế độ = Synchronous hoặc async

thấy this example

kết quả của tôi:

  1. Sử dụng ConnectionGroupName, KeepAlive = true (21188.62 m giây)

  2. Sử dụng ConnectionGroupName, KeepAlive = false mất (53.449,00 msec)

  3. Không ConnectionGroupName, KeepAlive = false mất (40.335,17 msec)

  4. Sử dụng ConnectionGroupName, KeepAlive = true; async = true, kết nối = 2 mất (11.576,84 msec)

  5. Sử dụng ConnectionGroupName, KeepAlive = true; async = true, kết nối = 4 mất (10.572,56 msec)

  6. Sử dụng ConnectionGroupName, KeepAlive = true; async = true, các kết nối = 8 mất (10598.76 msec)

Kết luận

  1. FtpWebRequest đã được thiết kế để hỗ trợ bể bơi kết nối nội bộ. Để đảm bảo, nhóm kết nối được sử dụng, chúng tôi phải đảm bảo rằng ConnectionGroupName đang được đặt.

  2. Thiết lập kết nối tốn kém. Nếu chúng ta đang kết nối với cùng một máy chủ ftp bằng cách sử dụng cùng một thông tin xác thực, việc giữ cờ còn sống được đặt thành true sẽ giảm thiểu số lượng thiết lập kết nối.

  3. Không đồng bộ là cách được khuyến nghị nếu bạn có nhiều tệp để ftp.

  4. Số kết nối mặc định là 2. Trong môi trường của tôi, giới hạn kết nối 4 sẽ mang lại cho tôi hiệu suất tổng thể cao nhất. Tăng số lượng kết nối có thể hoặc không thể cải thiện hiệu suất. Tôi khuyên bạn nên có giới hạn kết nối như một tham số cấu hình để bạn có thể điều chỉnh tham số này trong môi trường của mình.

Hy vọng bạn sẽ thấy điều này hữu ích.

+4

Trong khi tôi đồng ý với hầu hết các ý kiến ​​của bạn, tôi nghĩ rằng thử nghiệm của bạn là rất đáng nghi. "21188.62 msec"? Bạn có thể muốn nói "21" thay vào đó. Bạn đã chạy điều này một lần hay nhiều lần và trung bình kết quả? Kết luận rằng các kết nối = 4 mang lại lợi ích cao nhất từ ​​chênh lệch 30ms là không khả thi. Không có ý định phạm tội, nhưng thử nghiệm vì nó không hữu ích, thay vì gây hiểu nhầm. - Nếu bạn có thể khắc phục các vấn đề (độ chính xác so với độ chính xác, nhiều lần chạy, nhiều tệp hơn, giải thích nền, v.v) thì đây sẽ là một bài đăng hay. – mafu

+2

Tôi nghi ngờ rằng anh ta/cô ấy đã gõ "21188.62 msec" một cách tình cờ. Có lẽ bạn muốn nói "thời gian liệt kê trong vài giây sẽ dễ đọc hơn"? Và tôi không nghĩ rằng bài kiểm tra không hữu ích. Có thể rút ra kết luận về một tập hợp dữ liệu bị hạn chế, nhưng dữ liệu có ở đó nếu bạn muốn sử dụng nó. Ít nhất đó là điểm khởi đầu. – d512

0

Single Point lời khuyên:

LOWER BUFFER/Chunk-kích cỡ đáng kể làm giảm hiệu suất

Lý do: Nhiều đĩa hơn i/o, bộ nhớ i/o, bước sóng initp và nhiều yếu tố khác

1

Để giải quyết vấn đề về hiệu suất bạn chỉ cần đặt:

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

1

Tôi biết đó là một chủ đề cũ, nhưng gần đây tôi đã phải trải qua một tình huống tương tự.

Chúng tôi cần tải xuống hơn 70 tệp XML từ máy chủ FTP dưới 25 phút mà không cần mở hơn 5 kết nối trong khung thời gian đó.

Đây là tất cả các lựa chọn thay thế chúng tôi cố gắng:

  • wget - Nó được nhanh, nhưng mỗi GET có nghĩa là một kết nối mới. Chúng tôi phải dừng lại do số lượng kết nối được tạo ra. Chúng tôi đã gặp phải một số vấn đề với GETM được ghi chép đầy đủ trên web để không phải là một lựa chọn.
  • FtpWebRequest - Mỗi cuộc gọi Tạo sẽ ghi lại kết nối mới, mặc dù chúng tôi đã sử dụng thuộc tính KeepAlive và ConnectionGroupName. Cộng với nó rất chậm.
  • Webclient - Chúng tôi đã không kiểm tra xem nó có tạo kết nối mới cho mỗi tệp hay không (mặc dù tôi giả định nó), nhưng nó đã sao chép 1 tệp/phút. Vì vậy, nó không phải là một lựa chọn.

Chúng tôi đã kết thúc bằng cách sử dụng tập lệnh theo lô hàng cũ. Nó nhanh và tôi chỉ sử dụng một kết nối để tải xuống tất cả các tệp. Nó không phải là linh hoạt, nhưng nó nhanh hơn nhiều so với mọi thứ khác mà tôi đã thử (75 tệp trong chưa đầy 20 phút).

-1

tôi đã làm việc một vài ngày với điều đó ... và tốc độ thực sự thấp, không có gì để so sánh với FileZilla ... cuối cùng tôi đã giải quyết với đa luồng. 10 đề làm cho các kết nối để tải về mang lại cho tôi một tỷ lệ tốt, thậm chí có thể được cải thiện hơn .. với cấu hình standar 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) 
-1

Hãy thử điều này bên dưới mã, bạn sẽ nhận được performence tốt hơn:

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); 
      } 
     } 
    } 
} 
Các vấn đề liên quan