先日作成した Azure Storage のコンテナをバックアップするプログラムは、高速化しても完了までに 5 時間弱かかる。
こいつを毎日実行するのは気が引ける。コンテナの完全バックアップは週一回にしておき、増分バックアップを毎日取る方針に切り替えた。
最初、増分バックアップも完全バックアップ同様にコンソールアプリケーションで作成し、夜間に実行しようと思ったけど、ふと閃いた。Azure Functions を使えば良いのでは、と。Azure Functions はブロブが登録されたのをトリガーに起動できるから、都度コピーすれば増分バックアップの出来上がりってことになる。
早速 Azure Functions を書いてみた。ソースコードを Git で管理したかったので、Visual Studio で Azure Functions プロジェクトを作成している。コードは次の通り。
using System; using System.IO; using System.Threading.Tasks; using Microsoft.Azure.WebJobs; using Microsoft.Azure.WebJobs.Host; using Microsoft.WindowsAzure.Storage; using Microsoft.WindowsAzure.Storage.Blob; namespace AzureStorageIncrementalBackup { // Azure Functions を使って増分バックアップ public static class AzureStorageIncrementalBackup { // ブロブが登録されると起動する [FunctionName("AzureStorageIncrementalBackup")] public static void Run([BlobTrigger("mycontainer/{name}", Connection = "AzureWebJobsStorage")]CloudBlockBlob myBlob, TraceWriter log) { CopyBlobAsync(myBlob, log).GetAwaiter().GetResult(); } // 日本標準時の現在時間を取得する static DateTimeOffset JstNow => DateTimeOffset.UtcNow.ToOffset(TimeSpan.FromHours(9)); // ブロブをバックアップ用のストレージアカウントにコピーする static async Task CopyBlobAsync(CloudBlockBlob myBlob, TraceWriter log) { var destConnectionString = "<コピー先のストレージアカウントの接続文字列>"; var destStorageAccount = CloudStorageAccount.Parse(destConnectionString); var destBlobClient = destStorageAccount.CreateCloudBlobClient(); // 今日の日付のコンテナが無ければ作る var destContainerName = $"mycontainer-incremental-{JstNow.ToString("yyyyMMdd")}"; var destContainer = destBlobClient.GetContainerReference(destContainerName); try { await destContainer.CreateIfNotExistsAsync(); } catch (Exception e) { log.Error(e.Message); } try { var destBlockBlob = destContainer.GetBlockBlobReference(myBlob.Name); log.Info($"{destBlockBlob.Name} にバックアップします。"); using (var stream = await myBlob.OpenReadAsync()) { await destBlockBlob.UploadFromStreamAsync(stream); } log.Info("バックアップ成功"); } catch (Exception ex) { log.Error(ex.Message); log.Info("バックアップ失敗"); } finally { log.Info("バックアップ完了"); } } } }
Microsoft Azure ポータルから Function App を作成し、Visual Studio から発行すればデプロイ完了。今回の要件は Azure Functions にピッタリだった。