モノリスを二つのサービスに分ける
目標
注文と在庫が1つのプロセスに入っているモノリスを、契約を先に固定してから2つの独立したサービスに分離し、分離の前後でレスポンスが同じかどうかを自動で検証します。
なぜ重要なのか
サービス分離で実際に難しいのは、コードを移すことではありません。移した後でも同じ答えが出ることを確認すること、そしてデータの所有権まで一緒に移したかを確認することです。現場で最もよくある失敗は、「サービスは分けたのにテーブルは共有」です。こうなると、デプロイは独立しましたが、スキーマの変更には今でも2つのチームの合意が必要です。結合はコードではなくデータにあったからです。そのため、このラボではコードを移す前に契約(contract)をファイルとして先に固定し、最後にソースを検査して、データアクセスが本当に切れたかを確認します。ストラングラーフィグ方式では、ファサードの裏にある2つの実装が同じ答えを返すという確信がなければ、トラフィックを移せません。
ステップ
/opt/fixtures/msa/monolith.pyを127.0.0.1:8101で起動し、GET /healthが200を返すようにしてください。- モノリスのルートを調べて、
/root/msa/seams.txtに1行に1つずつ경로 도메인の形式で書いてください(プレースホルダーはパスとドメインです)。ordersとinventoryの2つのドメインがどちらも登場し、最低4行なければなりません。 /root/msa/contract.jsonを作成してください。最上位のキーはordersとinventoryの2つで、それぞれport(整数)とpaths(文字列の配列)を持ちます。ordersは8103、inventoryは8102です。/root/msa/inventory_svc.pyを作成して、127.0.0.1:8102で起動してください。GET /stock/SKU-1が{"sku":"SKU-1","qty":<정수>}を返します(プレースホルダーは整数です)。/root/msa/orders_svc.pyを作成して、127.0.0.1:8103で起動してください。POST /ordersは{"sku":"SKU-1","qty":2}を受け取って在庫サービスに問い合わせ、十分なら201とorder_idを、足りなければ409を返します。orders_svc.pyのソースに、/opt/fixtures/msa/inventory.jsonのような在庫データのパスがなく、代わりに8102への呼び出しがなければなりません。/root/msa/parity.shを作成してください。同じリクエストをモノリス(8101)と新しい注文サービス(8103)に送り、ステータスコードと判定が同じならPARITY OKを出力します。実行結果を/root/msa/parity.outに残してください。/root/msa/decision.mdに、## 쪼갠 이유と## 쪼개지 말았어야 할 이유の2つの見出しを入れて(韓国語の見出しで、それぞれ「分割した理由」「分割すべきでなかった理由」を意味します)、それぞれ30文字以上書いてください。
参考
- バックグラウンドでの起動:
nohup python3 파일.py > /root/msa/파일.log 2>&1 &(プレースホルダーはファイル名です) - ポートの確認:
ss -ltnp | grep 810 - よくあるミス1: 新しいサービスが在庫のJSONファイルをそのまま開いて読むことです。それは分離ではありません。
- よくあるミス2: レスポンスのJSONのキー名を変えてしまうことです。契約を先に書いた理由がそれです。
モノリスを起動して基準線を取る
/opt/fixtures/msa/monolith.pyを127.0.0.1:8101で起動し、GET /healthが200を返すようにしてください。
/opt/fixtures/msa/monolith.pyをpython3で実行すると、8101番ポートで起動します。バックグラウンド実行(&)とログのリダイレクトを忘れないでください。
継ぎ目(seam)の一覧を作る
モノリスのルートを調べて、/root/msa/seams.txtに1行に1つずつ경로 도메인の形式で書いてください(プレースホルダーはパスとドメインです)。ordersとinventoryの2つのドメインがどちらも登場し、最低4行なければなりません。
分割する前に、境界の候補を先に書きます。モノリスのルート定義をgrepして、パスと担当するドメインを1行ずつ書いてください。
2つのサービスの契約を固定する
/root/msa/contract.jsonを作成してください。最上位のキーはordersとinventoryの2つで、それぞれport(整数)とpaths(文字列の配列)を持ちます。ordersは8103、inventoryは8102です。
コードより契約が先です。JSONで、サービス名、ポート、公開するパスを書きます。在庫サービスが何を約束するのかが要点です。
在庫サービスを分離する
/root/msa/inventory_svc.pyを作成して、127.0.0.1:8102で起動してください。GET /stock/SKU-1が{"sku":"SKU-1","qty":<정수>}を返します(プレースホルダーは整数です)。
在庫に関するロジックだけを新しいファイルに移して、8102で起動します。レスポンスは、skuとqtyを含むJSONでなければなりません。
注文サービスを分離する
/root/msa/orders_svc.pyを作成して、127.0.0.1:8103で起動してください。POST /ordersは{"sku":"SKU-1","qty":2}を受け取って在庫サービスに問い合わせ、十分なら201とorder_idを、足りなければ409を返します。
注文サービスは、在庫を直接読まずに、HTTPで問い合わせます。在庫が足りなければ409を返すのが契約です。
データの所有権が分離されたことを証明する
orders_svc.pyのソースに、/opt/fixtures/msa/inventory.jsonのような在庫データのパスがなく、代わりに8102への呼び出しがなければなりません。
注文サービスのソースに在庫データのファイルパスが残っていれば、まだ結合しています。ソースを検査してみてください。
モノリスとレスポンスの同等性を比較する
/root/msa/parity.shを作成してください。同じリクエストをモノリス(8101)と新しい注文サービス(8103)に送り、ステータスコードと判定が同じならPARITY OKを出力します。実行結果を/root/msa/parity.outに残してください。
同じ入力を2つの経路に入れて、結果を比較するスクリプトを書きます。2つのレスポンスが同じなら、PARITY OKを出力するようにしてください。
分離の判断の記録を残す
/root/msa/decision.mdに、## 쪼갠 이유と## 쪼개지 말았어야 할 이유の2つの見出しを入れて(韓国語の見出しで、それぞれ「分割した理由」「分割すべきでなかった理由」を意味します)、それぞれ30文字以上書いてください。
分割した根拠と、分割すべきでなかった根拠を、それぞれ書きます。指定された2つのマークダウンの見出しを正確に書かなければ、採点されません。