『王様達のヴァイキング(14)』を読んだ

ラスボスが登場して、いよいよ最終決戦かと思っていたけど、まだ続くみたい。 ラスボスが日本のトップになるとはね。まさに魔王だな。

勇者是枝御一行は、かつての宿敵をパーティに加え、魔王の懐に潜り込んで討伐の機会をうかがうわけだが、そこで開発するサイバー防衛システムは、自分には非現実的過ぎるな。犯罪者を識別する顔認識は機械学習だと思うけど、通信を傍受する方は専門外なので、ちょっと実現方法が思いつかない。

ラスボスが登場したあたりから、作中に登場するテクノロジーが現実を超えてきた気がする。 もう SF。 今までリアルに感じていただけに、高度に発達したテクノロジーは魔法と区別つかない、というのを擬似体験した気分だ。

王様達のヴァイキング(14) (ビッグコミックス)

王様達のヴァイキング(14) (ビッグコミックス)

一心不乱

赤のれんに行ったら結構並んでいて、待っていたら昼休みが終わりそうだったので、予定変更。すぐ近くにある『一心不乱』に入った。

食べたのは『黒のコクとんこつラーメン』とご飯と餃子のセット。久しぶりに食べる濃厚とんこつは、スープに確かなコクがあって旨し。自分の中のとんこつランキングで結構良い線いってる。

餃子はニンニクが効いていて、これまたイケル。 3個じゃ食べ足りなかったけど、 ご飯は追加料金なしで大盛りにしてもらえたので、満足度は高い。

『みんなの Go 言語』を読んだ

少しずつ読み進めて、ようやく読了。技術書なのに雑誌っぽい紙面で、まるで WEB+DB PRESS を読んでいるみたいだった。

中身は実際にアプリケーションを開発するときに使える TIPS で溢れていて、チュートリアルと本書を読めば Go 言語入門はひとまず終了してよさそう。あとは実践あるのみ。

みんなのGo言語【現場で使える実践テクニック】

みんなのGo言語【現場で使える実践テクニック】

Azure Functions を使った Azure Storage の増分バックアップ

先日作成した Azure Storage のコンテナをバックアップするプログラムは、高速化しても完了までに 5 時間弱かかる。

tnakamura.hatenablog.com

こいつを毎日実行するのは気が引ける。コンテナの完全バックアップは週一回にしておき、増分バックアップを毎日取る方針に切り替えた。

最初、増分バックアップも完全バックアップ同様にコンソールアプリケーションで作成し、夜間に実行しようと思ったけど、ふと閃いた。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 にピッタリだった。

WCF on .NET Core

.NET Core でも WCF を使うことはできる。提供されているのはクライアントライブラリだけなので、.NET Core で動く WCF サービスを作ることはできないけど。

試しに TCP でやってみた。WCF サービスは .NET Framework で作るしかない。

using System;
using System.Runtime.Serialization;
using System.ServiceModel;

namespace DotNetFrameworkWcf
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.Title = ".NET Framework WCF";

            var host = new ServiceHost(typeof(BookService));
            host.AddServiceEndpoint(
                typeof(IBookService),
                new NetTcpBinding(),
                "net.tcp://localhost:8080/BookService");
            host.Open();

            Console.WriteLine("Enter で終了");
            Console.ReadLine();

            host.Close();
        }
    }

    [DataContract]
    public class Book
    {
        [DataMember]
        public string Author { get; set; }

        [DataMember]
        public string Title { get; set; }

        [DataMember]
        public decimal Price { get; set; }
    }

    [ServiceContract]
    public interface IBookService
    {
        [OperationContract]
        Book Echo(Book book);
    }

    public class BookService : IBookService
    {
        public Book Echo(Book book)
        {
            Console.WriteLine($"{book.Author} - {book.Title} \\{book.Price}");
            return book;
        }
    }
}

.NET Core のコンソールアプリケーションを新規作成し、System.ServiceModel.NetTcp パッケージを追加。

www.nuget.org

WCF サービスを呼び出してみる。ChannelFactory の使い方がちょっと違うけど、悩むほどではない。

using System;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Channels;

namespace DotNetCoreWcf
{
    using DotNetFrameworkWcf;

    class Program
    {
        static void Main(string[] args)
        {
            Console.Title = ".NET Core WCF";

            var factory = new ChannelFactory<IBookService>(
                new NetTcpBinding(),
                new EndpointAddress("net.tcp://localhost:8080/BookService"));
            var channel = factory.CreateChannel();

            var result = channel.Echo(new Book()
            {
                Author = "赤坂アカ",
                Title = "かぐや様は告らせたい 7",
                Price = 500,
            });
            Console.WriteLine($"{result.Author} - {result.Title} \\{result.Price}");

            Console.WriteLine("Enter で終了");
            Console.ReadLine();

            ((IChannel)channel).Close();
        }
    }
}

namespace DotNetFrameworkWcf
{
    [DataContract]
    public class Book
    {
        [DataMember]
        public string Author { get; set; }

        [DataMember]
        public string Title { get; set; }

        [DataMember]
        public decimal Price { get; set; }
    }

    [ServiceContract]
    public interface IBookService
    {
        [OperationContract]
        Book Echo(Book book);
    }
}

先にサービスを起動しておいて、クライアントを実行。

f:id:griefworker:20171124173150p:plain

.NET Framework で作った WCF サービスを、.NET Core から問題なく呼び出せた。.NET Core で WCF サービスは需要無いだろうから、今後もパッケージが提供されることはないんだろうな。

実際、自分も必要としているのはクライアント側だけで、.NET Core で WCF サービスを作りたいとは思わない。.NET Core で動かしている ASP.NET Core アプリケーションから、レガシーな WCF サービスを呼び出せれば十分。

『星野、目をつぶって。(8)』を読んだ

8 巻は高校最大のイベントと言っていい修学旅行。 体育祭で一躍ヒーローになった小早川だが、だからといって班を組めるかどうかは別問題というのは、マンガなのに厳しい。

この修学旅行で小早川・星野・松方・加納の関係に何か変化が起こるかなと思っていたら、まさかの急展開。おいおい、このタイミングでマジですか?早すぎない? ここからどういう風にストーリーを展開していくのか、ちょっと読めない。 各自のケジメとかどうすんだろうね。今後はそこがメインになるのかな。 ハラハラしてきた。

『かぐや様は告らせたい(7)』を読んだ

7 巻は生徒会選挙編。 対立候補として新たに登場する伊井野ミコが、これまた良いキャラクターだった。清廉潔白かつ品行方正で、前生徒会メンバーとは性格的に衝突しそう。かぐやなんて、目的のためには手段を選ばないタイプなので特に。

肝心の選挙は会長というか元会長が勝つんだが、選挙当日の白銀の行動は器の大きさが表現されていて見事。いやぁ、あんな勝ち方をするとはね。ミコは大方の予想通り生徒会に参加するみたいで、生徒会メンバーとの絡みもこれから増えるだろうし、今後が楽しみ。