hirapi's blog

ちゃんとしたふりをする

builderscon tokyo 2018 聴講メモ #6「ブログサービスのHTTPS化を支えたAWSで作るピタゴラスイッチ」by aerealさん

speakerdeck.com

※ 以下は私個人の解釈を多大に含んだメモ書きです。正確な講演内容はスライドか、もしくはYouTubeで公開される(?)公式動画をご覧ください。

ブログサービスのHTTPS化を支えたAWSで作るピタゴラスイッチ

@aereal

はてな

テーマ

テイクホームメッセージ

  • バッチシステムについても、ソフトウェア構築一般の原則が使える
    • 状態を持たない
    • 分割統治
  • ↑↑実現するための一例として、
    • ワークフローエンジン:AWS StepFunctions
    • pub/subをサポートするデータストア:DynamoDB

内容めも

  • Let's encrypt
    APIで証明書発行が可能
    はてなから寄付も。これから継続していく
  • 万単位のドメイン。発行・管理を自動化しないと有料プランのサービスとしてきつい

  • 配信の要件

    • 万単位のドメイン → メモリ使用量増加、nginxリロード時間増加
      → リクエスト毎にDBやキャッシュから証明書を取得
    • SAN:1証明書に複数ドメイン はどうか? → LEでSANを利用する場合、DNSの設定に制限
    • ACME:証明書発行の自動化プロトコル ← LEが中心に策定を進めている仕様
      ACMEチャレンジ(所有者確認)
  • 発行の要件

    • 無効なドメインは削除しなければならない
      無効なドメインACMEチャレンジに失敗する。
      かつ、LEのAPIには失敗上限がある
    • 要求は高いが不確実性は高い ← 外部APIと通信する、設定はユーザーに任せている
      → 失敗しても一連のフローが完了する必要がある
    • ドメイン数が増えても、実行時間が伸びたりしない
      複数のドメインを1回のバッチで処理しようとすると、失敗したドメインだけリトライというのが難しい
  • 発行の実装

    • AWS Step Functions:JSONでステップ実行を記述
    • はてな → StepFunctions → Lamda → LE → DB・StepFunctions(戻る)
  • 更新の実装

    • DynamoDBのTTL Trigger → StepFunctions
      TTL Trigger:アイテムが寿命を迎えて自動的に削除されたことが流れるストリーム
      → pub/sub形式。都度見に行って対象データを集めてくる処理がバッチのスコープから外れる。
    • AWS SFnでエラーハンドリング
  • 考察:ピタゴラスイッチ
    巨大なバッチの難しさ

    • 全体でどれだけあって、どこで失敗しうる/したのか把握しにくい
      全体がわからないとどこにどう手を入れていいかわからなくなる
    • 巨大なバッチ、扱うデータ量が巨大 → 処理時間が長くなる。成功/失敗のログが必要
  • さいきょうのピタゴラスイッチ

    • ワークフローエンジンの導入
    • 分割統治
      バッチ処理側がデータの状態を気にしなくていいようにする
      アプリケーション書くときは意識できてるのに、なぜバッチ設計ではできないのか?
      • 合成可能ではない
  • 合成可能なバッチ

    • 直列実行を二項演算ととらえてみる
      • operand:責任範囲が小さいこと(1つの演算子が1つの処理を担当する)
        コンポーネントの責任を小さくする
      • operator:様々な法則を満たす
        ステップの副作用を小さくする
    • → 局所状態を持たない local state
      各ステップが変わりうる状態を持つのではなく、グローバルに状態を持つようにする
      グローバル変数みたいなものなら、悪ではないか?
      → 違う。グローバル変数のように誰でも変更できるものではなく、ワークフローエンジンだけが状態を持ち、バッチ処理はそれを受け取るだけになる

質疑

  • SFnのテスト
    ダミーのLamdaを呼び出すようにして動かしてみた
  • TTL Triggerで失敗したとき、DynamoDBから消えているからリトライできてないんでは?
    TTLを仕込んだテーブルと仕込んでないテーブルの2つがある。
    TTLは証明書の期限より2週間くらい早く設定している。
    リトライにも失敗したらMackerelから通知が来るのでログを元に手動対応。
  • proxyのリロード、メモリにのっていたもの消えちゃうんでは?
    proxyのリロード = nginxのプロセス再起動。memcachedにのっているのでnginxを立ち上げ直しても影響はしない。
    memcachedにも無かったらDynamoDBに取りに行くが、そのときの遅延も許容範囲内だった。
  • AWS SFnの設定をJSONで書くの、気持ちのいいもの?w
    全体でどういう状態があるか、みたいなスキーマが特に無いから今は平気。
    だけどミスったときに検知できない。バッチ側から可能的な状態一覧を生成するようにしたい。。。

感想

ソフトウェア設計の考え方をこういうシステム設計に適用するっていうの、ちらちら思ってたけど全然実現できてなくてすごく参考になった。
TTL Triggerみたいなマネージドサービスの機能をきれいに使ってるの見て、自分の思考がアプリケーション(プログラム)の中に閉じてたのに気づいた。
解くべき問題(要件)をまとめた後、何が最短経路かを構成全部から考えられるようになりたい。

こういう設計力、勉強というより実際のサービス設計・運用とかその過程でのディスカッションとかから得られるのかなあ。
日常にディスカッションが足りない……。