kitak blog

Kみたいなエンジニアになりたいブログ

2020-01-31 アトレティコ、カバーニ獲得失敗、カラスコ復帰

1月ももう終わり。ここ数日は確定申告の準備で、昨年の会計データの内容を確認したり、必要な書類を集めたりしていた。用意した一式を毎年申告の書類作成をお願いしている税理士の人に送る。

仕事は久しぶりに Nuxt を書いているのと、バックエンドのAPIの実装。やりとりは gRPC Web でやっているのだけど、どハマりしてしまってつらかった(この件はまとめて改めてエントリを書く)。
端的に書くと protobuf の仕様をサーバーとクライアントそれぞれの言語の実装が満たしていないことによるものだった。dart の protobuf 実装は、デフォルトでエンコーディングすべきものをエンコーディングしていないのと(proto3 だとrepeatedフィールドのpackedエンコーディングはデフォルトで使用するはず)、js の protobuf 実装はエンコーディングされていなくてもパースできるはずのものをパースできなかった。
いったんは proto のファイルに [packed=true] を指定することで乗り切るけど、各ライブラリを本当は直すべき。

サッカーは冬の移籍マーケットが閉まる。アトレティコは、今シーズンの得点力不足を解消するために、ウルグアイ代表でパリ・サンジェルマン所属のエディソン・カバーニを狙っていたのだけど、移籍金の折り合いがつかなくて断念したらしい。うーん、数年前からシメオネカバーニの獲得を熱望していて、カバーニ本人も移籍したがっているという相思相愛の状況だったのに残念。ワールドクラスのストライカーなのにハードワークで献身的に守備をする、相方のフォワードを引き立てる黒子の役に徹することができる、というプレースタイルはアトレティコに合ってそうなので、夏のマーケットでぜひ来てほしい。
それとは別で、2018年にアトレティコから大連一方に移籍したベルギー代表のカラスコの復帰が決定。フォワードではないけれど、攻撃的ミッドフィールダーでドリブルがえぐい。ジョアン・フェリックスが怪我して、フォワード陣がモラタ、コレア、シャポニッチしかいない危機的な状況の中で明るい話題。明後日は、いよいよマドリードダービーなので楽しみ。

アトレティコ、マドリードダービーの前に不安が残る結果

朝起きて、疲労抜きジョグをする予定だったけれども雨が降っていたので中止。本を読んだり、コードを書いたりして9時ごろまで過ごす。

毎週日曜にやっている朝活のために表参道へ。ピースオブケイクのオフィスで、もくもくコードを書く。そこそこ集中できたかな。

13時ごろに表参道の清水湯へ。冷温交代浴で昨日のランニング練習の疲労を抜きたかったのだけど、入り口の靴箱に空きがないぐらい混雑していて断念。もうちょっと昼下がりに行かないとダメだなー。日曜の昼の表参道はどの店も混雑している印象。おとなしく帰宅。

適当にテレビを付けたら、テセウスの船の第一話の再放送をやっていて、面白そうだったので原作の漫画をKindleで買って一通り読んだ。面白かったけど、猟奇的な殺人犯が出てくるやつをタイムスリップで少しアレンジしたぐらいの内容かな、という感想だった。

相撲は初場所の千秋楽。正代の取り組みを見て、結びの一番まで時間があったので、それまで疲労抜きジョグ。太ももや股関節にダメージがきているなぁ。30分ほど走って戻ったら、ちょうど結びの一番。徳勝龍が貴景勝に勝って、優勝決定。うーん、正代との優勝決定戦が見たかったw 徳勝龍は場所中に大学時代の恩師の方が急逝されたらしく、並々ならぬ思いだったんだろうなぁ。勝った後に堪えられずに涙が流れていたのが印象的でした。
平幕の力士が力を付けてきていて、横綱大関を脅かしていたのが今場所の印象。世代交代が近づいてきているのかな。来場所も楽しみ。

20時からラ・リーガ 第21節 アトレティコvsレガネスをライブで見る。先週、国王杯のラウンド32でセグンダB(3部)のチーム相手に負けたので、ここで勝って気持ちを切り替えて、来週のマドリードダービー(vsレアル・マドリー)に繋げたい。にしても、都並敏史さんの解説はワイルドというか、選手に対する愛が溢れ出ていていいなぁ。
試合は相変わらず、守備の立ち上がりが悪くてヒヤヒヤすることが多数、後半主導権を握って相手のゴールに迫ることが増えたけれども、攻撃の厚みが足りなくて決まらない。終了間際にセルビアU21代表のシャポニッチが交代でリーガデビュー(多分)。普通にマッチしているかんじだったので、これからの活躍に期待。
結局、試合はスコアレスドローという結果。レアル・マドリー、今シーズン昇格で大物を食っているグラナダバレンシアリヴァプールと手強い相手との対戦が続く前の内容としては不安が残る... シメオネが解任されないか心配だ。

ひさしぶりの皇居ラン

ということで、ポイント練習のために久しぶりの皇居ランへ。一周5kmで適度に起伏がある皇居はポイント練習にちょうどいい。ランステは、いつものサクラホテル神保町。神保町駅から近くて、皇居にもすぐに行ける。シャワーにプラスして、走った後のご褒美のビールのセットもあって、 世界各地のビールが選べる。だれかと一緒に来た時は大抵これ。がんばってシャワーを浴びた後に飲むビールのうまいことうまいこと(本日はひとりなので飲まないけどね)。

皇居まで、準備運動がてら軽くジョグ。土曜なので、平日よりもランナーが多い印象。皇居に着いたら、タイムトライアル 5kmを2セットこなす。久しぶりに来たら、道が新しく舗装されている箇所があって、前よりも走りやすくなっていた。ゼーハーゼーハー言うまで追い込んだので、なかなかしんどいw

坂道のおかげもありそうだけど、1km、5km、10kmのタイムを更新!10kmをキロ4'36のペースで走った。久しぶりの記録更新なので、うれしい。Garminのトレーニングの効果の計測だと有酸素系はオーバーペースということだったので、負荷をかけすぎたかもしれない。無酸素系はそこそこの向上。無酸素系はスプリント走とか坂道インターバルで重点的にやったほうがいいかもしれない。

走り終わった後はご褒美で共栄堂のスマトラカレー。開店直後だったので、並ばずに入れた。スマトラカレーの独特のスパイスの香りがして、おいしい。走った後で身体が塩分を求めているからか、ちょっと塩をふって食べたら大正解。スマトラカレー、渋谷でもっと本格的なやつを食べたときは「うおっ!」ってなるぐらい香り?辛さ?が強烈だったのだけど、共栄堂のやつは日本人に合わせたマイルドな味。なんとなくビーフにしたけど、周りのオーダーを見てたらチキンが多かった。次はチキンも食べてみよう。

カレーを食べた後はなんとなく髪を切りたくなったので、渋谷へ。引っ越して半年以上経つけど、相変わらず旧居の近くのお店に通っている。早いし、安いんだよなぁ。髪を切った後は近くのハーツライトコーヒーへ。髪を切る場所を変えないのは、このお店かCONROW、うさぎに行く口実を作るためかもw
お店のお兄さんと、旧居の近くにあった自動車整備のお店やナイキの厚底シューズなどよもやま話。近くにできたカリカリスパイスというカレー屋がおいしいそうなので、今度いってみよう。

コーヒーを飲んだ後は Fab cafe などカフェを転々として、もくもく。どこも混んでるなぁ。区切りがいいところで、家に帰って相撲を見る。
優勝候補だった貴景勝が朝乃山に敗れて、レースから脱落。悔しそうな顔をしていたなぁ。アナウンサーが読み上げる「強くなって来場所帰ってきます」というコメントからも悔しさが滲み出ていた(本人の声じゃないんだけどw)。でも、互いにぎりぎりのところで踏みとどまって攻守が入れ替わる良い相撲だった。来場所も、朝乃山とのライバル対決が楽しみ。

ASP.NET Core のアプリで Firebase 認証

.NET Core の gRPC とか C# の Firestore クライアントを触る - kitak blog で書いたアプリに Firebase の認証を組み込む。具体的にはクライアントの Firebase SDK で生成した ID トークンの検証をおこない、ユーザーの id を取得する。.NET Core のバージョンは 3.1.0

ASP.NET Core には認証や認可の機能が含まれているので、Startup.cs でそれぞれのサービスとミドルウェアを登録してあげればよい。事前に利用する認証スキームのパッケージをインストールしておく。Firebase Authentication の場合は Microsoft.AspNetCore.Authentication.JwtBearer

dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer

サービスの登録

[Project ID] は Firebase のプロジェクトIDで置き換える。

public void ConfigureServices(IServiceCollection services)
{

    // ...

    services.AddAuthorization(options =>
    {
        options.AddPolicy(JwtBearerDefaults.AuthenticationScheme, policy =>
        {
            policy.AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme);
            policy.RequireClaim(ClaimTypes.Name);
        });
    });
    services
        .AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddJwtBearer(options =>
        {
            options.Authority = "https://securetoken.google.com/[Project ID]";
            options.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuer = true,
                ValidIssuer = "https://securetoken.google.com/[Project ID]",
                ValidateAudience = true,
                ValidAudience = "[Project ID]",
                ValidateLifetime = true
            };
        });

   // ...
}

ミドルウェアの登録

呼び出す順番が重要なので注意

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    // ...

    app.UseAuthentication();
    app.UseAuthorization();

    // ...
}

アクセスの制御

実際にアクセスを制御するには、制御したい gRPC のサービスのクラスかメソッドに Authorize 属性を指定する。ユーザーの情報は ServerCallContext から取得できる。

[Authorize]
public override Task<HelloReply> SayHello(HelloRequest request, ServerCallContext context)
{
    var user = context.GetHttpContext().User;
    var uid = user.Claims.Where(claim => claim.Type == "user_id").FirstOrDefault().Value;
    
    // ...
}

.NET Core アプリを Cloud Run にデプロイする

.NET Core の gRPC とか C# の Firestore クライアントを触る - kitak blog で書いたアプリを Cloud Run にデプロイしてみた。

Docker を使用してアプリをコンテナー化するチュートリアル - .NET Core | Microsoft Docshttps://cloud.google.com/run/docs/quickstarts/build-and-deploy?hl=ja を参考に進めた。

Dockerfile は、こんなかんじ。

# Use Microsoft's official lightweight build .NET image.
# https://hub.docker.com/_/microsoft-dotnet-core-sdk/
FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build
WORKDIR /app

# Install production dependencies.
# Copy csproj and restore as distinct layers.
COPY *.csproj ./
RUN dotnet restore

# Copy local code to the container image.
COPY . ./
WORKDIR /app

# Build a release artifact.
RUN dotnet publish -c Release -o out

# Use Microsoft's official runtime .NET image.
# https://hub.docker.com/_/microsoft-dotnet-core-aspnet/
FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS runtime
WORKDIR /app
COPY --from=build /app/out ./
ENV ASPNETCORE_ENVIRONMENT Production
ENV PORT 8080

# Run the web service on container startup.
ENTRYPOINT ["dotnet", "GrpcGreeter.dll"]

Cloud Run にデプロイするにあたって、Program.csCreateWebHostBuilder の定義を以下のように書き換える。ポートを環境変数で指定できるようにするのと、IPアドレス0.0.0.0 にする。

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                string port = Environment.GetEnvironmentVariable("PORT") ?? "8080";
                webBuilder.ConfigureKestrel(options =>
                {
                    // Setup a HTTP/2 endpoint without TLS.
                    options.Listen(IPAddress.Any, int.Parse(port), o => o.Protocols = 
                            HttpProtocols.Http2);
                });
                webBuilder.UseStartup<Startup>();
            });
    }

イメージのビルド&デプロイはドキュメントの通りで、

gcloud builds submit --tag gcr.io/[PROJECT-ID]/greeter

gcloud beta run deploy --image gcr.io/[PROJECT-ID]/greeter

で、とっても簡単。

ちょっと前まで Windows だけでしか動かなかったサービスが Googleクラウドで動くのだから、すごい時代(コンテナ・ Docker が普及したのが大きそう)。

デプロイしたサービスのシャットダウンは GCP のコンソールから行う。

足の治療院に行ってきた 2020年1月

毎月行っている足の治療院へ。

ちょうど数日前にビルドアップ走をしてから、足首やら足の付根が痛くなっていたので、相談に乗ってもらった。日に日に痛みはなくなってきているので、普通に負荷がかかりすぎたんでしょう、とのこと。

心肺機能を向上させるために、週に1,2回、ゼーハーゼーハー言いながら走っているのだけど、そこまで追い込むと足にけっこうなダメージが与えているという課題が浮き彫りになった。筋肉が硬くて動きが悪いのを無理に動かそうとして、足がダメージを受けているので、ストレッチで筋肉を柔らかくして身体を動かしやすくしましょう、という話になった。
具体的には走り終わった後とかお風呂に入った後に、ふくらはぎ、腿前、腿裏、お尻の静的ストレッチを5分以上やる。アプリとか Pixela で記録をつけるといいかも。

.NET Core の gRPC とか C# の Firestore クライアントを触る

仕事で扱っていないフレームワーク・言語になにか触れてみようと思い、.NET Core (C#) を触ってみた。

C# は学生時代に Windows 向けのアプリケーションを授業で作ったとき以来に書く。当時はまさか、.NET のクロスプラットフォームオープンソースな実装が使える時代が来るとは全く思っていなかった。

とりあえず gRPC のサーバーを作ってみようと思い、以下のチュートリアルをやってみる。

docs.microsoft.com

gRPC が .NET Core にシームレスに統合されていて感動。Visual Studio Code .NET Core SDK (dotnet コマンド) の組み合わせでやったけれど、サーバーの起動まわり以外はハマることなく、さくさく進めることができた。チュートリアル中でもちゃんとケアしてくれているけれど、Mac OS では HTTP/2 over TLS でサーバーを起動できないので注意( .NET Core での gRPC のトラブルシューティング | Microsoft Docs を参照)、TLS を外したら次はクライアントで .NET Core での gRPC のトラブルシューティング | Microsoft Docs でハマるので注意。

DI コンテナも標準で ASP.NET Core に入っていてうれしい ( ASP.NET Core での依存関係の挿入 | Microsoft Docs )

gRPC のチュートリアルを一通りこなして、次は Firestore のクライアントを触ってみることにした ( Cloud Firestore を使ってみる  |  Firebase )。 ドキュメントを試しに書き込んでみたのだけど await で実行がフリーズしてしまった。調べたら、Firestore のクライアントが依存している gRPC のバージョンと、.NET Core が依存している gRPC のバージョンで互換性がないのが原因らしい。

github.com

次のメジャーバージョンでアップデートするそうなので( Major Version Plan | Google Cloud APIs )、一回休み。対応されるまでは、Entity Framework と MySQL の組み合わせを試してみる。