6

XML を取り込み、最終的に XML の情報に基づいてファイルをアップロードする API があります。アップロードはスケジュール通りに (XML からも) 行われ、私はそれに関するすべてをテストし、動作することを確認しました。

各時間サイクル (時間サイクル = 一部のファイルでは 45 分、他のファイルでは 30 分) でアップロードしようとする最初のファイルで約 40% の時間でエラーが発生します。

アップロード用のコードは次のとおりです。

try {
    LoggerFTP.Log("Uploading file: " + filename, false);

    // Create the request.
    FtpWebRequest request = (FtpWebRequest)WebRequest.Create(appSettingsFTP.ftpUrl + @"/" + filename);
    request.Method = WebRequestMethods.Ftp.UploadFile;
    request.Timeout = 6000000; //set to 100 minutes
    //request.Timeout = -1; //set to infinite

    // Add the login credentials.
    request.Credentials = new NetworkCredential(appSettingsFTP.ftpLogin, appSettingsFTP.ftpPassword);

    // Grab the file contents.
    StreamReader sourceStream = new StreamReader(appSettingsFTP.uploadFileDirectory + filename);
    byte[] fileContents = Encoding.UTF8.GetBytes(sourceStream.ReadToEnd());
    sourceStream.Close();
    request.ContentLength = fileContents.Length;

    // Copy the file contents to the outgoing stream.
    Stream requestStream = request.GetRequestStream();
    requestStream.Write(fileContents, 0, fileContents.Length);
    requestStream.Close();

    FtpWebResponse response = (FtpWebResponse)request.GetResponse();
    //Logger.Log(filename.ToString() + " " + "Upload Complete, Status: " + response.StatusCode + " " + response.StatusDescription, false);
    //Took response.StatusDescription out because it appears to be creating extra line feeds.
    LoggerFTP.Log(filename.ToString() + " " + "Upload Complete, Status: " + response.StatusCode, false);
}
catch (Exception ex) {
    LoggerFTP.Log(ex.ToString(), false);
}

私はこの問題を調査したところ、速度の問題である可能性があることについてオンラインで何かを見ました。同様に、タイムアウトがあります。しかし、FtpWebRequest のタイムアウトを 100 分に設定しているので、そうではないでしょうか? 知らない。これもサービスとして実行されるため、コードのこの側面をテストするのは困難です。

私のロガー(e.ToString)に記録されている例外は次のとおりです。

System.Net.WebException: System error. ---> System.Net.InternalException: System error.
   at System.Net.PooledStream.PrePush(Object expectedOwner)
   at System.Net.ConnectionPool.PutConnection(PooledStream pooledStream, Object owningObject, Int32 creationTimeout, Boolean canReuse)
   at System.Net.FtpWebRequest.FinishRequestStage(RequestStage stage)
   at System.Net.FtpWebRequest.SyncRequestCallback(Object obj)
   at System.Net.FtpWebRequest.RequestCallback(Object obj)
   at System.Net.CommandStream.Dispose(Boolean disposing)
   at System.IO.Stream.Close()
   at System.IO.Stream.Dispose()
   at System.Net.ConnectionPool.Destroy(PooledStream pooledStream)
   at System.Net.ConnectionPool.PutConnection(PooledStream pooledStream, Object owningObject, Int32 creationTimeout, Boolean canReuse)
   at System.Net.FtpWebRequest.AttemptedRecovery(Exception e)
   at System.Net.FtpWebRequest.SubmitRequest(Boolean async)
   --- End of inner exception stack trace ---
   at System.Net.FtpWebRequest.GetRequestStream()
   at CPMainSpringAPIExportsSC.UploadFTP.FTPUploadMethod(String viewname, String filename)
4

2 に答える 2

5

FTP over SSL を試みている SSIS パッケージでまったく同じスタック トレースを取得しています。SSL がなくても問題なく動作しますが、SSL を有効にするとすぐに爆発します。

    System.Net.WebException: System error. --->
    System.Net.InternalException: System error.    at
    System.Net.PooledStream.PrePush(Object expectedOwner)    at
    System.Net.ConnectionPool.PutConnection(PooledStream pooledStream, Object owningObject, Int32 creationTimeout, Boolean canReuse)    at
    System.Net.FtpWebRequest.FinishRequestStage(RequestStage stage)    at
    System.Net.FtpWebRequest.SyncRequestCallback(Object obj)    at
    System.IO.Stream.Close()    at
    System.Net.ConnectionPool.Destroy(PooledStream pooledStream)    at
    System.Net.ConnectionPool.PutConnection(PooledStream pooledStream, Object owningObject, Int32 creationTimeout, Boolean canReuse)    at
    System.Net.FtpWebRequest.AttemptedRecovery(Exception e)    at
    System.Net.FtpWebRequest.SubmitRequest(Boolean async)
    --- End of inner exception stack trace ---    at
    System.Net.FtpWebRequest.CheckError()    at
    System.Net.FtpWebRequest.GetRequestStream()    at
    ST_0ff7348de65a468bb358ab0206e3721f.ScriptMain.Main() in c:\Users\Stephens\AppData\Local\Temp\Vsta\e664c8a71bb647ff9e9dc6ac32d7b615\ScriptMain.cs:line 155 at 
    System.Net.FtpWebRequest.CheckError()    at
    System.Net.FtpWebRequest.GetRequestStream()    at
    ST_0ff7348de65a468bb358ab0206e3721f.ScriptMain.Main() in c:\Users\Stephens\AppData\Local\Temp\Vsta\e664c8a71bb647ff9e9dc6ac32d7b615\ScriptMain.cs:line 155

エラーは非常に一般的であるため、.NET ソースを調べて、何が壊れているかの手がかりをつかむことができるかどうかを確認することにしました。ここに行く場合:

http://labs.developerfusion.co.uk/SourceViewer/browse.aspx?assembly=SSCLI&namespace=System.Net#{%22pageClientState%22%3A%22type-2844%2Ccsharp%22}

281行目までスキップすると、例外が発生したときに実行されている内部 void PrePush(object expectedOwner) の定義が表示されます。これは次のようになります。

    internal void PrePush(object expectedOwner)
    {
        lock (this) {
            //3 // The following tests are retail assertions of things we can't allow to happen.
            if (null == expectedOwner) {
                if (null != m_Owner && null != m_Owner.Target)
                    throw new InternalException();
                // new unpooled object has an owner
            }
            else {
                if (null == m_Owner || m_Owner.Target != expectedOwner)
                    throw new InternalException();
                // unpooled object has incorrect owner
            }

            m_PooledCount++;

            if (1 != m_PooledCount)
                throw new InternalException();
            // pushing object onto stack a second time
            if (null != m_Owner)
                m_Owner.Target = null;
        }
    }

最終的に、FtpWebRequest は明示的 FTP (ポート 21) のみをサポートし、暗黙的 FTP (ポート 990) をサポートしないことがわかりました。これはここで明確に述べられていました:

.NET FtpWebRequest は暗黙的 (FTPS) と明示的 (FTPES) の両方をサポートしていますか?

とにかく、私の場合、それはファイアウォールの問題でした。当初、ポート 989、990、49152 ~ 65535 である暗黙的 FTP 用に構成しました (ベンダーの技術スタッフによる)。ネットワーク担当者に確認したところ、ポート 20、21、989、990、および 40000 ~ 655535 を明示的に開いたところ、その後はチャンピオンのように機能しました。

ただし、あなたの場合、接続プールの興奮が起こっているようです。この件に関する良い記事がここにあります:

FtpWebRequest のパフォーマンスを改善するには?

接続プールのセットアップをいじくり回してみて、ある程度の進歩が見られるかどうかを確認してください。お役に立てれば!

よろしく、

スチュアート

于 2015-05-20T23:38:47.673 に答える