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:
- Kiépített értesítési központ.
- Egy Azure Storage-blobtároló.
- Az Azure Storage NuGet-csomagra és a Notification Hubs NuGet-csomagra mutató hivatkozások.
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: