简体   繁体   English

C#+ Mono:运行Azure-Storage SDK时出错

[英]C# + Mono: Error while running Azure-Storage SDK

I have a application that running great on Windows environment. 我有一个在Windows环境下运行良好的应用程序。 The application written with C# 4.6.1 and using Azure Storage to upload\\download blobs. 用C#4.6.1编写并使用Azure存储上载\\下载Blob的应用程序。

I want to run the same application on linux ubuntu server (v16). 我想在linux ubuntu服务器(v16)上运行相同的应用程序。 After installing mono on the server, I tried to run the application. 在服务器上安装了单声道后,我尝试运行该应用程序。 The program crashed with exception. 该程序异常崩溃。

So, I added logs and found that the problem comming from Azure-Storage SDK (v7.0.0, installed via nu-get). 因此,我添加了日志,发现问题出自Azure-Storage SDK(v7.0.0,通过nu-get安装)。

This is my relevant code: 这是我的相关代码:

CloudBlockBlob blob = container.GetBlockBlobReference(string.Join("", blob_path));
using (MemoryStream ms = new MemoryStream())
{
    blob.DownloadToStream(ms); // <--- BOOM
    //...
}

This is the exception I get when running with Mono: 这是我在使用Mono运行时遇到的异常:

Microsoft.WindowsAzure.Storage.StorageException: read failed 
---> System.IO.IOException: read failed 
---> System.InvalidOperationException: Operation is not valid due to the current state of the object.
  at Mono.Net.Security.MobileAuthenticatedStream.CheckThrow (System.Boolean authSuccessCheck) [0x0001b] in <2b0d86369d72459baed0cee98a8e578a>:0 
  at Mono.Net.Security.MobileAuthenticatedStream.get_Context () [0x00000] in <2b0d86369d72459baed0cee98a8e578a>:0 
  at Mono.Net.Security.MobileAuthenticatedStream.ProcessRead (Mono.Net.Security.AsyncProtocolRequest asyncRequest, Mono.Net.Security.AsyncOperationStatus status) [0x00011] in <2b0d86369d72459baed0cee98a8e578a>:0 
  at Mono.Net.Security.AsyncProtocolRequest.ProcessOperation (Mono.Net.Security.AsyncOperationStatus status) [0x0006b] in <2b0d86369d72459baed0cee98a8e578a>:0 
  at Mono.Net.Security.AsyncProtocolRequest.ProcessOperation () [0x0000d] in <2b0d86369d72459baed0cee98a8e578a>:0 
  at Mono.Net.Security.AsyncProtocolRequest.StartOperation () [0x00000] in <2b0d86369d72459baed0cee98a8e578a>:0 
   --- End of inner exception stack trace ---
  at Mono.Net.Security.MobileAuthenticatedStream.EndReadOrWrite (System.IAsyncResult asyncResult, Mono.Net.Security.AsyncProtocolRequest& nestedRequest) [0x00055] in <2b0d86369d72459baed0cee98a8e578a>:0 
  at Mono.Net.Security.MobileAuthenticatedStream.EndRead (System.IAsyncResult asyncResult) [0x00000] in <2b0d86369d72459baed0cee98a8e578a>:0 
  at System.Net.WebConnection.EndRead (System.Net.HttpWebRequest request, System.IAsyncResult result) [0x000d4] in <2b0d86369d72459baed0cee98a8e578a>:0 
  at System.Net.WebConnectionStream.EndRead (System.IAsyncResult r) [0x000af] in <2b0d86369d72459baed0cee98a8e578a>:0 
  at Microsoft.WindowsAzure.Storage.Core.ByteCountingStream.EndRead (System.IAsyncResult asyncResult) [0x00000] in <1a6da444611441028237826045bb8126>:0 
  at Microsoft.WindowsAzure.Storage.Core.Util.StreamExtensions.WriteToSync[T] (System.IO.Stream stream, System.IO.Stream toStream, System.Nullable`1[T] copyLength, System.Nullable`1[T] maxLength, System.Boolean calculateMd5, System.Boolean syncRead, Microsoft.WindowsAzure.Storage.Core.Executor.ExecutionState`1[T] executionState, Microsoft.WindowsAzure.Storage.Core.Util.StreamDescriptor streamCopyState) [0x002c6] in <1a6da444611441028237826045bb8126>:0 
  at Microsoft.WindowsAzure.Storage.Core.Executor.Executor.ExecuteSync[T] (Microsoft.WindowsAzure.Storage.Core.Executor.RESTCommand`1[T] cmd, Microsoft.WindowsAzure.Storage.RetryPolicies.IRetryPolicy policy, Microsoft.WindowsAzure.Storage.OperationContext operationContext) [0x003c7] in <1a6da444611441028237826045bb8126>:0 
   --- End of inner exception stack trace ---
  at Microsoft.WindowsAzure.Storage.Core.Executor.Executor.ExecuteSync[T] (Microsoft.WindowsAzure.Storage.Core.Executor.RESTCommand`1[T] cmd, Microsoft.WindowsAzure.Storage.RetryPolicies.IRetryPolicy policy, Microsoft.WindowsAzure.Storage.OperationContext operationContext) [0x006b5] in <1a6da444611441028237826045bb8126>:0 
  at Microsoft.Wind… Read more                        
  at Microsoft.WindowsAzure.Storage.Core.ByteCountingStream.EndRead (System.IAsyncResult asyncResult) [0x00000] in <1a6da444611441028237826045bb8126>:0 
  at Microsoft.WindowsAzure.Storage.Core.Util.StreamExtensions.WriteToSync[T] (System.IO.Stream stream, System.IO.Stream toStream, System.Nullable`1[T] copyLength, System.Nullable`1[T] maxLength, System.Boolean calculateMd5, System.Boolean syncRead, Microsoft.WindowsAzure.Storage.Core.Executor.ExecutionState`1[T] executionState, Microsoft.WindowsAzure.Storage.Core.Util.StreamDescriptor streamCopyState) [0x002c6] in <1a6da444611441028237826045bb8126>:0
  at Microsoft.WindowsAzure.Storage.Core.Executor.Executor.ExecuteSync[T] (Microsoft.WindowsAzure.Storage.Core.Executor.RESTCommand`1[T] cmd, Microsoft.WindowsAzure.Storage.RetryPolicies.IRetryPolicy policy, Microsoft.WindowsAzure.Storage.OperationContext operationContext) [0x003c7] in <1a6da444611441028237826045bb8126>:0 
   --- End of inner exception stack trace ---
  at Microsoft.WindowsAzure.Storage.Core.Executor.Executor.ExecuteSync[T] (Microsoft.WindowsAzure.Storage.Core.Executor.RESTCommand`1[T] cmd, Microsoft.WindowsAzure.Storage.RetryPolicies.IRetryPolicy policy, Microsoft.WindowsAzure.Storage.OperationContext operationContext) [0x006b5] in <1a6da444611441028237826045bb8126>:0 
  at Microsoft.WindowsAzure.Storage.Blob.CloudBlob.DownloadRangeToStream (System.IO.Stream target, System.Nullable`1[T] offset, System.Nullable`1[T] length, Microsoft.WindowsAzure.Storage.AccessCondition accessCondition, Microsoft.WindowsAzure.Storage.Blob.BlobRequestOptions options, Microsoft.WindowsAzure.Storage.OperationContext operationContext) [0x00033] in <1a6da444611441028237826045bb8126>:0 
  at Microsoft.WindowsAzure.Storage.Blob.CloudBlob.DownloadToStream (System.IO.Stream target, Microsoft.WindowsAzure.Storage.AccessCondition accessCondition, Microsoft.WindowsAzure.Storage.Blob.BlobRequestOptions options, Microsoft.WindowsAzure.Storage.OperationContext operationContext) [0x00000] in <1a6da444611441028237826045bb8126>:0 
  at ***.DownloadFile (System.Uri url, System.IO.FileInfo file) [0x000e8] in <1a85ad8f477c4d6f8a3af08c9e99e976>:0 
  at ***.TimedCache+<Add>d__32.MoveNext () [0x00160] in <1a85ad8f477c4d6f8a3af08c9e99e976>:0 
Request Information
RequestID:2025b933-0001-0031-2325-10951e000000
RequestDate:Tue, 08 Aug 2017 09:08:58 GMT
StatusMessage:Partial Content

The Linux machine is running under Google-Cloud. Linux机器在Google-Cloud下运行。 One direction for solving this is the Goolge-Cloud firewall. 解决此问题的一个方向是Goolge-Cloud防火墙。 Maybe the firewall blocking the communication with Azure-Storage? 也许防火墙阻止了与Azure存储的通信?

My code is basically downloading a blob from the storage and save it locally. 我的代码基本上是从存储下载blob并将其保存在本地。 The strange thing is that when I checking the directory, where the files are being saved, I can find there some files. 奇怪的是,当我检查文件所在的目录时,可以在其中找到一些文件。 What's mean, it's working part of the times. 意思是,它在部分时间是有效的。

How to solve the problem? 如何解决问题?

UPDATE 更新

According to @Amor, I tried to understand where is the problem. 根据@Amor,我试图了解问题出在哪里。 We have two options: 我们有两种选择:

  • The problem is with the C# code or Mono. 问题出在C#代码或Mono。
  • The problem is with the environment (Linux \\ google-cloud \\ ...) 问题出在环境上(Linux \\ google-cloud \\ ...)

I downloaded the code called "Storage_REST_CS.zip" on this page . 我在此页面上下载了名为“ Storage_REST_CS.zip”的代码。 Update the code as needed (insert my credientials) and tested it in Windows environment - working good. 根据需要更新代码(插入我的证书),并在Windows环境中对其进行测试-运行良好。 I took the binaries and moved them to test it on my Linux machine. 我将二进制文件移到Linux计算机上进行测试。 I got error: 我收到错误消息:

System.Net.WebException: The remote server returned an error: (403) Server failed to authenticate the request. Make sure the value of Authorization headers formed correctly including the signature.
    at StorageSampleREST.RESTHelper.Retry[T] (StorageSampleREST.RESTHelper+RetryDelegate`1[T] del, System.Int32 numberOfRetries, System.Int32 msPause) [0x0001d] in <033ea4d1a16740f3b711001b7c2f09f5>:0 
    at StorageSampleREST.RESTHelper.Retry[T] (StorageSampleREST.RESTHelper+RetryDelegate`1[T] del) [0x00001] in <033ea4d1a16740f3b711001b7c2f09f5>:0 
    at StorageSampleREST.BlobHelper.ListContainers () [0x00001] in <033ea4d1a16740f3b711001b7c2f09f5>:0 
    at StorageSampleREST.Program.TestBlobStorage () [0x00023] in <033ea4d1a16740f3b711001b7c2f09f5>:0

Now I tried to understand where is the problem - In my code (c#) or with the environment (Linux - Google cloud). 现在,我试图了解问题出在哪里-在我的代码(c#)中或在环境中(Linux-Google cloud)。 So I extracted the HTTP request that executed (with failure on Mono) and tried to run it with cURL directly: 因此,我提取了已执行的HTTP请求(Mono失败),并尝试直接使用cURL运行它:

curl -i -H "x-ms-date: Wed, 09 Aug 2017 09:03:46 GMT
x-ms-version: 2009-09-19
Authorization: SharedKey userfiles:***" -X GET https://***.blob.core.windows.net/?comp=list

And the result was 200 OK. 结果是200 OK。 What's mean, it's not a problem of any Firewall, Linux environment or connectivity. 意思是,这不是任何防火墙,Linux环境或连接性的问题。

Now, the focus should be on Mono settings since executing the same HTTP request with cURL finished successfully (200). 现在,重点应该放在Mono设置上,因为成功完成了cURL执行相同的HTTP请求(200)。 It's not depends on my specific code, since similar behavior happen also with the sample code mentioned above. 这不取决于我的特定代码,因为上述示例代码也发生了类似的行为。

Thank you. 谢谢。

Azure Storage Client SDK will communicate with the Storage Server with Https and your client side will validate the certificate received from server side. Azure Storage Client SDK将使用Https与Storage Server通信,并且您的客户端将验证从服务器端收到的证书。 After migrate to MONO, please add following code at the top of your code to validate the certificate. 迁移到MONO后,请在代码顶部添加以下代码以验证证书。

ServicePointManager.ServerCertificateValidationCallback = MyRemoteCertificateValidationCallback;

public static bool  MyRemoteCertificateValidationCallback(Object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
    bool isOk = true;
    // If there are errors in the certificate chain,
    // look at each error to determine the cause.
    if (sslPolicyErrors != SslPolicyErrors.None)
    {
        for (int i = 0; i < chain.ChainStatus.Length; i++)
        {
            if (chain.ChainStatus[i].Status == X509ChainStatusFlags.RevocationStatusUnknown)
            {
                continue;
            }
            chain.ChainPolicy.RevocationFlag = X509RevocationFlag.EntireChain;
            chain.ChainPolicy.RevocationMode = X509RevocationMode.Online;
            chain.ChainPolicy.UrlRetrievalTimeout = new TimeSpan(0, 1, 0);
            chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllFlags;
            bool chainIsValid = chain.Build((X509Certificate2)certificate);
            if (!chainIsValid)
            {
                isOk = false;
                break;
            }
        }
    }
    return isOk;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM