نماذج التعليمات البرمجية ل Azure Blob Storage باستخدام مكتبات عميل .NET الإصدار 11.x
تعرض هذه المقالة نماذج التعليمات البرمجية التي تستخدم الإصدار 11.x من مكتبة عميل Azure Blob Storage ل .NET.
في 31 مارس 2023، قمنا بإيقاف الدعم لمكتبات Azure SDK التي لا تتوافق مع إرشادات Azure SDK الحالية. يتم تحديث مكتبات Azure SDK الجديدة بانتظام لدفع تجارب متسقة وتعزيز وضع الأمان الخاص بك. يوصى بالانتقال إلى مكتبات Azure SDK الجديدة للاستفادة من الإمكانات الجديدة وتحديثات الأمان الهامة.
على الرغم من أنه لا يزال من الممكن استخدام المكتبات القديمة بعد 31 مارس 2023، إلا أنها لن تتلقى الدعم والتحديثات الرسمية من Microsoft. لمزيد من المعلومات، راجع إعلان إيقاف الدعم.
إنشاء لقطة
لإنشاء لقطة من كائن ثنائي كبير الحجم للكتلة باستخدام الإصدار 11.x من مكتبة عميل تخزين Azure لـ .NET، استخدم إحدى الطرق التالية:
يوضح مثال التعليمات البرمجية التالي كيفية إنشاء لقطة باستخدام الإصدار 11.x. يحدد هذا المثال بيانات تعريف إضافية لللقطة عند إنشائها.
private static async Task CreateBlockBlobSnapshot(CloudBlobContainer container)
{
// Create a new block blob in the container.
CloudBlockBlob baseBlob = container.GetBlockBlobReference("sample-base-blob.txt");
// Add blob metadata.
baseBlob.Metadata.Add("ApproxBlobCreatedDate", DateTime.UtcNow.ToString());
try
{
// Upload the blob to create it, with its metadata.
await baseBlob.UploadTextAsync(string.Format("Base blob: {0}", baseBlob.Uri.ToString()));
// Sleep 5 seconds.
System.Threading.Thread.Sleep(5000);
// Create a snapshot of the base blob.
// You can specify metadata at the time that the snapshot is created.
// If no metadata is specified, then the blob's metadata is copied to the snapshot.
Dictionary<string, string> metadata = new Dictionary<string, string>();
metadata.Add("ApproxSnapshotCreatedDate", DateTime.UtcNow.ToString());
await baseBlob.CreateSnapshotAsync(metadata, null, null, null);
Console.WriteLine(snapshot.SnapshotQualifiedStorageUri.PrimaryUri);
}
catch (StorageException e)
{
Console.WriteLine(e.Message);
Console.ReadLine();
throw;
}
}
حذف اللقطات
لحذف كائن ثنائي كبير الحجم ولقطاته باستخدام الإصدار 11.x من مكتبة عميل تخزين Azure ل .NET، استخدم إحدى طرق حذف الكائن الثنائي كبير الحجم التالي، وقم بتضمين التعداد DeleteSnapshotsOption :
يوضح مثال التعليمات البرمجية التالي كيفية حذف كائن ثنائي كبير الحجم ولقطاته في .NET، حيث blockBlob
يوجد عنصر من النوع [CloudBlockBlob][dotnet_CloudBlockBlob]:
await blockBlob.DeleteIfExistsAsync(DeleteSnapshotsOption.IncludeSnapshots, null, null, null);
إنشاء نهج وصول مشترك
لإنشاء نهج وصول مخزن على حاوية مع الإصدار 11.x من مكتبة عميل .NET لتخزين Azure، اتصل بإحدى الطرق التالية:
ينشئ المثال التالي نهج وصول مخزَّنًا ساري المفعول لمدة يوم واحد، ويمنح أذونات قراءة وكتابة وإدراج:
private static async Task CreateStoredAccessPolicyAsync(CloudBlobContainer container, string policyName)
{
// Create a new stored access policy and define its constraints.
// The access policy provides create, write, read, list, and delete permissions.
SharedAccessBlobPolicy sharedPolicy = new SharedAccessBlobPolicy()
{
// When the start time for the SAS is omitted, the start time is assumed to be the time when Azure Storage receives the request.
SharedAccessExpiryTime = DateTime.UtcNow.AddHours(24),
Permissions = SharedAccessBlobPermissions.Read | SharedAccessBlobPermissions.List |
SharedAccessBlobPermissions.Write
};
// Get the container's existing permissions.
BlobContainerPermissions permissions = await container.GetPermissionsAsync();
// Add the new policy to the container's permissions, and set the container's permissions.
permissions.SharedAccessPolicies.Add(policyName, sharedPolicy);
await container.SetPermissionsAsync(permissions);
}
إنشاء SAS لخدمة لحاوية كائنات ثنائية كبيرة الحجم
لإنشاء SAS لخدمة لحاوية، قم باستدعاء الأسلوب CloudBlobContainer.GetSharedAccessSignature.
private static string GetContainerSasUri(CloudBlobContainer container,
string storedPolicyName = null)
{
string sasContainerToken;
// If no stored policy is specified, create a new access policy and define its constraints.
if (storedPolicyName == null)
{
// Note that the SharedAccessBlobPolicy class is used both to define
// the parameters of an ad hoc SAS, and to construct a shared access policy
// that is saved to the container's shared access policies.
SharedAccessBlobPolicy adHocPolicy = new SharedAccessBlobPolicy()
{
// When the start time for the SAS is omitted, the start time is assumed
// to be the time when the storage service receives the request. Omitting
// the start time for a SAS that is effective immediately helps to avoid clock skew.
SharedAccessExpiryTime = DateTime.UtcNow.AddHours(24),
Permissions = SharedAccessBlobPermissions.Write | SharedAccessBlobPermissions.List
};
// Generate the shared access signature on the container,
// setting the constraints directly on the signature.
sasContainerToken = container.GetSharedAccessSignature(adHocPolicy, null);
Console.WriteLine("SAS for blob container (ad hoc): {0}", sasContainerToken);
Console.WriteLine();
}
else
{
// Generate the shared access signature on the container. In this case,
// all of the constraints for the shared access signature are specified
// on the stored access policy, which is provided by name. It is also possible
// to specify some constraints on an ad hoc SAS and others on the stored access policy.
sasContainerToken = container.GetSharedAccessSignature(null, storedPolicyName);
Console.WriteLine("SAS for container (stored access policy): {0}", sasContainerToken);
Console.WriteLine();
}
// Return the URI string for the container, including the SAS token.
return container.Uri + sasContainerToken;
}
إنشاء SAS لخدمة لكائن ثنائي كبير الحجم
لإنشاء SAS لخدمة لكائن ثنائي كبير الحجم، قم باستدعاء الأسلوب CloudBlob.GetSharedAccessSignature.
private static string GetBlobSasUri(CloudBlobContainer container,
string blobName,
string policyName = null)
{
string sasBlobToken;
// Get a reference to a blob within the container.
// Note that the blob may not exist yet, but a SAS can still be created for it.
CloudBlockBlob blob = container.GetBlockBlobReference(blobName);
if (policyName == null)
{
// Create a new access policy and define its constraints.
// Note that the SharedAccessBlobPolicy class is used both to define the parameters
// of an ad hoc SAS, and to construct a shared access policy that is saved to
// the container's shared access policies.
SharedAccessBlobPolicy adHocSAS = new SharedAccessBlobPolicy()
{
// When the start time for the SAS is omitted, the start time is assumed to be
// the time when the storage service receives the request. Omitting the start time
// for a SAS that is effective immediately helps to avoid clock skew.
SharedAccessExpiryTime = DateTime.UtcNow.AddHours(24),
Permissions = SharedAccessBlobPermissions.Read |
SharedAccessBlobPermissions.Write |
SharedAccessBlobPermissions.Create
};
// Generate the shared access signature on the blob,
// setting the constraints directly on the signature.
sasBlobToken = blob.GetSharedAccessSignature(adHocSAS);
Console.WriteLine("SAS for blob (ad hoc): {0}", sasBlobToken);
Console.WriteLine();
}
else
{
// Generate the shared access signature on the blob. In this case, all of the constraints
// for the SAS are specified on the container's stored access policy.
sasBlobToken = blob.GetSharedAccessSignature(null, policyName);
Console.WriteLine("SAS for blob (stored access policy): {0}", sasBlobToken);
Console.WriteLine();
}
// Return the URI string for the container, including the SAS token.
return blob.Uri + sasBlobToken;
}
إنشاء حساب SAS
لإنشاء حساب SAS للحاوية، اتصل بطريقة CloudStorageAccount.GetSharedAccessSignature .
ينشئ مثال التعليمة البرمجية التالي حساب SAS صالح لخدمات كائن ثنائي كبير الحجم وملف، ويعطي العميل أذونات للقراءة والكتابة والقائمة للوصول إلى واجهات برمجة التطبيقات على مستوى الخدمة. يقصر الحساب SAS البروتوكول على HTTPS، لذلك يجب إنشاء الطلب باستخدام HTTPS. تذكر استبدال قيم العناصر النائبة بين أقواس الزاوية بالقيم الخاصة بك:
static string GetAccountSASToken()
{
// To create the account SAS, you need to use Shared Key credentials. Modify for your account.
const string ConnectionString = "DefaultEndpointsProtocol=https;AccountName=<storage-account>;AccountKey=<account-key>";
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(ConnectionString);
// Create a new access policy for the account.
SharedAccessAccountPolicy policy = new SharedAccessAccountPolicy()
{
Permissions = SharedAccessAccountPermissions.Read |
SharedAccessAccountPermissions.Write |
SharedAccessAccountPermissions.List,
Services = SharedAccessAccountServices.Blob | SharedAccessAccountServices.File,
ResourceTypes = SharedAccessAccountResourceTypes.Service,
SharedAccessExpiryTime = DateTime.UtcNow.AddHours(24),
Protocols = SharedAccessProtocol.HttpsOnly
};
// Return the SAS token.
return storageAccount.GetSharedAccessSignature(policy);
}
استخدام حساب SAS من عميل
في هذا القصاصة البرمجية، استبدل العنصر النائب <storage-account>
باسم حساب التخزين خاصتك.
static void UseAccountSAS(string sasToken)
{
// Create new storage credentials using the SAS token.
StorageCredentials accountSAS = new StorageCredentials(sasToken);
// Use these credentials and the account name to create a Blob service client.
CloudStorageAccount accountWithSAS = new CloudStorageAccount(accountSAS, "<storage-account>", endpointSuffix: null, useHttps: true);
CloudBlobClient blobClientWithSAS = accountWithSAS.CreateCloudBlobClient();
// Now set the service properties for the Blob client created with the SAS.
blobClientWithSAS.SetServiceProperties(new ServiceProperties()
{
HourMetrics = new MetricsProperties()
{
MetricsLevel = MetricsLevel.ServiceAndApi,
RetentionDays = 7,
Version = "1.0"
},
MinuteMetrics = new MetricsProperties()
{
MetricsLevel = MetricsLevel.ServiceAndApi,
RetentionDays = 7,
Version = "1.0"
},
Logging = new LoggingProperties()
{
LoggingOperations = LoggingOperations.All,
RetentionDays = 14,
Version = "1.0"
}
});
// The permissions granted by the account SAS also permit you to retrieve service properties.
ServiceProperties serviceProperties = blobClientWithSAS.GetServiceProperties();
Console.WriteLine(serviceProperties.HourMetrics.MetricsLevel);
Console.WriteLine(serviceProperties.HourMetrics.RetentionDays);
Console.WriteLine(serviceProperties.HourMetrics.Version);
}
التزامن المتفائل للكائنات الثنائية كبيرة الحجم
مثال على التعليمات البرمجية:
public void DemonstrateOptimisticConcurrencyBlob(string containerName, string blobName)
{
Console.WriteLine("Demonstrate optimistic concurrency");
// Parse connection string and create container.
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(ConnectionString);
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer container = blobClient.GetContainerReference(containerName);
container.CreateIfNotExists();
// Create test blob. The default strategy is last writer wins, so
// write operation will overwrite existing blob if present.
CloudBlockBlob blockBlob = container.GetBlockBlobReference(blobName);
blockBlob.UploadText("Hello World!");
// Retrieve the ETag from the newly created blob.
string originalETag = blockBlob.Properties.ETag;
Console.WriteLine("Blob added. Original ETag = {0}", originalETag);
/// This code simulates an update by another client.
string helloText = "Blob updated by another client.";
// No ETag was provided, so original blob is overwritten and ETag updated.
blockBlob.UploadText(helloText);
Console.WriteLine("Blob updated. Updated ETag = {0}", blockBlob.Properties.ETag);
// Now try to update the blob using the original ETag value.
try
{
Console.WriteLine(@"Attempt to update blob using original ETag
to generate if-match access condition");
blockBlob.UploadText(helloText, accessCondition: AccessCondition.GenerateIfMatchCondition(originalETag));
}
catch (StorageException ex)
{
if (ex.RequestInformation.HttpStatusCode == (int)HttpStatusCode.PreconditionFailed)
{
Console.WriteLine(@"Precondition failure as expected.
Blob's ETag does not match.");
}
else
{
throw;
}
}
Console.WriteLine();
}
تزامن متشائم للكائنات الثنائية كبيرة الحجم
مثال على التعليمات البرمجية:
public void DemonstratePessimisticConcurrencyBlob(string containerName, string blobName)
{
Console.WriteLine("Demonstrate pessimistic concurrency");
// Parse connection string and create container.
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(ConnectionString);
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer container = blobClient.GetContainerReference(containerName);
container.CreateIfNotExists();
CloudBlockBlob blockBlob = container.GetBlockBlobReference(blobName);
blockBlob.UploadText("Hello World!");
Console.WriteLine("Blob added.");
// Acquire lease for 15 seconds.
string lease = blockBlob.AcquireLease(TimeSpan.FromSeconds(15), null);
Console.WriteLine("Blob lease acquired. Lease = {0}", lease);
// Update blob using lease. This operation should succeed.
const string helloText = "Blob updated";
var accessCondition = AccessCondition.GenerateLeaseCondition(lease);
blockBlob.UploadText(helloText, accessCondition: accessCondition);
Console.WriteLine("Blob updated using an exclusive lease");
// Simulate another client attempting to update to blob without providing lease.
try
{
// Operation will fail as no valid lease was provided.
Console.WriteLine("Now try to update blob without valid lease.");
blockBlob.UploadText("Update operation will fail without lease.");
}
catch (StorageException ex)
{
if (ex.RequestInformation.HttpStatusCode == (int)HttpStatusCode.PreconditionFailed)
{
Console.WriteLine(@"Precondition failure error as expected.
Blob lease not provided.");
}
else
{
throw;
}
}
// Release lease proactively.
blockBlob.ReleaseLease(accessCondition);
Console.WriteLine();
}
إنشاء تطبيق عالي التوفر باستخدام Blob Storage
قم بتنزيل نموذج المشروع، واستخرج (فك ضغط) ملف storage-dotnet-circuit-breaker-pattern-ha-apps-using-ra-grs.zip، ثم انتقل إلى مجلد v11 للعثور على ملفات المشروع.
يمكنك أيضاً استخدام git لتنزيل نسخة من التطبيق إلى بيئة التطوير خاصتك. يحتوي نموذج المشروع في مجلد v11 على تطبيق وحدة تحكم.
git clone https://github.com/Azure-Samples/storage-dotnet-circuit-breaker-pattern-ha-apps-using-ra-grs.git
تهيئة العينة
في التطبيق، يجب توفير سلسلة الاتصال لحساب التخزين الخاص بك. يمكنك تخزين سلسلة الاتصال هذه ضمن متغير بيئة على الجهاز المحلي الذي يقوم بتشغيل التطبيق. اتبع أحد الأمثلة أدناه اعتمادًا على نظام التشغيل لإنشاء متغير البيئة.
انتقل إلى تطبيق التخزين الجديد في مدخل Azure. حدد مفاتيح الوصول الموجودة ضمن الإعدادات في حساب التخزين. انسخ سلسلة الاتصال من المفتاح الأساسي أو الثانوي. شغِّل أحد الأوامر التالية بناءً على نظام التشغيل الخاص بك، مع استبدال <سلسلة الاتصال الخاصة بك> بسلسلة الاتصال الفعلية. يحفظ هذا الأمر متغير البيئة إلى الجهاز المحلي. لا يُتاح متغير البيئة في Windows إلى أن تُعيد تحميل موجه الأمر أو تطبيق shell الذي تستخدمه.
تشغيل تطبيق وحدة التحكم
في Visual Studio، اضغط F5 أو حدد بدء لبدء تصحيح أخطاء التطبيق. يقوم Visual Studio تلقائيًا باستعادة حزم NuGet المفقودة إذا تم تكوين استعادة الحزمة، قم بزيارة تثبيت وإعادة تثبيت الحزم مع استعادة الحزمة لمعرفة المزيد.
يتم تشغيل نافذة وحدة التحكم ويبدأ تشغيل التطبيق. يُحمل التطبيق صورة HelloWorld.png من الحل إلى حساب التخزين. يتحقق التطبيق للتأكد من النسخ المتماثل للصورة إلى نقطة نهاية RA-GZRS الثانوية. ثم يبدأ تحميل الصورة بما يصل إلى 999 مرة. يجرى تمثيل كل قراءة برمز P أو S. حيث يمثل P نقطة النهاية الأساسية ويمثل Sنقطة النهاية الثانوية.
في نموذج التعليمات البرمجية، RunCircuitBreakerAsync
تُستخدم مهمة في الملف لتحميل صورة من حساب التخزين باستخدام أسلوبProgram.cs
DownloadToFileAsync. قبل التنزيل، يُحدد OperationContext. يُحدد سياق العملية معالجات الأحداث، التي تظهر عند اكتمال التنزيل بنجاح أو إذا فشل التنزيل ثم أعد المحاولة.
يجب فهم نموذج التعليمات البرمجية
إعادة محاولة معالج الأحداث
يُطلب معالج الأحداث OperationContextRetrying
عند فشل تحميل الصورة وتعيينه لإعادة المحاولة. في حالة الوصول إلى الحد الأقصى لعدد مرات إعادة المحاولة المعرفة في التطبيق، يتم تغيير LocationMode الخاص بالطلب إلى SecondaryOnly
. يفرض هذا الإعداد على التطبيق محاولة تحميل الصورة من نقطة النهاية الثانوية. تُقلل هذه التهيئة الوقت المستغرق لطلب الصورة حيث لا تتم إعادة محاولة نقطة النهاية الأساسية إلى أجل غير مسمى.
private static void OperationContextRetrying(object sender, RequestEventArgs e)
{
retryCount++;
Console.WriteLine("Retrying event because of failure reading the primary. RetryCount = " + retryCount);
// Check if we have had more than n retries in which case switch to secondary.
if (retryCount >= retryThreshold)
{
// Check to see if we can fail over to secondary.
if (blobClient.DefaultRequestOptions.LocationMode != LocationMode.SecondaryOnly)
{
blobClient.DefaultRequestOptions.LocationMode = LocationMode.SecondaryOnly;
retryCount = 0;
}
else
{
throw new ApplicationException("Both primary and secondary are unreachable. Check your application's network connection. ");
}
}
}
طلب معالج الأحداث المكتملة
يُطلب معالج الأحداث OperationContextRequestCompleted
عند نجاح تحميل الصورة. إذا كان التطبيق يستخدم نقطة النهاية الثانوية، فإن التطبيق يستمر في استخدام نقطة النهاية هذه حتى 20 مرة. بعد 20 مرة، يُحدد التطبيقLocationMode مع العودة إلى PrimaryThenSecondary
ثم إعادة محاولة نقطة النهاية الأساسية. في حالة نجاح الطلب، يستمر التطبيق في القراءة من نقطة النهاية الأساسية.
private static void OperationContextRequestCompleted(object sender, RequestEventArgs e)
{
if (blobClient.DefaultRequestOptions.LocationMode == LocationMode.SecondaryOnly)
{
// You're reading the secondary. Let it read the secondary [secondaryThreshold] times,
// then switch back to the primary and see if it's available now.
secondaryReadCount++;
if (secondaryReadCount >= secondaryThreshold)
{
blobClient.DefaultRequestOptions.LocationMode = LocationMode.PrimaryThenSecondary;
secondaryReadCount = 0;
}
}
}
تحميل كميات كبيرة من البيانات العشوائية إلى تخزين Azure
يُعين الحد الأدنى والحد الأقصى لمؤشرات الترابط ليكون 100 للتأكد من السماح بعدد كبير من الاتصالات المتزامنة.
private static async Task UploadFilesAsync()
{
// Create five randomly named containers to store the uploaded files.
CloudBlobContainer[] containers = await GetRandomContainersAsync();
var currentdir = System.IO.Directory.GetCurrentDirectory();
// Path to the directory to upload
string uploadPath = currentdir + "\\upload";
// Start a timer to measure how long it takes to upload all the files.
Stopwatch time = Stopwatch.StartNew();
try
{
Console.WriteLine("Iterating in directory: {0}", uploadPath);
int count = 0;
int max_outstanding = 100;
int completed_count = 0;
// Define the BlobRequestOptions on the upload.
// This includes defining an exponential retry policy to ensure that failed connections
// are retried with a back off policy. As multiple large files are being uploaded using
// large block sizes, this can cause an issue if an exponential retry policy is not defined.
// Additionally, parallel operations are enabled with a thread count of 8.
// This should be a multiple of the number of processor cores in the machine.
// Lastly, MD5 hash validation is disabled for this example, improving the upload speed.
BlobRequestOptions options = new BlobRequestOptions
{
ParallelOperationThreadCount = 8,
DisableContentMD5Validation = true,
StoreBlobContentMD5 = false
};
// Create a new instance of the SemaphoreSlim class to
// define the number of threads to use in the application.
SemaphoreSlim sem = new SemaphoreSlim(max_outstanding, max_outstanding);
List<Task> tasks = new List<Task>();
Console.WriteLine("Found {0} file(s)", Directory.GetFiles(uploadPath).Count());
// Iterate through the files
foreach (string path in Directory.GetFiles(uploadPath))
{
var container = containers[count % 5];
string fileName = Path.GetFileName(path);
Console.WriteLine("Uploading {0} to container {1}", path, container.Name);
CloudBlockBlob blockBlob = container.GetBlockBlobReference(fileName);
// Set the block size to 100MB.
blockBlob.StreamWriteSizeInBytes = 100 * 1024 * 1024;
await sem.WaitAsync();
// Create a task for each file to upload. The tasks are
// added to a collection and all run asynchronously.
tasks.Add(blockBlob.UploadFromFileAsync(path, null, options, null).ContinueWith((t) =>
{
sem.Release();
Interlocked.Increment(ref completed_count);
}));
count++;
}
// Run all the tasks asynchronously.
await Task.WhenAll(tasks);
time.Stop();
Console.WriteLine("Upload has been completed in {0} seconds. Press any key to continue", time.Elapsed.TotalSeconds.ToString());
Console.ReadLine();
}
catch (DirectoryNotFoundException ex)
{
Console.WriteLine("Error parsing files in the directory: {0}", ex.Message);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
بالإضافة إلى إعداد إعدادات حد الترابط والاتصال، تُكون BlobRequestOptions لأسلوب UploadFromStreamAsync بغية استخدام التوازي وتعطيل التحقق من صحة تجزئة MD5. تُحمل الملفات في كتل يبلغ حجمها 100 ميغابايت، ويوفر هذا التكوين أداء أفضل ولكن يمكن أن يكون مكلفاً في حال استخدام شبكة ضعيفة الأداء كما لو كان هنالك فشل تعيد الكتلة البالغة 100 ميغابايت بأكملها هو إعادة محاولة.
الخاصية | القيمة | الوصف |
---|---|---|
ParallelOperationThreadCount | 8 | يكسر الإعداد بتقسيم الكائن الثنائي كبير الحجم إلى كتل عند تحميله. للحصول على أداء أفضل، ينبغي أن تبلغ هذه القيمة ثمانية أضعاف عدد مراكز المعالجة. |
DisableContentMD5Validation | صواب | تعطل هذه الخاصية التحقق من تجزئة MD5 من المحتوى الذي حُمل. يسفر تعطيل التحقق من صحة MD5 عن نقل أسرع. ولكنه لا يؤكد صحة الملفات المنقولة أو سلامتها. |
StoreBlobContentMD5 | false | تحدد هذه الخاصية إذا تم حساب تجزئة MD5 وتخزينها مع الملف. |
RetryPolicy | ثانيتين من التراجع، و10 بحد أقصى لإعادة المحاولة | تحديد نهج إعادة المحاولة للطلبات. تُعاد محاولة فشل الاتصال، وفي هذا المثال كُون نهج ExponentialRetry مع ثانيتين من التراجع، و10 بحد أقصى لإعادة المحاولة. ويعد هذا الإعداد مهم عندما اقتراب التطبيق من الوصول إلى أهداف قابلية التوسع لتخزين الكائن الثنائي كبير الحجم. لمزيد من المعلومات، راجع أهداف قابلية التوسع والأداء لذاكرة تخزين الكائن الثنائي كبير الحجم. |
تحميل كميات كبيرة من البيانات العشوائية من Azure Storage
يقرأ التطبيق الحاويات الموجودة في حساب التخزين المحدد في سلسلة التخزين. يتكرر عبر blobs 10 في كل مرة باستخدام طريقة ListBlobsSegmentedAsync في الحاويات ويقوم بتنزيلها على الجهاز المحلي باستخدام طريقة DownloadToFileAsync.
يعرض الجدول التالي BlobRequestOptions المحددة لكل blob في أثناء تنزيله.
الخاصية | القيمة | الوصف |
---|---|---|
DisableContentMD5Validation | صواب | تعطل هذه الخاصية التحقق من تجزئة MD5 من المحتوى الذي حُمل. يسفر تعطيل التحقق من صحة MD5 عن نقل أسرع. ولكنه لا يؤكد صحة الملفات المنقولة أو سلامتها. |
StoreBlobContentMD5 | false | تحدد هذه الخاصية ما إذا تم احتساب تجزئة MD5 وتخزينها. |
private static async Task DownloadFilesAsync()
{
CloudBlobClient blobClient = GetCloudBlobClient();
// Define the BlobRequestOptions on the download, including disabling MD5
// hash validation for this example, this improves the download speed.
BlobRequestOptions options = new BlobRequestOptions
{
DisableContentMD5Validation = true,
StoreBlobContentMD5 = false
};
// Retrieve the list of containers in the storage account.
// Create a directory and configure variables for use later.
BlobContinuationToken continuationToken = null;
List<CloudBlobContainer> containers = new List<CloudBlobContainer>();
do
{
var listingResult = await blobClient.ListContainersSegmentedAsync(continuationToken);
continuationToken = listingResult.ContinuationToken;
containers.AddRange(listingResult.Results);
}
while (continuationToken != null);
var directory = Directory.CreateDirectory("download");
BlobResultSegment resultSegment = null;
Stopwatch time = Stopwatch.StartNew();
// Download the blobs
try
{
List<Task> tasks = new List<Task>();
int max_outstanding = 100;
int completed_count = 0;
// Create a new instance of the SemaphoreSlim class to
// define the number of threads to use in the application.
SemaphoreSlim sem = new SemaphoreSlim(max_outstanding, max_outstanding);
// Iterate through the containers
foreach (CloudBlobContainer container in containers)
{
do
{
// Return the blobs from the container, 10 at a time.
resultSegment = await container.ListBlobsSegmentedAsync(null, true, BlobListingDetails.All, 10, continuationToken, null, null);
continuationToken = resultSegment.ContinuationToken;
{
foreach (var blobItem in resultSegment.Results)
{
if (((CloudBlob)blobItem).Properties.BlobType == BlobType.BlockBlob)
{
// Get the blob and add a task to download the blob asynchronously from the storage account.
CloudBlockBlob blockBlob = container.GetBlockBlobReference(((CloudBlockBlob)blobItem).Name);
Console.WriteLine("Downloading {0} from container {1}", blockBlob.Name, container.Name);
await sem.WaitAsync();
tasks.Add(blockBlob.DownloadToFileAsync(directory.FullName + "\\" + blockBlob.Name, FileMode.Create, null, options, null).ContinueWith((t) =>
{
sem.Release();
Interlocked.Increment(ref completed_count);
}));
}
}
}
}
while (continuationToken != null);
}
// Creates an asynchronous task that completes when all the downloads complete.
await Task.WhenAll(tasks);
}
catch (Exception e)
{
Console.WriteLine("\nError encountered during transfer: {0}", e.Message);
}
time.Stop();
Console.WriteLine("Download has been completed in {0} seconds. Press any key to continue", time.Elapsed.TotalSeconds.ToString());
Console.ReadLine();
}
تمكين سجلات Azure Storage Analytics (كلاسيكي)
مثال على التعليمات البرمجية:
var storageAccount = CloudStorageAccount.Parse(connStr);
var queueClient = storageAccount.CreateCloudQueueClient();
var serviceProperties = queueClient.GetServiceProperties();
serviceProperties.Logging.LoggingOperations = LoggingOperations.All;
serviceProperties.Logging.RetentionDays = 2;
queueClient.SetServiceProperties(serviceProperties);
تعديل فترة استبقاء بيانات السجل
يطبع المثال التالي إلى وحدة التحكم فترة الاستبقاء لخدمات تخزين للكائنات ثنائية كبيرة الحجم وقائمة الانتظار.
var storageAccount = CloudStorageAccount.Parse(connectionString);
var blobClient = storageAccount.CreateCloudBlobClient();
var queueClient = storageAccount.CreateCloudQueueClient();
var blobserviceProperties = blobClient.GetServiceProperties();
var queueserviceProperties = queueClient.GetServiceProperties();
Console.WriteLine("Retention period for logs from the blob service is: " +
blobserviceProperties.Logging.RetentionDays.ToString());
Console.WriteLine("Retention period for logs from the queue service is: " +
queueserviceProperties.Logging.RetentionDays.ToString());
يغير المثال التالي إلى وحدة التحكم فترة الاستبقاء لخدمات تخزين للكائنات ثنائية كبيرة الحجم وقائمة الانتظار.
blobserviceProperties.Logging.RetentionDays = 4;
queueserviceProperties.Logging.RetentionDays = 4;
blobClient.SetServiceProperties(blobserviceProperties);
queueClient.SetServiceProperties(queueserviceProperties);
تمكين مقاييس Azure Storage Analytics (كلاسيكي)
مثال على التعليمات البرمجية:
var storageAccount = CloudStorageAccount.Parse(connStr);
var queueClient = storageAccount.CreateCloudQueueClient();
var serviceProperties = queueClient.GetServiceProperties();
serviceProperties.HourMetrics.MetricsLevel = MetricsLevel.Service;
serviceProperties.HourMetrics.RetentionDays = 10;
queueClient.SetServiceProperties(serviceProperties);
تكوين بروتوكول أمان طبقة النقل (TLS) لتطبيق العميل
يوضح النموذج التالي كيفية تمكين TLS 1.2 في عميل .NET باستخدام الإصدار 11.x من مكتبة عميل Azure Storage:
static void EnableTls12()
{
// Enable TLS 1.2 before connecting to Azure Storage
System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12;
// Add your connection string here.
string connectionString = "";
// Connect to Azure Storage and create a new container.
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(connectionString);
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer container = blobClient.GetContainerReference("sample-container");
container.CreateIfNotExists();
}
مراقبة تخزين Microsoft Azure وتشخيصها واستكشاف مشكلاتها وإصلاحها (كلاسيكي)
إذا طرحت مكتبة عميل التخزين StorageException الخاصة بكمبيوتر العميل، تحتوي الخاصية RequestInformation على عنصر RequestResult يتضمن خاصية ServiceRequestID. يمكنك أيضا الوصول إلى العنصرRequestResult من مثيل OperationContext .
يوضح نموذج التعليمات البرمجية أدناه كيفية تعيين قيمة ClientRequestId مخصصة عن طريق إرفاق الطلب بعنصر OperationContext المتعلق بخدمة التخزين. كما يوضح كيفية استرداد قيمة ServerRequestId عن طريق رسالة الاستجابة.
//Parse the connection string for the storage account.
const string ConnectionString = "DefaultEndpointsProtocol=https;AccountName=account-name;AccountKey=account-key";
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(ConnectionString);
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
// Create an Operation Context that includes custom ClientRequestId string based on constants defined within the application along with a Guid.
OperationContext oc = new OperationContext();
oc.ClientRequestID = String.Format("{0} {1} {2} {3}", HOSTNAME, APPNAME, USERID, Guid.NewGuid().ToString());
try
{
CloudBlobContainer container = blobClient.GetContainerReference("democontainer");
ICloudBlob blob = container.GetBlobReferenceFromServer("testImage.jpg", null, null, oc);
var downloadToPath = string.Format("./{0}", blob.Name);
using (var fs = File.OpenWrite(downloadToPath))
{
blob.DownloadToStream(fs, null, null, oc);
Console.WriteLine("\t Blob downloaded to file: {0}", downloadToPath);
}
}
catch (StorageException storageException)
{
Console.WriteLine("Storage exception {0} occurred", storageException.Message);
// Multiple results may exist due to client side retry logic - each retried operation will have a unique ServiceRequestId
foreach (var result in oc.RequestResults)
{
Console.WriteLine("HttpStatus: {0}, ServiceRequestId {1}", result.HttpStatusCode, result.ServiceRequestID);
}
}
التحقيق في مشكلات أداء العميل - تعطيل خوارزمية Nagle
مثال على التعليمات البرمجية:
var storageAccount = CloudStorageAccount.Parse(connStr);
ServicePoint queueServicePoint = ServicePointManager.FindServicePoint(storageAccount.QueueEndpoint);
queueServicePoint.UseNagleAlgorithm = false;
التحقيق في مشكلات زمن انتقال الشبكة - تكوين مشاركة الموارد عبر المنشأ (CORS)
مثال على التعليمات البرمجية:
CloudBlobClient client = new CloudBlobClient(blobEndpoint, new StorageCredentials(accountName, accountKey));
// Set the service properties.
ServiceProperties sp = client.GetServiceProperties();
sp.DefaultServiceVersion = "2013-08-15";
CorsRule cr = new CorsRule();
cr.AllowedHeaders.Add("*");
cr.AllowedMethods = CorsHttpMethods.Get | CorsHttpMethods.Put;
cr.AllowedOrigins.Add("http://www.contoso.com");
cr.ExposedHeaders.Add("x-ms-*");
cr.MaxAgeInSeconds = 5;
sp.Cors.CorsRules.Clear();
sp.Cors.CorsRules.Add(cr);
client.SetServiceProperties(sp);
إنشاء page blob فارغة بحجم محدد
لإنشاء page blob، نقوم أولاً بإنشاء عنصر CloudBlobClient، باستخدام URI الأساسي للوصول إلى تخزين blob لحساب التخزين الخاص بك (pbaccount في الشكل 1) جنبًا إلى جنب مع عنصر StorageCredentialsAccountAndKey، كما هو موضح في المثال التالي. يوضح المثال بعد ذلك إنشاء مرجع إلى عنصر CloudBlobContainer، ثم إنشاء الحاوية (testvhds) إذا لم تكن موجودة بالفعل. ثم باستخدام عنصر CloudBlobContainer، قم بإنشاء مرجع إلى عنصر CloudPageBlob عن طريق تحديد اسم page blob (os4.vhd) للوصول إليه. لإنشاء page blob، قم باستدعاء CloudPageBlob.Create، وتمرير الحد الأقصى لحجم blob المراد إنشاؤها. يجب أن يكون blobSize أحد مضاعفات 512 بايت.
using Microsoft.Azure;
using Microsoft.Azure.Storage;
using Microsoft.Azure.Storage.Blob;
long OneGigabyteAsBytes = 1024 * 1024 * 1024;
// Retrieve storage account from connection string.
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(
CloudConfigurationManager.GetSetting("StorageConnectionString"));
// Create the blob client.
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
// Retrieve a reference to a container.
CloudBlobContainer container = blobClient.GetContainerReference("testvhds");
// Create the container if it doesn't already exist.
container.CreateIfNotExists();
CloudPageBlob pageBlob = container.GetPageBlobReference("os4.vhd");
pageBlob.Create(16 * OneGigabyteAsBytes);
تغيير حجم page blob
لتغيير حجم page blob بعد الإنشاء، استخدم أسلوب تغيير الحجم. يجب أن يكون الحجم المطلوب أحد مضاعفات 512 بايت.
pageBlob.Resize(32 * OneGigabyteAsBytes);
كتابة الصفحات إلى page blob
لكتابة الصفحات، استخدم الأسلوب CloudPageBlob.WritePages.
pageBlob.WritePages(dataStream, startingOffset);
قراءة الصفحات من page blob
لقراءة الصفحات، استخدم الأسلوب CloudPageBlob.DownloadRangeToByteArray لقراءة نطاق من وحدات البايت من page blob.
byte[] buffer = new byte[rangeSize];
pageBlob.DownloadRangeToByteArray(buffer, bufferOffset, pageBlobOffset, rangeSize);
لتحديد الصفحات المدعومة بالبيانات، استخدم CloudPageBlob.GetPageRanges. يمكنك بعد ذلك تعداد النطاقات التي تم إرجاعها وتنزيل البيانات في كل نطاق.
IEnumerable<PageRange> pageRanges = pageBlob.GetPageRanges();
foreach (PageRange range in pageRanges)
{
// Calculate the range size
int rangeSize = (int)(range.EndOffset + 1 - range.StartOffset);
byte[] buffer = new byte[rangeSize];
// Read from the correct starting offset in the page blob and
// place the data in the bufferOffset of the buffer byte array
pageBlob.DownloadRangeToByteArray(buffer, bufferOffset, range.StartOffset, rangeSize);
// Then use the buffer for the page range just read
}