はい、5月2日、火曜日ですね。時刻は朝9時10分になりました。
今日は、昨日と変わって、かなり良い天気ですね。東京はですけども。はい、おはようございます。
めめめのkeethこと、くわはらです。ではでは、本日も朝活を始めていきたいなと思います。
本日は、昨日とまた違った記事なんですけども、タイトルになります。
THE TWELVE-FACTOR APPっていう記事ですね。こちらを読んでいこうと思います。
これですね、僕だいぶ前に、前職ですね、の先輩に教えていただいたんですけど、そこから結局ちゃんと読んでなかったなっていうのがあって、
ちょっと今日のところから、この記事のリンクを見つけまして、ちょっと読もうかなと思ったので、今日はこの記事を読んでいこうと思ってます。
で、おそらくですけどね、これ全部を読み切るのは多分今日は不可能だと思うので、何日かにわたって読んでいこうかなと思ってますので、お付き合いいただければ幸いです。
では、早速入っていきましょう。
あと、ちなみにこの記事、基本的には英語なんですけど、ちゃんと日本語訳もされてますので、今日はその日本語訳の方を読んでいこうと思っております。
じゃあ入ります。
はじめに、現代ではソフトウェアは一般にサービスとして提供され、ウェブアプリケーションやソフトウェアアザサービスと呼ばれるようになりました。
THE TWELVE-FACTOR APPっていうのは、次のようなソフトウェアアザサービスを作り上げるための方法論になります。
セットアップ自動化のために、宣言的なフォーマットを使い、プロジェクトに新しく加わった開発者が利用する時間とコストを最小化する。
仮想のOSへの依存関係を明確化し、実行環境間での移植性を最大化する。
モダンなクラウドプラットフォーム上に、超絵のデプロイに適しており、サーバー管理やシステム管理を不要なものにする。
開発環境と本番環境の差異を最小限にし、アジリティを最大化する継続的デプロイを可能にする。
ツール、アーキテクチャ、開発プラクティスを大幅に変更することなく、スケールアップできる。
トゥエレブ・ファクターの方法論は、どのようなプログラミング言語で書かれたアプリケーションにでも適用できます。
また、どのようなバックエンドサービス、いわゆるデータベース、メッセージ給、メモリーキャッシュなどの組み合わせを使っていても適用できるよ、というものですね。
はい。
読んでいただくことで、プテラノノさんですね。ご参加いただきありがとうございます。今日もこのままダラダラと読んでいこうと思ってます。
はい。
続いて背景ですね。このドキュメントへの寄稿者は、何百ものアプリケーションの開発とデプロイに直接関わり、
ヘロクプラットフォーム上での仕事を通して、何百何千ものアプリケーションの開発運用スケールに間接的に立ち会いました。
このドキュメントは、多種多様なサーフアプリケーション開発現場での私たちの経験と観察をまとめたものであります。
これは、アプリケーション開発における理想的なプラクティスを見出すための三角測量であります。
特に、アプリケーションが時間とともに有機的に成長する力学、アプリケーションの行動ベースに取り組む開発者間のコラボレーションの力学、
そして、ソフトウェア腐敗によるコストの回避というところに着目をしています。
別なんですけど、ソフトウェア腐敗によるコストの回避というところは別の記事のリンクが貼られてますので、それも見てみてください。
私たちの動機は、私たちがモダンなアプリケーション開発で見てきた、ある種のシステム的な問題への関心を高めること、
その問題を議論するための共通の語彙を提供すること、そしてこの問題に対する広い概念的な解決策と専門用語を提供することになります。
このフォーマットはマーティン・ファウラーの書籍、パターンズ・オブ・エンタープライズ・アプリケーション・アーキテクチャー及びリファクタリングに着想を得ています。
マーティン・ファウラーのブログも久しぶりに読みたいですね。
ちょっと抽象度が高かったり、彼の独自な考え方があったりして読むのが難解なブログが多いんですけど、それでもやっぱり刺激というか気づきが多いので、
彼のブログも今回のこのテールファクターが終わったら読んでいこうかなと思いますね。
続いてこのドキュメントの対象者ですね。
サービスとして動くアプリケーションを開発している全ての開発者というのがこのドキュメントの対象者になります。
およびそのようなアプリケーションをデプロイまたは管理しているインフラエンジニアというところも対象です。
結局ほぼほぼサービス開発に関わっているエンジニア全てって感じがしますね。
というところで今のが冒頭の話、初めの話でした。
では早速入っていきたいと思います。
1つ目ですね。
12の1つ目はコードベースになります。
バージョン管理されている1つのコードベースと複数のデプロイというお話から入ります。
12ファクターアップはGitやマーキュリアルとサブバージョンなどのバージョン管理システムで常に変更を追跡しております。
リビジョン追跡データベースのコピーというのはコードリポジトリと言われ単にリポジトリとも言われます。
僕らが一般的に使っているのはGitHubリポジトリとかいうやつですね。
コードベースは単一のリポジトリ、サブバージョンのような集中バージョン管理システムの場合ですね。
単一のリポジトリまたはルートコミットを共有する複数のリポジトリ、これがGitのような分散バージョン管理システムの場合ですね。
などなどになります。
コードベースとアプリケーションの間には常に1対1の関係があります。
複数のコードベースがある場合それはアプリケーションではない、それは分散システムになります。
分散システムのそれぞれのコンポーネントがアプリケーションであり個別に12ファクターに適合することができます。
同じコードを共有する複数のアプリケーションは12ファクターに違反しています。
その場合の解決策は共通のコードをライブラリに分解しそのライブラリを依存関係管理ツールなどで組み込むようにできることです。
この依存関係管理ツールというところも別の12ファクターの別の章にあるのでこれ後ほど読んでいこうと思います。
アプリケーションごとにただ一つのコードベースが存在するがアプリケーションのデプロイは複数存在する。
デプロイはアプリケーションの実行中のインスタンスである。
これは通常一つの本番サイトと一つ以上のステージングサイトであります。
さらに全ての開発者はローカル開発環境で動作するアプリケーションのコピーを持っておりそれらもデプロイとみなせます。
さらに言うとプロダクションも別に一つではなくて複数サーバーに同じものを入れておいて
大量アクセスとかをロードバランサーでかましておいて複数の方に切り分けることができたりするのでプロダクションも普通に複数デプロイとかあり得ますよね。
なので同じコードの複数アプリケーションというのは違反してますが
一つのコードの一つアプリケーションを複数のデプロイに渡っているというのは別に正しいよという話ですね。
デプロイごとに異なるバージョンがアクティブであるかもしれないが
コードベースは全てのデプロイを通して同一であります。
はい、そりゃそうだよね。
例えば開発者はステージング環境にまだデプロイされていないコミットを抱えているし
ステージング環境には本番環境にデプロイされていないコミットが含まれています。
しかしこれらのデプロイは全て同一のコードベースを共有しているため
同一のアプリケーションの異なるデプロイであるというふうに認識もできます。
ここは僕らが普段やっている開発とよく似ているというかそれをちゃんと言語化したって言うんですね。
それがもし似ているなという感触をされているのであれば
皆さんはこの12ファクターアップの書き方通りになっているということですね。
すみません、また救急車とか消防車がうるさいのでちょっとだけ待ちます。
ごめんなさい、僕の家すぐ目の前が総合病院があって
毎日のようにしょっちゅうサイレンが鳴ってしまって本当に申し訳ないです。
もうそろそろ良いかな?
多分…はい。
気づいたらケンジさんですね。
おはようございます、ご参加いただきありがとうございます。
今日もこんな感じでダラダラと読んでいきます。
そろそろ多分良いかなというところなので
じゃあ続いてセクション2のお話ですね。
2つ目は依存関係になります。
依存関係を明示的に宣言し分離するというお話です。
ほとんどのプログラミング言語はサポートライブラリを配布するためのパッケージ管理システムを提供している。
例えば、PearlにおけるCPANやRubyにおけるRubyGemsなどであります。
パッケージ管理システムでインストールされているライブラリは
システム全体、サイトパッケージと言われたりしますね。
このシステム全体にインストールされる場合と
アプリケーションを含むディレクトリのスコープ
いわゆるベンダリングまたはビルディングと呼ばれたりするらしいですね。
ちょっと初めて聞きました。
というスコープにインストールされる場合があります。
12FAPはシステム全体にインストールされるパッケージが
暗黙的に存在することに決して依存はしていませんということが書かれています。
すべての依存関係を依存関係宣言マニフェストで
完全かつ厳密に宣言をします。
さらに実行時には依存関係分離ツールを使って取り囲んでいるシステムから
暗黙の依存関係が漏れていないことも保証します。
安全かつ明示的な依存関係の指定というのは
本番環境と開発環境の両方に対して同様に適用されます。
あんまりやったことないですけどこういう宣言をしっかりしてるんですね。
例えばRubyで使われるバンドラーというものは
依存関係宣言のマニフェストのフォーマットである
いわゆるGEMファイルと依存関係分離のためのバンドルエグゼックを提供していると。
あ、そういうことね。なるほどなるほど。
だから僕らはもう多分自然とそれに乗っかってますね、すでに。
で、Pythonではこれらのステップで2つの別々のツールが使われますと。
いわゆるPIPってものですね。
PIPが宣言のために使われ、バーチャルエンブが分離のために使われますと。
C言語でもオートコンフで依存関係を宣言し、
静的リンクで依存関係を分離することもできますと。
ツールが何であれ依存関係の宣言と分離っていうのは常に一緒に使わなければならないと。
どちらか片方だけではトゥエレブファクター満足するのに不十分であります。
明示的に依存関係を宣言する利点の一つは
アプリケーションに新しい開発者が加わった際のセットアップを単純化できることにあります。
新しい開発者は言語のランタイムと依存関係管理ツールさえインストールされていれば
アプリケーションのコードベースを自分の開発マシンにチェックアウトすることもできます。
開発者が決められたビルドコマンドでアプリケーションのコードを実行するために必要なすべてのものをセットアップできます。
例えばRuby BundlerのビルドコマンドはBundleインストールであり
Clojure、RainyGenですか、そんなやつがあるんですね。
すいません、僕Clojure書いたことがないんで。
RainyGenではRain Depthでありますよね。
アプリケーションがシステムツールを必要とするならばそのツールをアプリケーションに組み込むべきでありますと。
はいはい、なるほどでしたね。
まあでも今、昨今ですね、いろんな、どんなプラットフォームとかどんな言語での開発環境でも
今言ったようにPIPとかGEMとかNPMなどっていうのは普通に用意されているはずですし
僕らはそれに乗っかると思うので
逆に言うとそれぞれのプラットフォームの開発者ですね
大元の開発者たちはこの12ファクターにちゃんと従ったとか
そった環境を提供してくださっているってことですよね。
いやほんとありがたいなっていうのはつくづく思いますね。
僕らはこの辺を全然意識しないまま書かれたものとか決められたことに乗っかれているっていうところですよね。
では続いていきましょう。
12ファクターアップ第3話、設定の話ですね。
設定を環境変数に格納しましょうと。
あーなんかこれも当たり前の話かもしれないけど、はい上を抜きます。
アプリケーションの設定はいわゆるデプロイですね。
ステージング、本番、開発環境などの間で異なり得る唯一のものでありますと。
設定には以下のものが含まれます。
いわゆるデータベース、メムキャッシュ、他のバックエンドサービスなどのリソースへのバンドルとか、
もしくはAmazon S3やTwitterなどの外部サービスの認証情報などとか、
デプロイされたホストの正規化されたホスト名など、デプロイごとの値ですね。
アプリケーションは常に、時にはですね、設定を定数としてコード内にも格納します。
これは12ファクターに違反していますと。
12ファクターは設定をコードから厳密に分離することを要求しています。
設定はデプロイごとに大きく異なるが、コードはそうではないと。
そうするとドット円部とかってどうなんですかね。
そのドット円部から定数として読み出して使っているというんですけど、その辺はどうなんだろうな。
本当はそういうのも全部サービスごととかに環境変数としてちゃんと保存しておいてコード内には入れないってことなんですかね。
もちろん定数として読み込むことはあり得ると思いますけど。
もうちょっと読んでみます。
アプリケーションが全ての設定をコードの外部に正しく分離できているかどうかの簡単なテストは、
認証情報を漏えいさせることなくコードベースを今すぐにでもオープンソースにすることができるかどうかであります。
企業のソースコードであるかっていう社会的な話はあるけど、そういうのを度返ししてオープンにできる場合できますかっていう話です。
できないであればそういう環境変数とかが読み取られる可能性があり得るのでできないよねって話なので、
それができるかどうかっていうのが一つの基準だと。
でもこれはわかりやすいですね。
なおこの設定の定義にはアプリケーション内部の設定は含まないことに注意しましょう。
内部の設定とは、Railsにおけるconfig/.routies.rbなどなどとか、
Springにおいてコードモジュールがどう接続されるかなどの設定のことを指します。
この種の設定はデプロイの間で変わらないため、コードの内部で行うべきであります。
設定に対するもう一つのアプローチっていうのは、バージョン管理システムにチェックインされない設定ファイルを使う方法であります。
じゃあちゃんとあるんですね。
例としてRailsにおけるconfig/.database.yamlなどなど、さっきの激励.envも一つの選択肢ですよって話ですね。
この方法はリポジトリにチェックインされる定数を使うことに比べると非常に大きな進歩でありますが、
まだでも弱点もあります。
設定ファイルが誤ってリポジトリにチェックインされやすいことと、
設定ファイルが異なる場所に異なるフォーマットで散乱し、
全ての設定を一つの場所で見たり管理したりすることが難しくなりがちであることであります。
その上、これらのフォーマットは言語やフレームワークに固有のものになりがちになります。
ここは多少受け入れる面もありますし、
多少この12ファクターが定義された時よりは改善はされていると思うので、
現代だと普通にそういう設定ファイルに書き出すのはよくよくありますし、
どっちを取るか、アプリケーションとかビジネス次第だなという感じはしますね。
とはいえ、これ多分定義されたのは結構前のはずなので、
その時からちゃんとここまで厳密に書かれているっていうのは素晴らしいなってすくずく感じますね。
では戻ります。
12ファクターアップは設定を環境変数に格納します。
環境変数はコードを変更することなくデプロイごとに簡単に変更できます。
設定ファイルとは異なり、誤ってリポジトリにチェックインされる可能性はほぼほぼありません。
また独自形式の設定ファイルやJavaやシステムプロパティーズなどの他の設定の仕組みとは異なり、
環境変数は言語やOSに依存しない標準になります。
設定管理のもう一つの側面はグルーピングになります。
アプリケーションは設定を名前付きのグループ、しばしば環境と呼ばれたりしますけど、
そういうものにまとめることがあります。
グループはレールズにおけるディベロップメント、テスト、プロダクションみたいな環境のように
デプロイの名前を取って名付けられることが多いです。
この方法はうまくスケールしません。アプリケーションのデプロイが増えるにつれて、
新しい環境名、ステージング、QAなどが必要になってきたりもします。
さらにプロジェクトを拡大すると、開発者は上手ステージングのように自分用の環境を追加します。
いや、それは初めて見ましたけど、確かにね。
やったことがないけど、そう言われてみればそうですね。
開発者ごとのステージング環境というのを作る場合もあり得るんですね。
結果として設定が組み合わせ的に爆発し、このアプリケーションのデプロイの管理が非常に不安定になります。
これは確かに一つの課題を生み出してしまいますね。
利便性というかニーズを満たしてはいますけど、この辺難しいですね。
12ファクターアップの場合、環境変数はRUDEの細かい管理であり、
それぞれの環境変数は互いに直行しています。
環境変数は環境としてまとめられることはないが、代わりにデプロイごとに独立して管理をされます。
これはアプリケーションのライフサイクルに渡って、アプリケーションが多くのデプロイへと自然に拡大していくにつれて、
スムーズにスケールアップするモデルにもなります。
すごい、ここまでしっかり言語化されているとありがたいなと思いますね。
今までこれなんで読んでなかったんだって、自分の不勉強を恥じますね。
続いて4番ですね。4番バックエンドサービスのところです。
さっきは環境周りとか、実際に開発する前の定義のお話で3つ話されていた感じがしますので、
コードベースと設定と依存関係の3つだったけど、今度からバックエンドサービスです。
バックエンドサービスはアタッチされたリソースとして扱います。
バックエンドサービスはアプリケーションが通常の動作の中でネットワーク越しに利用する全てのサービスのことを言います。
例としては、データストア、MySQLとかカウチDBとかですね。
カウチDB懐かしいですね。メッセージキューイングシステムか。
RabbitMQとかBeanstalkですね。
もしくは電子メールを送信するためのSMTPサービスですね。
Postfixとかですね。
キャッシュシステムのMemcacheとかRedisなどがたくさんありますけど、そういうものですね。
従来データストアなどのバックエンドサービスというのは、デプロイされたアプリケーションと同じ管理者によって管理されていました。
このようなローカルで管理されるサービスに加えて、サードパーティーによって提供管理されるサービスを利用することもあります。
例としていわゆるSMTPサービスのポストマークですね。
さっきはPostfixだったんですけど、これは公開されているやつで、そうじゃないものとしてポストマークというものがあるらしいです。
僕はちょっと初めて知りました。
あとはメトリクス収集システムであるNew Relicとかロギーですね。
New Relicなんかまたブラッシュアップかしらないですけど、すごく名前を見るようになったり、すごく最近盛り上がっているというような感触を受けているんですけど、いかがですかね。
結構いろんな会社さんでNew Relicを使っているという事例も聞きますからね。
あとはストレージサービスですね。Amazon S3とか、あとFirebaseも使っている方もいるんじゃないですかね。Firestoreとかも使っている方もいらっしゃるかもと思いますけど。
あとはAPIアクセス可能な消費者向けサービスとしてTwitter、Google MapsとかラストFMとかなどがあるということですね。
12ファクターアップの行動はローカルサービスとサードパーティーサービスの実は区別していません。
アプリケーションにとってはどちらもアタッチされたリソースであり、設定に格納されたURLとかその他のロケーター、認証情報でアクセスをします。
12ファクターアップのデプロイというのは、アプリケーションの行動に変更を加えることなく、ローカルで管理されたMySQLデータベースをサードパーティーに管理されるサービス、いわゆるRDSとかですね。
に切り替えることができるべきであります。
同様にローカルのSMTPサーバーも行動を変更することなくサードパーティーのSMTPサービス、先ほど出しましたポストマークなどに切り替えることができるべきであります。
どちらの場合も変更が必要なのは設定の中のリソースハンドルのみであります。
まあそうだよね、設定のところの向き先と認証のiPathとかを変えればそことつなげることができるというのが本来の実装とか設計でありますよね。
それぞれのバックエンドサービスはリソースになります。
例えば一つのMySQLのデータベースはリソースですと。
2つのMySQLデータベース、アプリケーション層でシャーディングを使うとかですね。
こういうものは2つの異なるリソースともちろん見なせます。
AtoElevFactorAppっていうのはそれらのデータベースをアタッチされたリソースとして扱います。
これはアタッチされたリソースとアタッチする対象のデプロイが素結合であることも意味しています。
それはそうだよね。
リソースは自由にデプロイにアタッチしたりデプロイからデタッチしたりすることもできます。
例えばハードウェアの問題によってアプリケーションのデータベースの動作がおかしい場合、
アプリケーションの管理者は最新のバックアップから新しいデータベースサーバーを立ち上げたりします。
そして現在の本番データベースをデタッチし、新しいデータベースをアタッチします。
あくまでコードを一切変更せずにできるというのがポイントです。
再三言ってるよってことですね。
いろんな発表を聞いたり勉強会の登壇とか聞きますけど、みなさんちゃんとこれできてるように聞くかもしれません。
そういう方がちゃんと登壇できるっていう話なのかわからないけど。
結果的にそこに集約してるんだろうなって感じがしますね。
続いて5つ目です。5つ目はビルド、リリース、実行のステージになります。
ビルド、リリース、実行の3つのステージを厳密に分離をしましょうと言ってます。
コードベースっていうのは3つのステージを経て開発環境ではないデプロイへと変換されます。
ビルドステージはコードリポジトリをビルドと呼ばれる実行可能な塊へと変える変換になります。
デプロイプロセスで指定したコミットのコードで指定されたバージョンを使って、
ビルドステージは依存関係を取得してローカル環境に配置し、
バイナリーやアセットファイルをコンパイルします。
リリースステージはビルドステージで生成されたビルドを受け取り、
それをデプロイの現在の設定と結合させます。
出来上がるリリースにはビルドと設定の両方が含まれ、
実行環境の中ですぐにでも実行できるよう準備が整えます。
最後、実行ステージですね。いわゆるランタイムと呼ばれるものですけど、
選択されたリリースに対してアプリケーションのいくつかのプロセスを起動することで、
アプリケーションを実行環境の中で実行しますと。
一応これをちゃんと明確に分けましょうと。
デュエルファクターアップはビルド、リリース、実行の3つのステージを厳密に分離しています。
例えば実行ステージにある行動を変更しても、
その変更をビルドステージに伝える方法がないため、
行動を実行中に変更することはあり得ません。
それはそうだよね。
デプロイツールは通常リリース管理ツールを提供します。
中でも注目すべきは以前のリリースにロールバックする機能であります。
はい、これ大事だよね。
例えばデプロイツールのキャピストラームっていうのがあるらしいですね。
というものはリリースをリリーシーズという名前のサブディレクトリに格納し、
現在のリリースのディレクトリへのシンボリックリンクとなります。
このキャピストラームっていうのは、
ロールバックコマンドを使うと簡単かつ即座に以前のリリースにロールバックできます。
多分内部的に要は向き先を変えているだけですよね。
シンボリックリンクを書き換えているだけですよね。
まあわかりやすいですね。
確かにディレクトリパンと切っちゃうのはわかりやすいですが、
そのサーバーのリソースとか容量空気がするので、
それは果たしてどうなのっていうのはちょっとありつつですけど、
まだ昔そういうことをやってたんですね。
すべてのリリースは常に1位のリリースIDを持つべきであります。
リリースIDの例としてはリリースのタイムスタンプですね。
例として、例えば20110406-20321だとかですね。
単純にYMDとHMSか、みたいな感じですね。
などの連番だったりとか、単純にバージョン100などのカウントするナンバリングですね。
とかがあります。
リリースは追記専用の台帳であり、
一度作られたリリースは変更することはもちろんできません。
変更する場合は新しいリリースを作らなければなりません。
なので、メジャー、マイナー、パッチバージョンとかってあったりしますよね。
あとそれに加えて、RCとかあったりしますよね。バージョン管理です。
ビルドステージは新しいコードがデプロイされるときに必ずアプリケーションの開発者によって開始をされます。
一方、実行ステージっていうのはサーバーの再起動時やクラッシュしたプロセスが
プロセスマネージャーによって再起動されるときに自動で開始されます。
このため実行ステージはできるだけ可変部分を持たないようにするべきであります。
なぜならアプリケーションの実行を妨げるような問題が起きると
開発者が待機して真夜中にアプリケーションが壊れてしまう結果になるためです。
ビルドステージはもっと複雑でも構いません。
なぜならビルドステージのエラーは常にデプロイを実行している開発者の目の前で発生するためであります。
だから複雑であればいいっていうよりもどちらかというとより具体が強い方がいいってことですね。
あとそうですよね。実行ステージが可変部分を持たないようにするべきっていうのは
そのエラーが起きた後のリカバリですね。
また再起動するときのリカバリだったりリブートの速度を上げるためにも変更部分がない方が早いからっていうのもありますよね。
っていうのはちょっと思いました。
今のが5つ目のリリース、ビルドリリース実行というところでしたね。
ちょっと時間的に、あともうちょっとですね。ラスト1個だけ。6個ですね。
第6個目プロセスを読んで前半として今日は終了して
明日後半部分残り6個いけるかな。わかんないけど読んでいこうと思います。
ラスト6個目はプロセスですね。
アプリケーションを1つもしくは複数のステートレスなプロセスとして実行します。
アプリケーションは実行環境の中で1つもしくは複数のプロセスで実行されますよと。
最も単純な場合ではコードは単体のスクリプトであり、実行環境は言語ランタイムがインストールされた開発者のローカルノートPCであり、
プロセスはコマンドラインから実行される。例として例えば python スペース myscript.py とかですね。py ですけど。
みたいな感じの本当に単純なスクリプトファイルでそれを単純に python コマンドとかで実行するってことですね。
対極にあるのは複数の実行プロセスとしてインスタンス化される多くのプロセスタイプを洗練されたアプリケーションの本番にデプロイでありますと。
12ファクターのプロセスはステートレスかつシェアドナッシングでありますと。
永続化する必要のあるすべてのデータっていうのはステートフルなバックエンドサービス、典型的なデータベースに格納しなければなりません。
まあそうだよね。ステートフルであるんであれば。最終的にはデータベースが正しいデータを持っているというのはその良い話ですね。
プロセスのメモリー空間やファイルシステムっていうのは短い単一のトランザクション内でのキャッシュとして利用しても良い。
例えば大きなファイルをダウンロードしそのファイルを処理し結果をデータベースに格納するという一連の処理においてファイルシステムをキャッシュとして利用できます。
12ファクターアップはメモリーやディスクにキャッシュされたものが将来のリクエストやジョブにおいて利用できることを決して仮定はしません。
それぞれのプロセスタイプのプロセスが多く実行されている場合、将来のリクエストやジョブが別のプロセスで処理される可能性が高い。
一つのプロセスしか実行されていない場合であっても、プロセスが再起動するとすべての局所的な状態、いわゆるメモリーとかファイルシステムなどが消えてしまうことがあります。
プロセスの再起動の要因としては、コードのデプロイ、設定の変更、プロセスを別のプツリ位置に再配置する実行環境などがあります。
次にアセットパッケージャーですね。JAMITとかDjangoコンプレッサーなどのアセットパッケージャーというものは、コンパイルされたアセットをキャッシュするためにファイルシステムを利用します。
12ファクターアップというのはこのコンパイル処理を実行時に行うよりも、Railsアセットパイプラインのようにビルドステージで行う方が望ましいと考えています。
まあでもそうなんじゃないですか。コンパイル処理はビルドステージで行う方が望ましい。そりゃそうでしょ。
ウェブシステムの中にはSticky Sessionに頼るものもあります。Sticky Session、本当懐かしいですね。
昔本当使ってましたけど、今さすがにSticky Session使わないんじゃないですかね。
まあこれは単純に技術の進歩と時代の変化ですね。
昔は使ってましたと。これはユーザーのセッションデータをアプリケーションプロセスのメモリーにキャッシュし、同じ訪問者からの将来のリクエストが同じプロセスに送られることを期待するものになります。
で、Sticky Sessionはデュエルファクターに違反しており、やっぱそうなんや。決して使ったり頼ったりしてはなりません。
セッション状態のデータは有効期限を持つデータストア、メムキャッシュやレディスに格納すべきであるからであります。
はい、というところでプロセスのお話も終了です。
最後ちょっと気になりますけど、有効期限のデータストアって意外にデータベースに保存する場合もあったりしますよね。
いわゆるキャッシュテーブル的なところを作ってきたりとか、その中間テーブルでそこでいろいろ処理をしておくみたいなことをすることもありますよね。
メムキャッシュやレディスってのはやっぱり起発性があるので、最後に消える可能性があるからやっぱり消えてほしくないなというものに対して、
それ専用のテーブルを用意してるみたいなアプリケーションとかそういうシステムを見たことがあるので。
一概にメムキャッシュやレディスとは限らないんですけど、要はちゃんと有効期限っていうのをパラメーターも持ったデータストアとしてどっかに保存してあればいいっていうのがお話だと思いますね。
いわゆるスティッキーセッションみたいな、物理的にファイルとしてガンと用意しておくってのはよろしくないよって話だし、それに頼るのは違うよって話ですね。
基本的にはメムキャッシュやレディスに格納すべきでいいんじゃないかなと思いますね。
というところで、じゃあ今日の朝活は以上にしたいと思います。
結果的にちょっと30分になってしまいましたね。
というところで、今日は改めましてご参加いただいたのがエプテラノドさんとケンジさんですね。
ありがとうございました。
また明日も後半ですね。
第7章から入っていきたいと思いますので、興味ある方は聞いてみてください。
また、一応この記事もですね、みなさん多分読んだことあると思うんですけど、改めてTwitterでシェアしますので、みなさんの方でも読んでいただければいいなと思っております。
はい、あっという間にファクター、いい記事だって言われてたし、ずっと僕は先輩から読めと言われてたんですけど、改めて読むと僕らが当たり前にやってたことをすごい明確に言語されていて、
これラストアップデートが2017年なんですね。
もう6年前にこれをアップデートで書いたってことは最初のスタートですね。