Share via


Azure Notification Hubs-regisztrációk tömeges exportálása és importálása

Vannak olyan helyzetek, amikor nagy számú regisztrációt kell létrehoznia vagy módosítania egy értesítési központban. Ezek közé a forgatókönyvek közé tartoznak a kötegelt számításokat követő címkefrissítések, vagy egy meglévő leküldéses implementáció migrálása az Azure Notification Hubs használatára.

Ez a cikk bemutatja, hogyan hajthat végre nagy számú műveletet egy értesítési központban, vagy hogyan exportálhatja az összes regisztrációt tömegesen.

MEGJEGYZÉS: A tömeges importálás/exportálás csak a "standard" tarifacsomaghoz érhető el

Magas szintű folyamat

A Batch-támogatás célja, hogy támogassa a több millió regisztrációt tartalmazó, hosszan futó feladatokat. A skálázás eléréséhez a kötegelt támogatás az Azure Storage használatával tárolja a feladatok részleteit és kimenetét. Tömeges frissítési műveletek esetén a felhasználónak létre kell hoznia egy fájlt egy blobtárolóban, amelynek tartalma a regisztrációs frissítési műveletek listája. A feladat indításakor a felhasználó megad egy URL-címet a bemeneti blobnak, valamint egy kimeneti könyvtár url-címét (szintén egy blobtárolóban). A feladat elindítása után a felhasználó ellenőrizheti az állapotot a feladat indításakor megadott URL-cím helyének lekérdezésével. Egy adott feladat csak bizonyos típusú műveleteket hajthat végre (létrehozás, frissítések vagy törlések). Az exportálási műveletek végrehajtása hasonló módon történik.

Importálás

Beállítás

Ez a szakasz a következő entitásokat feltételezi:

Bemeneti fájl létrehozása és tárolása blobban

A bemeneti fájlok az XML-ben szerializált regisztrációk listáját tartalmazzák, soronként egyet. Az Azure SDK használatával az alábbi példakód bemutatja, hogyan szerializálhatja a regisztrációkat, és töltheti fel őket a blobtárolóba:

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);
     }
}

Fontos

Az előző kód szerializálja a regisztrációkat a memóriában, majd feltölti a teljes streamet egy blobba. Ha néhány megabájtnál több fájlt töltött fel, tekintse meg az Azure Blob útmutatóját a lépések végrehajtásához; például blokkblobok.

URL-jogkivonatok létrehozása

A bemeneti fájl feltöltése után hozza létre az értesítési központnak a bemeneti fájlhoz és a kimeneti könyvtárhoz tartozó URL-címeket. A bemenethez és a kimenethez két különböző blobtároló használható.

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);
}

Feladat küldése

A két bemeneti és kimeneti URL-címmel most már elindíthatja a kötegelt feladatot.

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--;
}

A bemeneti és kimeneti URL-címek mellett ez a példa egy NotificationHubJob objektumot tartalmazó JobType objektumot is létrehoz, amely az alábbi típusok egyike lehet:

  • ImportCreateRegistrations
  • ImportUpdateRegistrations
  • ImportDeleteRegistrations

A hívás befejezése után az értesítési központ folytatja a feladatot, és a GetNotificationHubJobAsync hívásával ellenőrizheti annak állapotát.

A feladat befejezése után az eredmények vizsgálatához tekintse meg a következő fájlokat a kimeneti könyvtárban:

  • /<hub>/<jobid>/Failed.txt
  • /<hub>/<jobid>/Output.txt

Ezek a fájlok tartalmazzák a köteg sikeres és sikertelen műveleteinek listáját. A fájlformátum az .cvs, amelyben minden sor az eredeti bemeneti fájl sorszámával és a művelet kimenetével (általában a létrehozott vagy frissített regisztrációs leírással) rendelkezik.

Teljes mintakód

Az alábbi mintakód egy értesítési központba importálja a regisztrációkat.

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);

        }
    }
}

Exportálás

A regisztráció exportálása hasonló az importáláshoz, a következő különbségekkel:

  • Csak a kimeneti URL-címre van szüksége.
  • Létre kell hoznia egy ExportRegistrations típusú NotificationHubJob feladatot.

Mintakódrészlet

Az alábbiakban egy mintakódrészletet vizsgáljuk meg a Regisztrációk Java-ban való exportálásához:

// 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;
}

Következő lépések

A regisztrációkkal kapcsolatos további információkért tekintse meg a következő cikkeket: