大量匯出及匯入 Azure 通知中樞註冊
在某些情況下,您必須在通知中心裡建立或修改大量的註冊。 例如,批次計算之後的標籤更新,或移轉現有推送實作以使用 Azure 通知中樞。
本文說明如何在通知中樞上執行大量作業,或大量匯出所有註冊。
注意: 大量匯入/匯出僅適用于「標準」定價層
高階流程
批次支援的用途,是要支援牽涉到數百萬項註冊的長時間執行工作。 若要達到此規模,批次支援會使用 Azure 儲存體來儲存工作詳細資料與輸出。 進行大量更新作業時,使用者必須在 Blob 容器中建立一個內容為註冊更新作業清單的檔案。 工作開始時,使用者會先提供輸入 Blob 的 URL,以及輸出目錄的 URL (也是在 Blob 容器中)。 在工作開始之後,使用者可查詢在工作開始時提供的 URL 位置,以查看狀態。 特定工作只能執行特定種類的作業 (建立、更新或刪除)。 匯出作業會以類似的方式執行。
匯入
設定
本節假設您已具備下列實體:
- 已佈建的通知中心。
- Azure 儲存體 Blob 容器。
- Azure 儲存體 NuGet套件與通知中樞 NuGet 套件的參考。
建立輸入檔案並將其儲存在 Blob 中
輸入檔案包含以 XML 序列化的註冊清單,每列一個。 下列程式碼範例會使用 Azure SDK,示範如何將註冊序列化並將其上傳至 Blob 容器:
private static async Task SerializeToBlobAsync(BlobContainerClient container, RegistrationDescription[] descriptions)
{
StringBuilder builder = new StringBuilder();
foreach (var registrationDescription in descriptions)
{
builder.AppendLine(registrationDescription.Serialize());
}
var inputBlob = container.GetBlobClient(INPUT_FILE_NAME);
using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(builder.ToString())))
{
await inputBlob.UploadAsync(stream);
}
}
重要
前述程式碼會序列化記憶體中的註冊,並將整個資料流上傳至 Blob 中。 若您所上傳的檔案只有幾 MB 的大小,請參閱如何執行這些步驟的 Azure Blob 指引,例如區塊 Blob。
建立 URL 權杖
上傳輸入檔案之後,您必須產生 URL,以提供給通知中樞的輸入檔案與輸出目錄。 可以針對輸入與輸出使用兩種不同的 Blob 容器。
static Uri GetOutputDirectoryUrl(BlobContainerClient container)
{
Console.WriteLine(container.CanGenerateSasUri);
BlobSasBuilder builder = new BlobSasBuilder(BlobSasPermissions.All, DateTime.UtcNow.AddDays(1));
return container.GenerateSasUri(builder);
}
static Uri GetInputFileUrl(BlobContainerClient container, string filePath)
{
Console.WriteLine(container.CanGenerateSasUri);
BlobSasBuilder builder = new BlobSasBuilder(BlobSasPermissions.Read, DateTime.UtcNow.AddDays(1));
return container.GenerateSasUri(builder);
}
提交工作
有了輸入與輸出 URL 之後,即可開始進行批次工作。
NotificationHubClient client = NotificationHubClient.CreateClientFromConnectionString(CONNECTION_STRING, HUB_NAME);
var job = await client.SubmitNotificationHubJobAsync(
new NotificationHubJob {
JobType = NotificationHubJobType.ImportCreateRegistrations,
OutputContainerUri = outputContainerSasUri,
ImportFileUri = inputFileSasUri
}
);
long i = 10;
while (i > 0 && job.Status != NotificationHubJobStatus.Completed)
{
job = await client.GetNotificationHubJobAsync(job.JobId);
await Task.Delay(1000);
i--;
}
除了輸入與輸出 URL 之外,此範例也會建立包含 JobType
物件的 NotificationHubJob
物件,這可能是下列其中一種類型:
ImportCreateRegistrations
ImportUpdateRegistrations
ImportDeleteRegistrations
呼叫完成之後,通知中樞會繼續執行工作,而您可以呼叫 GetNotificationHubJobAsync 以查看其狀態。
工作完成時,您可以檢視輸出目錄中的下列檔案,以檢查結果:
/<hub>/<jobid>/Failed.txt
/<hub>/<jobid>/Output.txt
這些檔案會列出批次作業中的成功和失敗作業。 檔案格式為 .cvs
;在此格式中,每一個資料列都會有原始輸入檔案的行號,以及作業的輸出 (通常是已建立或已更新的註冊描述)。
完整範例程式碼
下列範例程式碼會將註冊匯入通知中樞。
using Microsoft.Azure.NotificationHubs;
using Azure.Storage.Blobs;
using Azure.Storage.Sas;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
private static string CONNECTION_STRING = "namespace";
private static string HUB_NAME = "demohub";
private static string INPUT_FILE_NAME = "CreateFile.txt";
private static string STORAGE_ACCOUNT_CONNECTIONSTRING = "connectionstring";
private static string CONTAINER_NAME = "containername";
static async Task Main(string[] args)
{
var descriptions = new[]
{
new MpnsRegistrationDescription(@"http://dm2.notify.live.net/throttledthirdparty/01.00/12G9Ed13dLb5RbCii5fWzpFpAgAAAAADAQAAAAQUZm52OkJCMjg1QTg1QkZDMkUxREQFBlVTTkMwMQ"),
new MpnsRegistrationDescription(@"http://dm2.notify.live.net/throttledthirdparty/01.00/12G9Ed13dLb5RbCii5fWzpFpAgAAAAADAQAAAAQUZm52OkJCMjg1QTg1QkZDMjUxREQFBlVTTkMwMQ"),
new MpnsRegistrationDescription(@"http://dm2.notify.live.net/throttledthirdparty/01.00/12G9Ed13dLb5RbCii5fWzpFpAgAAAAADAQAAAAQUZm52OkJCMjg1QTg1QkZDMhUxREQFBlVTTkMwMQ"),
new MpnsRegistrationDescription(@"http://dm2.notify.live.net/throttledthirdparty/01.00/12G9Ed13dLb5RbCii5fWzpFpAgAAAAADAQAAAAQUZm52OkJCMjg1QTg1QkZDMdUxREQFBlVTTkMwMQ"),
};
// Get a reference to a container named "sample-container" and then create it
BlobContainerClient container = new BlobContainerClient(STORAGE_ACCOUNT_CONNECTIONSTRING, CONTAINER_NAME);
await container.CreateIfNotExistsAsync();
await SerializeToBlobAsync(container, descriptions);
// TODO then create Sas
var outputContainerSasUri = GetOutputDirectoryUrl(container);
BlobContainerClient inputcontainer = new BlobContainerClient(STORAGE_ACCOUNT_CONNECTIONSTRING, STORAGE_ACCOUNT_CONNECTIONSTRING + "/" + INPUT_FILE_NAME);
var inputFileSasUri = GetInputFileUrl(inputcontainer, INPUT_FILE_NAME);
// Import this file
NotificationHubClient client = NotificationHubClient.CreateClientFromConnectionString(CONNECTION_STRING, HUB_NAME);
var job = await client.SubmitNotificationHubJobAsync(
new NotificationHubJob {
JobType = NotificationHubJobType.ImportCreateRegistrations,
OutputContainerUri = outputContainerSasUri,
ImportFileUri = inputFileSasUri
}
);
long i = 10;
while (i > 0 && job.Status != NotificationHubJobStatus.Completed)
{
job = await client.GetNotificationHubJobAsync(job.JobId);
await Task.Delay(1000);
i--;
}
}
private static async Task SerializeToBlobAsync(BlobContainerClient container, RegistrationDescription[] descriptions)
{
StringBuilder builder = new StringBuilder();
foreach (var registrationDescription in descriptions)
{
builder.AppendLine(registrationDescription.Serialize());
}
var inputBlob = container.GetBlobClient(INPUT_FILE_NAME);
using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(builder.ToString())))
{
await inputBlob.UploadAsync(stream);
}
}
static Uri GetOutputDirectoryUrl(BlobContainerClient container)
{
Console.WriteLine(container.CanGenerateSasUri);
BlobSasBuilder builder = new BlobSasBuilder(BlobSasPermissions.All, DateTime.UtcNow.AddDays(1));
return container.GenerateSasUri(builder);
}
static Uri GetInputFileUrl(BlobContainerClient container, string filePath)
{
Console.WriteLine(container.CanGenerateSasUri);
BlobSasBuilder builder = new BlobSasBuilder(BlobSasPermissions.Read, DateTime.UtcNow.AddDays(1));
return container.GenerateSasUri(builder);
}
}
}
匯出
註冊的匯出與匯入類似,但有以下差異:
- 您只需要輸出 URL。
- 建立 NotificationHubJob 的 ExportRegistrations 類型。
範例程式碼片段
下列是在 JAVA 中匯出註冊的範例程式碼片段:
// Submit an export job
NotificationHubJob job = new NotificationHubJob();
job.setJobType(NotificationHubJobType.ExportRegistrations);
job.setOutputContainerUri("container uri with SAS signature");
job = hub.submitNotificationHubJob(job);
// Wait until the job is done
while(true){
Thread.sleep(1000);
job = hub.getNotificationHubJob(job.getJobId());
if(job.getJobStatus() == NotificationHubJobStatus.Completed)
break;
}
下一步
若要深入了解註冊,請參閱下列文章: