TECH PLAY

株式会社メドレー

株式会社メドレー の技術ブログ

1359

株式会社メドレーのエンジニアの笹塚です。 主にジョブメドレーのインフラを担当しています。 直近では、コンテナ化されていなかった環境の移行などをしていました。 休日は主にゲームをやっています。今は、日本語版がリリースされたばかりの「レムナント:フロム・ジ・アッシュ」に夢中です。 今回は Terraform のテスト環境を、 Terraform Workspaces を使用して構築した事例を紹介します。 背景 ジョブメドレーにはいくつかのサービスがあり、Terraform によるコード化が進んでいるサービスと、Ansible、 itamae などで部分的にコード化はされているものの、Terraform の使用が遅れているサービスが混在しており、これらのサービスについても Terraform への移行を進めています。 Terraform への移行とあわせて、メンテナンスを担当するメンバーを増やす必要があるのですが 【作業担当】 Terraform のコードから、実際に稼働させる環境を作るのは慣れていても難しい。 【レビュワー】 Terraform のコードの差分だけで、内容をすぐに把握するのは難しい。 などの理由から、作業担当、レビュワーともにハードルが低いとは言えず、Terraform によるインフラの変更内容を事前に確認できる環境構築が必要だと感じるようになりました。 検討内容 事前に確認できる環境を作るにあたり、まず最初に検討したのは、各ステージのコードを共通化することでした。 ジョブメドレーの関連サービスでは、大きくわけて 3 つのステージで構成しています。 Sandbox(個人の検証用) → QA(リリース前の検証用) → Production この各ステージのコードを共通化できれば、Production には QA 環境までで確認済みのコードを apply することができます。 ですが、Sandbox 環境、QA 環境、Production 環境はそれぞれ似てはいるものの、全てが同じ構成ではありません。 Terraform の HCL では if 構文がない( resource の作成を count で制御することはできる) module 単位でのリソース作成の制御ができない(Terraform 0.13 から module でも count や for_each が可能になる ようです) などの制限があり、構造の差分をコードで吸収しにくく、共通化できたとしてもメンテナンス性を下げる可能性が高いです。 また、すでに Terraform でコード化されている状態からの移行作業も楽ではないでしょう。 そこで、ステージごとのコードを共通化するのではなく、 AWS Organizations で別アカウントを作り、各ステージのコードを試せる環境を作ることにしました。 <目標とする> Terraform のコードをプロダクションアカウントで実行する前に、テストアカウントで実行し、設定した内容を AWS マネジメントコンソール や AWS CLI で確認することできる。 テストアカウント上で設定を確認した後、プロダクションアカウントに同じコードを apply することができる。 コストを抑えるため、テストアカウント上のリソースは、確認が終了したら destory することができる。 <目標としない> テストアカウント上でサービスが稼働することは目標としない。 必要なデータセットの作成など用意するものが増えるので、目標には含めませんでした。 設定作業 必要な作業は大きくわけて 2 つです。 Terraform Workspaces の設定 アカウントごとに必要なコードの追加、修正 Terraform Workspaces の設定 Terraform と AWS provider の設定を変更することで、workspace を切り替えることができます。 以下が作業イメージです。 workspace の追加 $ terraform workspace new production $ terraform workspace list default * production Terraform の環境変更 terraform { required_version = "= 0.12.28" backend "s3" { bucket = "example-state" workspace_key_prefix = "workspace" dynamodb_table = "terraform-state-lock" key = "example.tfstate" region = "ap-northeast-1" profile = "production" } } provider "aws" { region = "ap-northeast-1" version = "= 2.70.0" profile = var. workspace_profile [ terraform . workspace ] } variable "workspace_profile" { type = map ( string ) default = { default = "test" production = "production" } } この例では、default workspace はテスト環境、Production を実際にサービスが稼働する環境のアカウントになるように設定しています。 それぞれ default は、aws config の test profile、Production は production profile を参照しています。 s3://example-state/example.tfstate がテスト環境、 s3://example-state/workspace/production/example.tfstate が、プロダクション環境の state ファイルになります。 Terraform のコード内からは、現在の workspace 名を terraform.workspace で参照することができます。 ここまでの設定で $ terraform workspace select [workspace 名] で workspace を切り替えることができるようになりました。 あとは、アカウントごとに必要な変更をしていきます。 アカウントをまたいだ共通のリソースの定義 全アカウントでユニークにする必要があるリソース(S3 bucket、DNS など)の場合は、名称の分岐処理が必要です。 テストアカウントでは、リソース名に prefix をつけて作成するようにしました。 # 定義 variable "example_bucket_name" { type = map ( string ) default = { default = "test-example-bucket" production = "example-bucket" } } # リソースでの参照時 resource "aws_s3_bucket" "example" { bucket = var. example_bucket_name [ terraform . workspace ] .. } テストアカウントで起動するインスタンスタイプや台数の変更 テストアカウントでは EC2 のインスタンスを起動させなくても良い場合には、台数を変更するようにしました。 resource "aws_autoscaling_group" "example_web" { name = "example-web" max_size = 12 min_size = 6 desired_capacity = terraform. workspace == "production" ? 6 : 0 … } インスタンスの起動が必要な場合も、同様の分岐でインスタンスタイプの変更を行っています。 コード化をしないリソースの扱い プロダクションアカウントで一旦コード化を保留したリソースについては data source で参照しますが、テストアカウントにはリソースが存在しないため作成しなければいけません。 テストアカウントのリソースは確認が終了した段階で destroy したいので ステージ用の Terraform コードとは別に、必要なリソースを作成するコードを用意する 必要なリソース用のコード → ステージ用のコードの順に apply する ようにしました。 data source で参照できれば良い範囲でのコード化なので、この追加のリソースも最小限のコストになるようにしています。 以上の設定で、同じ Terraform のコードを workspace を切り替えて plan、apply ができるようになりました。 運用してみて プロダクションアカウントに apply する前に、テストアカウントで事前に apply することができるようになったので、作業中の試行錯誤もしやすくなりました。 レビュワーも、テストアカウント上で実際に apply された結果を確認することができるようになり、apply の差分だけではわかりにくかった変更内容を確認できるようになりました。 これなら新しく担当するメンバーの不安を、少しかもしれませんが解消できそうです。 まとめ 今回は Terraform のテスト環境を、Terraform Workspaces を使用して構築した事例を紹介させていただきました。 テストアカウント上のリソースの自動 destroy や、 plan、apply の自動化については触れられていませんが、また別の機会に紹介できればと思います。 長らく運用しているサービスでは、サービスを稼働させたまま解決しなければいけない課題が数多くあります。 それらの課題を、一つずつ着実に解決していくことに楽しさを見いだせる方、ぜひメドレーで一緒に働きましょう! 募集の一覧 | 株式会社メドレー メドレーの採用情報はこちらからご確認ください。 www.medley.jp
アバター
株式会社メドレーのエンジニアの笹塚です。 主にジョブメドレーのインフラを担当しています。 直近では、コンテナ化されていなかった環境の移行などをしていました。 休日は主にゲームをやっています。今は、日本語版がリリースされたばかりの「レムナント:フロム・ジ・アッシュ」に夢中です。 今回は Terraform のテスト環境を、 Terraform Workspaces を使用して構築した事例を紹介します。 背景 ジョブメドレーにはいくつかのサービスがあり、Terraform によるコード化が進んでいるサービスと、Ansible、 itamae などで部分的にコード化はされているものの、Terraform の使用が遅れているサービスが混在しており、これらのサービスについても Terraform への移行を進めています。 Terraform への移行とあわせて、メンテナンスを担当するメンバーを増やす必要があるのですが 【作業担当】 Terraform のコードから、実際に稼働させる環境を作るのは慣れていても難しい。 【レビュワー】 Terraform のコードの差分だけで、内容をすぐに把握するのは難しい。 などの理由から、作業担当、レビュワーともにハードルが低いとは言えず、Terraform によるインフラの変更内容を事前に確認できる環境構築が必要だと感じるようになりました。 検討内容 事前に確認できる環境を作るにあたり、まず最初に検討したのは、各ステージのコードを共通化することでした。 ジョブメドレーの関連サービスでは、大きくわけて 3 つのステージで構成しています。 Sandbox(個人の検証用) → QA(リリース前の検証用) → Production この各ステージのコードを共通化できれば、Production には QA 環境までで確認済みのコードを apply することができます。 ですが、Sandbox 環境、QA 環境、Production 環境はそれぞれ似てはいるものの、全てが同じ構成ではありません。 Terraform の HCL では if 構文がない( resource の作成を count で制御することはできる) module 単位でのリソース作成の制御ができない(Terraform 0.13 から module でも count や for_each が可能になる ようです) などの制限があり、構造の差分をコードで吸収しにくく、共通化できたとしてもメンテナンス性を下げる可能性が高いです。 また、すでに Terraform でコード化されている状態からの移行作業も楽ではないでしょう。 そこで、ステージごとのコードを共通化するのではなく、 AWS Organizations で別アカウントを作り、各ステージのコードを試せる環境を作ることにしました。 <目標とする> Terraform のコードをプロダクションアカウントで実行する前に、テストアカウントで実行し、設定した内容を AWS マネジメントコンソール や AWS CLI で確認することできる。 テストアカウント上で設定を確認した後、プロダクションアカウントに同じコードを apply することができる。 コストを抑えるため、テストアカウント上のリソースは、確認が終了したら destory することができる。 <目標としない> テストアカウント上でサービスが稼働することは目標としない。 必要なデータセットの作成など用意するものが増えるので、目標には含めませんでした。 設定作業 必要な作業は大きくわけて 2 つです。 Terraform Workspaces の設定 アカウントごとに必要なコードの追加、修正 Terraform Workspaces の設定 Terraform と AWS provider の設定を変更することで、workspace を切り替えることができます。 以下が作業イメージです。 workspace の追加 $ terraform workspace new production $ terraform workspace list default * production Terraform の環境変更 terraform { required_version = "= 0.12.28" backend "s3" { bucket = "example-state" workspace_key_prefix = "workspace" dynamodb_table = "terraform-state-lock" key = "example.tfstate" region = "ap-northeast-1" profile = "production" } } provider "aws" { region = "ap-northeast-1" version = "= 2.70.0" profile = var. workspace_profile [ terraform . workspace ] } variable "workspace_profile" { type = map ( string ) default = { default = "test" production = "production" } } この例では、default workspace はテスト環境、Production を実際にサービスが稼働する環境のアカウントになるように設定しています。 それぞれ default は、aws config の test profile、Production は production profile を参照しています。 s3://example-state/example.tfstate がテスト環境、 s3://example-state/workspace/production/example.tfstate が、プロダクション環境の state ファイルになります。 Terraform のコード内からは、現在の workspace 名を terraform.workspace で参照することができます。 ここまでの設定で $ terraform workspace select [workspace 名] で workspace を切り替えることができるようになりました。 あとは、アカウントごとに必要な変更をしていきます。 アカウントをまたいだ共通のリソースの定義 全アカウントでユニークにする必要があるリソース(S3 bucket、DNS など)の場合は、名称の分岐処理が必要です。 テストアカウントでは、リソース名に prefix をつけて作成するようにしました。 # 定義 variable "example_bucket_name" { type = map ( string ) default = { default = "test-example-bucket" production = "example-bucket" } } # リソースでの参照時 resource "aws_s3_bucket" "example" { bucket = var. example_bucket_name [ terraform . workspace ] .. } テストアカウントで起動するインスタンスタイプや台数の変更 テストアカウントでは EC2 のインスタンスを起動させなくても良い場合には、台数を変更するようにしました。 resource "aws_autoscaling_group" "example_web" { name = "example-web" max_size = 12 min_size = 6 desired_capacity = terraform. workspace == "production" ? 6 : 0 … } インスタンスの起動が必要な場合も、同様の分岐でインスタンスタイプの変更を行っています。 コード化をしないリソースの扱い プロダクションアカウントで一旦コード化を保留したリソースについては data source で参照しますが、テストアカウントにはリソースが存在しないため作成しなければいけません。 テストアカウントのリソースは確認が終了した段階で destroy したいので ステージ用の Terraform コードとは別に、必要なリソースを作成するコードを用意する 必要なリソース用のコード → ステージ用のコードの順に apply する ようにしました。 data source で参照できれば良い範囲でのコード化なので、この追加のリソースも最小限のコストになるようにしています。 以上の設定で、同じ Terraform のコードを workspace を切り替えて plan、apply ができるようになりました。 運用してみて プロダクションアカウントに apply する前に、テストアカウントで事前に apply することができるようになったので、作業中の試行錯誤もしやすくなりました。 レビュワーも、テストアカウント上で実際に apply された結果を確認することができるようになり、apply の差分だけではわかりにくかった変更内容を確認できるようになりました。 これなら新しく担当するメンバーの不安を、少しかもしれませんが解消できそうです。 まとめ 今回は Terraform のテスト環境を、Terraform Workspaces を使用して構築した事例を紹介させていただきました。 テストアカウント上のリソースの自動 destroy や、 plan、apply の自動化については触れられていませんが、また別の機会に紹介できればと思います。 長らく運用しているサービスでは、サービスを稼働させたまま解決しなければいけない課題が数多くあります。 それらの課題を、一つずつ着実に解決していくことに楽しさを見いだせる方、ぜひメドレーで一緒に働きましょう! 募集の一覧 | 株式会社メドレー メドレーの採用情報はこちらからご確認ください。 www.medley.jp
アバター
株式会社メドレーのエンジニアの笹塚です。 主にジョブメドレーのインフラを担当しています。 直近では、コンテナ化されていなかった環境の移行などをしていました。 休日は主にゲームをやっています。今は、日本語版がリリースされたばかりの「レムナント:フロム・ジ・アッシュ」に夢中です。 今回は Terraform のテスト環境を、 Terraform Workspaces を使用して構築した事例を紹介します。 背景 ジョブメドレーにはいくつかのサービスがあり、Terraform によるコード化が進んでいるサービスと、Ansible、 itamae などで部分的にコード化はされているものの、Terraform の使用が遅れているサービスが混在しており、これらのサービスについても Terraform への移行を進めています。 Terraform への移行とあわせて、メンテナンスを担当するメンバーを増やす必要があるのですが 【作業担当】 Terraform のコードから、実際に稼働させる環境を作るのは慣れていても難しい。 【レビュワー】 Terraform のコードの差分だけで、内容をすぐに把握するのは難しい。 などの理由から、作業担当、レビュワーともにハードルが低いとは言えず、Terraform によるインフラの変更内容を事前に確認できる環境構築が必要だと感じるようになりました。 検討内容 事前に確認できる環境を作るにあたり、まず最初に検討したのは、各ステージのコードを共通化することでした。 ジョブメドレーの関連サービスでは、大きくわけて 3 つのステージで構成しています。 Sandbox(個人の検証用) → QA(リリース前の検証用) → Production この各ステージのコードを共通化できれば、Production には QA 環境までで確認済みのコードを apply することができます。 ですが、Sandbox 環境、QA 環境、Production 環境はそれぞれ似てはいるものの、全てが同じ構成ではありません。 Terraform の HCL では if 構文がない( resource の作成を count で制御することはできる) module 単位でのリソース作成の制御ができない(Terraform 0.13 から module でも count や for_each が可能になる ようです) などの制限があり、構造の差分をコードで吸収しにくく、共通化できたとしてもメンテナンス性を下げる可能性が高いです。 また、すでに Terraform でコード化されている状態からの移行作業も楽ではないでしょう。 そこで、ステージごとのコードを共通化するのではなく、 AWS Organizations で別アカウントを作り、各ステージのコードを試せる環境を作ることにしました。 <目標とする> Terraform のコードをプロダクションアカウントで実行する前に、テストアカウントで実行し、設定した内容を AWS マネジメントコンソール や AWS CLI で確認することできる。 テストアカウント上で設定を確認した後、プロダクションアカウントに同じコードを apply することができる。 コストを抑えるため、テストアカウント上のリソースは、確認が終了したら destory することができる。 <目標としない> テストアカウント上でサービスが稼働することは目標としない。 必要なデータセットの作成など用意するものが増えるので、目標には含めませんでした。 設定作業 必要な作業は大きくわけて 2 つです。 Terraform Workspaces の設定 アカウントごとに必要なコードの追加、修正 Terraform Workspaces の設定 Terraform と AWS provider の設定を変更することで、workspace を切り替えることができます。 以下が作業イメージです。 workspace の追加 $ terraform workspace new production $ terraform workspace list default * production Terraform の環境変更 terraform { required_version = "= 0.12.28" backend "s3" { bucket = "example-state" workspace_key_prefix = "workspace" dynamodb_table = "terraform-state-lock" key = "example.tfstate" region = "ap-northeast-1" profile = "production" } } provider "aws" { region = "ap-northeast-1" version = "= 2.70.0" profile = var. workspace_profile [ terraform . workspace ] } variable "workspace_profile" { type = map ( string ) default = { default = "test" production = "production" } } この例では、default workspace はテスト環境、Production を実際にサービスが稼働する環境のアカウントになるように設定しています。 それぞれ default は、aws config の test profile、Production は production profile を参照しています。 s3://example-state/example.tfstate がテスト環境、 s3://example-state/workspace/production/example.tfstate が、プロダクション環境の state ファイルになります。 Terraform のコード内からは、現在の workspace 名を terraform.workspace で参照することができます。 ここまでの設定で $ terraform workspace select [workspace 名] で workspace を切り替えることができるようになりました。 あとは、アカウントごとに必要な変更をしていきます。 アカウントをまたいだ共通のリソースの定義 全アカウントでユニークにする必要があるリソース(S3 bucket、DNS など)の場合は、名称の分岐処理が必要です。 テストアカウントでは、リソース名に prefix をつけて作成するようにしました。 # 定義 variable "example_bucket_name" { type = map ( string ) default = { default = "test-example-bucket" production = "example-bucket" } } # リソースでの参照時 resource "aws_s3_bucket" "example" { bucket = var. example_bucket_name [ terraform . workspace ] .. } テストアカウントで起動するインスタンスタイプや台数の変更 テストアカウントでは EC2 のインスタンスを起動させなくても良い場合には、台数を変更するようにしました。 resource "aws_autoscaling_group" "example_web" { name = "example-web" max_size = 12 min_size = 6 desired_capacity = terraform. workspace == "production" ? 6 : 0 … } インスタンスの起動が必要な場合も、同様の分岐でインスタンスタイプの変更を行っています。 コード化をしないリソースの扱い プロダクションアカウントで一旦コード化を保留したリソースについては data source で参照しますが、テストアカウントにはリソースが存在しないため作成しなければいけません。 テストアカウントのリソースは確認が終了した段階で destroy したいので ステージ用の Terraform コードとは別に、必要なリソースを作成するコードを用意する 必要なリソース用のコード → ステージ用のコードの順に apply する ようにしました。 data source で参照できれば良い範囲でのコード化なので、この追加のリソースも最小限のコストになるようにしています。 以上の設定で、同じ Terraform のコードを workspace を切り替えて plan、apply ができるようになりました。 運用してみて プロダクションアカウントに apply する前に、テストアカウントで事前に apply することができるようになったので、作業中の試行錯誤もしやすくなりました。 レビュワーも、テストアカウント上で実際に apply された結果を確認することができるようになり、apply の差分だけではわかりにくかった変更内容を確認できるようになりました。 これなら新しく担当するメンバーの不安を、少しかもしれませんが解消できそうです。 まとめ 今回は Terraform のテスト環境を、Terraform Workspaces を使用して構築した事例を紹介させていただきました。 テストアカウント上のリソースの自動 destroy や、 plan、apply の自動化については触れられていませんが、また別の機会に紹介できればと思います。 長らく運用しているサービスでは、サービスを稼働させたまま解決しなければいけない課題が数多くあります。 それらの課題を、一つずつ着実に解決していくことに楽しさを見いだせる方、ぜひメドレーで一緒に働きましょう! 募集の一覧 | 株式会社メドレー メドレーの採用情報はこちらからご確認ください。 www.medley.jp
アバター
株式会社メドレーのエンジニアの笹塚です。 主にジョブメドレーのインフラを担当しています。 直近では、コンテナ化されていなかった環境の移行などをしていました。 休日は主にゲームをやっています。今は、日本語版がリリースされたばかりの「レムナント:フロム・ジ・アッシュ」に夢中です。 今回は Terraform のテスト環境を、 Terraform Workspaces を使用して構築した事例を紹介します。 背景 ジョブメドレーにはいくつかのサービスがあり、Terraform によるコード化が進んでいるサービスと、Ansible、 itamae などで部分的にコード化はされているものの、Terraform の使用が遅れているサービスが混在しており、これらのサービスについても Terraform への移行を進めています。 Terraform への移行とあわせて、メンテナンスを担当するメンバーを増やす必要があるのですが 【作業担当】 Terraform のコードから、実際に稼働させる環境を作るのは慣れていても難しい。 【レビュワー】 Terraform のコードの差分だけで、内容をすぐに把握するのは難しい。 などの理由から、作業担当、レビュワーともにハードルが低いとは言えず、Terraform によるインフラの変更内容を事前に確認できる環境構築が必要だと感じるようになりました。 検討内容 事前に確認できる環境を作るにあたり、まず最初に検討したのは、各ステージのコードを共通化することでした。 ジョブメドレーの関連サービスでは、大きくわけて 3 つのステージで構成しています。 Sandbox(個人の検証用) → QA(リリース前の検証用) → Production この各ステージのコードを共通化できれば、Production には QA 環境までで確認済みのコードを apply することができます。 ですが、Sandbox 環境、QA 環境、Production 環境はそれぞれ似てはいるものの、全てが同じ構成ではありません。 Terraform の HCL では if 構文がない( resource の作成を count で制御することはできる) module 単位でのリソース作成の制御ができない(Terraform 0.13 から module でも count や for_each が可能になる ようです) などの制限があり、構造の差分をコードで吸収しにくく、共通化できたとしてもメンテナンス性を下げる可能性が高いです。 また、すでに Terraform でコード化されている状態からの移行作業も楽ではないでしょう。 そこで、ステージごとのコードを共通化するのではなく、 AWS Organizations で別アカウントを作り、各ステージのコードを試せる環境を作ることにしました。 <目標とする> Terraform のコードをプロダクションアカウントで実行する前に、テストアカウントで実行し、設定した内容を AWS マネジメントコンソール や AWS CLI で確認することできる。 テストアカウント上で設定を確認した後、プロダクションアカウントに同じコードを apply することができる。 コストを抑えるため、テストアカウント上のリソースは、確認が終了したら destory することができる。 <目標としない> テストアカウント上でサービスが稼働することは目標としない。 必要なデータセットの作成など用意するものが増えるので、目標には含めませんでした。 設定作業 必要な作業は大きくわけて 2 つです。 Terraform Workspaces の設定 アカウントごとに必要なコードの追加、修正 Terraform Workspaces の設定 Terraform と AWS provider の設定を変更することで、workspace を切り替えることができます。 以下が作業イメージです。 workspace の追加 $ terraform workspace new production $ terraform workspace list default * production Terraform の環境変更 terraform { required_version = "= 0.12.28" backend "s3" { bucket = "example-state" workspace_key_prefix = "workspace" dynamodb_table = "terraform-state-lock" key = "example.tfstate" region = "ap-northeast-1" profile = "production" } } provider "aws" { region = "ap-northeast-1" version = "= 2.70.0" profile = var. workspace_profile [ terraform . workspace ] } variable "workspace_profile" { type = map ( string ) default = { default = "test" production = "production" } } この例では、default workspace はテスト環境、Production を実際にサービスが稼働する環境のアカウントになるように設定しています。 それぞれ default は、aws config の test profile、Production は production profile を参照しています。 s3://example-state/example.tfstate がテスト環境、 s3://example-state/workspace/production/example.tfstate が、プロダクション環境の state ファイルになります。 Terraform のコード内からは、現在の workspace 名を terraform.workspace で参照することができます。 ここまでの設定で $ terraform workspace select [workspace 名] で workspace を切り替えることができるようになりました。 あとは、アカウントごとに必要な変更をしていきます。 アカウントをまたいだ共通のリソースの定義 全アカウントでユニークにする必要があるリソース(S3 bucket、DNS など)の場合は、名称の分岐処理が必要です。 テストアカウントでは、リソース名に prefix をつけて作成するようにしました。 # 定義 variable "example_bucket_name" { type = map ( string ) default = { default = "test-example-bucket" production = "example-bucket" } } # リソースでの参照時 resource "aws_s3_bucket" "example" { bucket = var. example_bucket_name [ terraform . workspace ] .. } テストアカウントで起動するインスタンスタイプや台数の変更 テストアカウントでは EC2 のインスタンスを起動させなくても良い場合には、台数を変更するようにしました。 resource "aws_autoscaling_group" "example_web" { name = "example-web" max_size = 12 min_size = 6 desired_capacity = terraform. workspace == "production" ? 6 : 0 … } インスタンスの起動が必要な場合も、同様の分岐でインスタンスタイプの変更を行っています。 コード化をしないリソースの扱い プロダクションアカウントで一旦コード化を保留したリソースについては data source で参照しますが、テストアカウントにはリソースが存在しないため作成しなければいけません。 テストアカウントのリソースは確認が終了した段階で destroy したいので ステージ用の Terraform コードとは別に、必要なリソースを作成するコードを用意する 必要なリソース用のコード → ステージ用のコードの順に apply する ようにしました。 data source で参照できれば良い範囲でのコード化なので、この追加のリソースも最小限のコストになるようにしています。 以上の設定で、同じ Terraform のコードを workspace を切り替えて plan、apply ができるようになりました。 運用してみて プロダクションアカウントに apply する前に、テストアカウントで事前に apply することができるようになったので、作業中の試行錯誤もしやすくなりました。 レビュワーも、テストアカウント上で実際に apply された結果を確認することができるようになり、apply の差分だけではわかりにくかった変更内容を確認できるようになりました。 これなら新しく担当するメンバーの不安を、少しかもしれませんが解消できそうです。 まとめ 今回は Terraform のテスト環境を、Terraform Workspaces を使用して構築した事例を紹介させていただきました。 テストアカウント上のリソースの自動 destroy や、 plan、apply の自動化については触れられていませんが、また別の機会に紹介できればと思います。 長らく運用しているサービスでは、サービスを稼働させたまま解決しなければいけない課題が数多くあります。 それらの課題を、一つずつ着実に解決していくことに楽しさを見いだせる方、ぜひメドレーで一緒に働きましょう! 募集の一覧 | 株式会社メドレー メドレーの採用情報はこちらからご確認ください。 www.medley.jp
アバター
株式会社メドレーのエンジニアの笹塚です。 主にジョブメドレーのインフラを担当しています。 直近では、コンテナ化されていなかった環境の移行などをしていました。 休日は主にゲームをやっています。今は、日本語版がリリースされたばかりの「レムナント:フロム・ジ・アッシュ」に夢中です。 今回は Terraform のテスト環境を、 Terraform Workspaces を使用して構築した事例を紹介します。 背景 ジョブメドレーにはいくつかのサービスがあり、Terraform によるコード化が進んでいるサービスと、Ansible、 itamae などで部分的にコード化はされているものの、Terraform の使用が遅れているサービスが混在しており、これらのサービスについても Terraform への移行を進めています。 Terraform への移行とあわせて、メンテナンスを担当するメンバーを増やす必要があるのですが 【作業担当】 Terraform のコードから、実際に稼働させる環境を作るのは慣れていても難しい。 【レビュワー】 Terraform のコードの差分だけで、内容をすぐに把握するのは難しい。 などの理由から、作業担当、レビュワーともにハードルが低いとは言えず、Terraform によるインフラの変更内容を事前に確認できる環境構築が必要だと感じるようになりました。 検討内容 事前に確認できる環境を作るにあたり、まず最初に検討したのは、各ステージのコードを共通化することでした。 ジョブメドレーの関連サービスでは、大きくわけて 3 つのステージで構成しています。 Sandbox(個人の検証用) → QA(リリース前の検証用) → Production この各ステージのコードを共通化できれば、Production には QA 環境までで確認済みのコードを apply することができます。 ですが、Sandbox 環境、QA 環境、Production 環境はそれぞれ似てはいるものの、全てが同じ構成ではありません。 Terraform の HCL では if 構文がない( resource の作成を count で制御することはできる) module 単位でのリソース作成の制御ができない(Terraform 0.13 から module でも count や for_each が可能になる ようです) などの制限があり、構造の差分をコードで吸収しにくく、共通化できたとしてもメンテナンス性を下げる可能性が高いです。 また、すでに Terraform でコード化されている状態からの移行作業も楽ではないでしょう。 そこで、ステージごとのコードを共通化するのではなく、 AWS Organizations で別アカウントを作り、各ステージのコードを試せる環境を作ることにしました。 <目標とする> Terraform のコードをプロダクションアカウントで実行する前に、テストアカウントで実行し、設定した内容を AWS マネジメントコンソール や AWS CLI で確認することできる。 テストアカウント上で設定を確認した後、プロダクションアカウントに同じコードを apply することができる。 コストを抑えるため、テストアカウント上のリソースは、確認が終了したら destory することができる。 <目標としない> テストアカウント上でサービスが稼働することは目標としない。 必要なデータセットの作成など用意するものが増えるので、目標には含めませんでした。 設定作業 必要な作業は大きくわけて 2 つです。 Terraform Workspaces の設定 アカウントごとに必要なコードの追加、修正 Terraform Workspaces の設定 Terraform と AWS provider の設定を変更することで、workspace を切り替えることができます。 以下が作業イメージです。 workspace の追加 $ terraform workspace new production $ terraform workspace list default * production Terraform の環境変更 terraform { required_version = "= 0.12.28" backend "s3" { bucket = "example-state" workspace_key_prefix = "workspace" dynamodb_table = "terraform-state-lock" key = "example.tfstate" region = "ap-northeast-1" profile = "production" } } provider "aws" { region = "ap-northeast-1" version = "= 2.70.0" profile = var. workspace_profile [ terraform . workspace ] } variable "workspace_profile" { type = map ( string ) default = { default = "test" production = "production" } } この例では、default workspace はテスト環境、Production を実際にサービスが稼働する環境のアカウントになるように設定しています。 それぞれ default は、aws config の test profile、Production は production profile を参照しています。 s3://example-state/example.tfstate がテスト環境、 s3://example-state/workspace/production/example.tfstate が、プロダクション環境の state ファイルになります。 Terraform のコード内からは、現在の workspace 名を terraform.workspace で参照することができます。 ここまでの設定で $ terraform workspace select [workspace 名] で workspace を切り替えることができるようになりました。 あとは、アカウントごとに必要な変更をしていきます。 アカウントをまたいだ共通のリソースの定義 全アカウントでユニークにする必要があるリソース(S3 bucket、DNS など)の場合は、名称の分岐処理が必要です。 テストアカウントでは、リソース名に prefix をつけて作成するようにしました。 # 定義 variable "example_bucket_name" { type = map ( string ) default = { default = "test-example-bucket" production = "example-bucket" } } # リソースでの参照時 resource "aws_s3_bucket" "example" { bucket = var. example_bucket_name [ terraform . workspace ] .. } テストアカウントで起動するインスタンスタイプや台数の変更 テストアカウントでは EC2 のインスタンスを起動させなくても良い場合には、台数を変更するようにしました。 resource "aws_autoscaling_group" "example_web" { name = "example-web" max_size = 12 min_size = 6 desired_capacity = terraform. workspace == "production" ? 6 : 0 … } インスタンスの起動が必要な場合も、同様の分岐でインスタンスタイプの変更を行っています。 コード化をしないリソースの扱い プロダクションアカウントで一旦コード化を保留したリソースについては data source で参照しますが、テストアカウントにはリソースが存在しないため作成しなければいけません。 テストアカウントのリソースは確認が終了した段階で destroy したいので ステージ用の Terraform コードとは別に、必要なリソースを作成するコードを用意する 必要なリソース用のコード → ステージ用のコードの順に apply する ようにしました。 data source で参照できれば良い範囲でのコード化なので、この追加のリソースも最小限のコストになるようにしています。 以上の設定で、同じ Terraform のコードを workspace を切り替えて plan、apply ができるようになりました。 運用してみて プロダクションアカウントに apply する前に、テストアカウントで事前に apply することができるようになったので、作業中の試行錯誤もしやすくなりました。 レビュワーも、テストアカウント上で実際に apply された結果を確認することができるようになり、apply の差分だけではわかりにくかった変更内容を確認できるようになりました。 これなら新しく担当するメンバーの不安を、少しかもしれませんが解消できそうです。 まとめ 今回は Terraform のテスト環境を、Terraform Workspaces を使用して構築した事例を紹介させていただきました。 テストアカウント上のリソースの自動 destroy や、 plan、apply の自動化については触れられていませんが、また別の機会に紹介できればと思います。 長らく運用しているサービスでは、サービスを稼働させたまま解決しなければいけない課題が数多くあります。 それらの課題を、一つずつ着実に解決していくことに楽しさを見いだせる方、ぜひメドレーで一緒に働きましょう! https://www.medley.jp/jobs/
アバター
こんにちは。メドレーにてジョブメドレー開発エンジニアをしています、矢野と申します。 ジョブメドレーでは、主にバックエンド ( Ruby on Rails ) の改修を担当してます 直近では 「サイトパフォーマンス改善施策」 として、Rails コードのリファクタリングによる TTFB 高速化に取り組んでました 「もう絶対にコケないのが分かってる」ビルドやテストを、手元のコンソールで何度も叩いて「わー。ちゃんと通る!」っていう時間が好きです 今回は、上記の「サイトパフォーマンス改善施策」の文脈で調査した、PWA の実装パターンである PRPL Pattern という リソース提供の設計アーキテクチャ について紹介します。 PRPL Pattern とは ref. Apply instant loading with the PRPL pattern - web.dev PRPL Pattern は、Google I/O 2016 で提案された PWA - Progressive Web Application の構築・配信のための設計アーキテクチャです。 Web サイト・アプリケーションが、回線強度やスペックが高くないスマートフォンなどのデバイスでもストレスなく機能するよう、リソース配信とアプリ起動時のパフォーマンス ( = 高速化 ) に重点を置いています。 PRPL meanings では具体的に「どうやって速くするの?」ということで、PRPL が提唱している 4 つのサイトレンダリング手法について見ていきます。 Push: <link preload> および HTTP/2 を使用して、初期 URL ルートの重要なリソースを Server Push する Render: クライアントが初期ルートをなるべく早くレンダリングする Pre-cache: 残りのルートをクライアントが Service Worker でプリキャッシュする Lazy load: クライアントはオンデマンドで残りのルートを遅延読込みして作成する PRPL は上記 4 つの頭文字をとったものですね。 PRPL は HTTP/2 の Server Push や、PWA の Service Worker など、Web プラットフォームの最新技術を駆使してサイトパフォーマンスをあげよう!というプラクティスです。 PWApps とは、最新の Web 技術を有効に活用し、漸進的 ( Progressive ) に高度なユーザー体験を提供しようとする概念です。この PWApps の概念を具体化する一つの手法として、「 PRPL 」 ( パープル ) と名付けられた開発・提供パターンが提案されました。 (中略) Web Components や、 Service Worker、 HTTP/2 Server Push といった Web の最新技術をフルに活用し、レスポンス性の高いユーザー体験を提供しようというものです。 ref. Google が新たに提唱する Progressive Web Apps の新たな開発パターン「 PRPL 」とは? 周辺知識 - HTTP/2 まずは、周辺知識からおさらいしていきます。PRPL は HTTP/2 の Server Push を利用する、という話でした。そもそも HTTP/2 とはどんなものでしょうか。 Hyper Text Transfer Protocol と呼ばれる TCP 上の通信プロトコルの次世代バージョン 普段私たちが Web サイトを閲覧する際に利用しているプロトコル HTTP/1.1 が 1997 年に策定され、2015 年にようやく /2 が標準化 Express, Apache, Nginx など各 Web サーバ、各ブラウザも対応してきている ref. HTTP の進化 現行の一般的なバージョンは HTTP/1.1 HTTP は普段私たちが Web サイトを閲覧する際に利用する通信プロトコルです。HTTP/2 はその次世代バージョンになります。HTTP/1.1 には以下のような特徴があります。 ステートレスな通信 テキストベースで情報をやりとりする 原則 1 リクエストに対して 1 レスポンスである → 複数リソースを得るために何度もリクエストしてコネクションを貼り直す必要があり パフォーマンス上の課題がある これに対して、1.1 の次期バージョンである HTTP/2 は以下のような特徴があります。 通信時にヘッダを圧縮し使い回す省エネ設計 = 一部ステートがある バイナリベースで情報をやりとりする ストリームという概念で、1 コネクション中で Request / Response を多重化できる → 1 コネクションの中で複数リソースを並行して Request / Response できる! リソースの Server Push が可能 HTTP/2 自体が HTTP/1.1 の課題であった通信のオーバヘッドを改善する規格であることがわかりますね。また「 request / response の多重化」により、1.1 と比較してどの程度「速く」なるのかについては、以下 Akamai 社のブログサイトが参考になります。 HTTP/1.1 HTTP/2 ( request / response の多重化 ) ref. HTTP/2 を活用するパフォーマンス最適化 ADAPTIVE ACCELERATION HTTP/2 の採用事例 ref. caniuse.com 上記対応状況からも分かる通り、モダンブラウザでは一通り対応しています。実際のプロダクションでも 日本ではメルカリさん、世界的なサービスだと Twitter, Facebook, Instagram など SNS サービスや、Slack, Dropbox などが HTTP/2 に対応しているようです。 ジョブメドレーはまだ HTTP/1.1 でのサービス提供しか行っていませんが、ゆくゆくはバージョンアップ対応を行っていきたいと思っています。 周辺知識 - PWA 次に、PWA についておさらいします。PRPL は PWA の Service Worker を利用した実装パターンという話でしたが、そもそも PWA や Service Worker とはどんなものなのでしょうか。 PWA - Progressive Web Application Web プラットフォームの新機能を使って「ネイティブアプリとウェブアプリのいいとこ取りした、UX の高いウェブアプリ」という概念 ウェブアプリの特性 ( Secure, Linkable, Indexable … ) を保ちつつ、ネイティブアプリの多機能さ ( インストール、プッシュ通知、オフライン動作 … ) を最新のブラウザ機能 = JavaScript API で実現する 必ずしも SPA であったり、最新機能の全てを使っている必要はなく、「斬新的に Web 新 API でネイティブな機能を取り入れていける」というコンセプト ref. プログレッシブウェブアプリの紹介 - MDN PWA を構成する新機能たち HTTPS: HyperText Transfer Protocol Secure 、 SSL / TLS による通信の暗号化 Service Worker: Web ページで動作するスクリプトから独立したイベント駆動型の worker Cache API: Request / Response オブジェクトのストレージキャッシュ Push API / Notifications API: サーバーからアプリへの通知送信 マニフェスト: アプリストアを通さず Web アプリをホーム画面にインストール可能 ref. プログレッシブウェブアプリ - MDN 上記以外にも、PWA には様々な API ・機能が存在します。その中でも PWA の、そして PRPL アーキテクチャの中核を成す重要な機能が Service Worker です。 Service Worker とは ブラウザのバックグラウンドプロセスとして動作する Worker Web ページで動作するスクリプトとは独立して動作する サーバサイドでいうところの Worker プロセスと同じような使い方ができる ref. Service Worker の紹介 Web ページの JavaScript プロセスとは切り離された文脈で、予め登録しておいた処理を、様々なイベントに応じて発火させることができるイメージですね。 プッシュ通知など、いわゆる「ネイティブアプリのような機能」は、この Service Worker を利用することで実現しています。 PWA の採用状況 Google からの提唱当初 ( PWA も Google のプロジェクトです ) こそ、先進的すぎてなかなか受け入れられなかった PWA ですが、2020 年現在は各ブラウザの対応状況も少しずつ向上されています。 日本では SUUMO、日経電子版、一休.com、世界的なサービスだと Instagram などが PWA による Web サイトを提供しているようです。 リクルートの『SUUMO』、Android スマートフォン用サイトでプッシュ通知できる機能を実装 PWA で表示速度が 2 倍に! スピード改善を妥協しない日経電子版に学ぶ、PWA のメリット&デメリット なぜ Instagram は PWA を作ったのか? 特に、既にネイティブアプリで大成功している Instagram が、回線・端末スペックの低い新興国をターゲットとした PWA をリリースしているという点はプロダクト観点からもとても興味深いですね。 PRPL パターンの利点 さて、話を戻して PRPL パターンが HTTP/2 や Service Worker を使って、具体的にどのようにサイトパフォーマンスを向上するのか?という点を見ていきます。 Server Push + Service Worker による Pre-cache PRPL の 4 要素を、改めてもう少しわかりやすく記載してみると以下のようになります。 Push 初回コネクションで HTTP/2 Server Push で 必要リソースをまとめて Push Render 上記で受け取った HTML リソースを元に初期画面をレンダリングする Pre-cache 上記初期画面で利用されるリソースは、 Server Push により非同期的に Service Worker が Pre-cache する また、今後利用しそうな追加リソースについても、非同期・投機的に Service Worker が事前に DL 、キャッシュする Lazy load 初期画面以降で必要になった画像などのリソースを、画面スクロールなどを検知し、表示に必要になったタイミングで遅延読み込みする 上記の太字箇所を画像で説明すると、以下のようになります。 HTTP/2 ( Server Push ) HTTP/2 を活用するパフォーマンス最適化 ADAPTIVE ACCELERATION HTTP/2 の Request / Response の多重化だけを利用したケースと比較すると、「ブラウザがページを解析して、必要リソースを Request する」よりも前に「サーバが必要リソースを強制的に Push 」しているのがわかります。 この Push されたリソースを Service Worker が受け取り → キャッシュ化することで 「ページ解析が終わった時点では既に必要リソースがブラウザにキャッシュされている」 状態となり、アプリの初回起動が速くなる、というのが Push & Pre-Cache の速度改善の仕組みです。 Service Worker で必要になりそうなリソースの事前キャッシュ また、初期画面に必ず必要なリソース以外については、「このあと必要になりそう・なるはずの追加リソース」ということで、Service Worker に投機的に事前 DL → Pre-cache されることも可能です。 このあたりのキャッシュ戦略・導入事例は以下の一休さんの記事が詳しいです。 一休.com に Service Worker(Workbox)を導入しました PRPL Pattern の採用状況 さて、そんなパフォーマンスに嬉しい PRPL Pattern ですが、HTTP/2、PWA 自体の普及率も高くなくまだまだプロダクションでの採用事例は少ない印象です。 Google I/O で日経電子版が事例として紹介された話 PRPL パターンを参考にした Service Worker を使ったキャッシュ、HTTP/2 Push でのリソース配信などが採用されている ライブラリでは有名どころだと Gatsby が標準対応、当たり前だが Google の Polymer ライブラリも PRPL パターンで実装されている とはいえ、PWA 化している Web サイトであればパターンの適用はそこまで難しくありません。 また Next.js の PWA 化ライブラリ next-pwa では、Next.js 本体の Code Splitting 機能と連携した「 Service Worker での追加コード読み込み」をサポートするなど、このようなアーキテクチャパターンの潮流は今後も派生していくのかな?という気がしています。 まとめ - HTTP/2 + PWA + PRPL Pattern まとめです。 PWA とは Web プラットフォームの新機能を使った「ネイティブアプリとウェブアプリのいいとこ取りした UX の高いウェブアプリ」という概念 PRPL パターンとは スマートフォンなど回線強度・スペックの低いデバイスのために、Google が UX 向上のために提唱する PWA の設計アーキテクチャ HTTP/2, Service Worker などを使って (リソースの) Server push, Pre-cache, Lazy load を行う プロダクトで使えるのか Web サイトの PWA をする/しているのであれば、サーバの HTTP/2 化をして、リソースの Push、Pre-cache を導入するのはパフォーマンス観点で十分検討できるのでは 但し、SPA + SSR 構成のサイトでは、Next.js などフレームワークのコード分割に寄せるのが今の所無難そうではある 今回は調査のみで、プロダクトへの実践投入は行いませんでしたが、今後プロダクトの PWA 化が企画されるような場合は、ぜひ導入してみたい技術だなと感じました。 以上、ここまで読んでくださり、ありがとうございました。
アバター
こんにちは。メドレーにてジョブメドレー開発エンジニアをしています、矢野と申します。 ジョブメドレーでは、主にバックエンド ( Ruby on Rails ) の改修を担当してます 直近では 「サイトパフォーマンス改善施策」 として、Rails コードのリファクタリングによる TTFB 高速化に取り組んでました 「もう絶対にコケないのが分かってる」ビルドやテストを、手元のコンソールで何度も叩いて「わー。ちゃんと通る!」っていう時間が好きです 今回は、上記の「サイトパフォーマンス改善施策」の文脈で調査した、PWA の実装パターンである PRPL Pattern という リソース提供の設計アーキテクチャ について紹介します。 PRPL Pattern とは ref. Apply instant loading with the PRPL pattern - web.dev PRPL Pattern は、Google I/O 2016 で提案された PWA - Progressive Web Application の構築・配信のための設計アーキテクチャです。 Web サイト・アプリケーションが、回線強度やスペックが高くないスマートフォンなどのデバイスでもストレスなく機能するよう、リソース配信とアプリ起動時のパフォーマンス ( = 高速化 ) に重点を置いています。 PRPL meanings では具体的に「どうやって速くするの?」ということで、PRPL が提唱している 4 つのサイトレンダリング手法について見ていきます。 Push: <link preload> および HTTP/2 を使用して、初期 URL ルートの重要なリソースを Server Push する Render: クライアントが初期ルートをなるべく早くレンダリングする Pre-cache: 残りのルートをクライアントが Service Worker でプリキャッシュする Lazy load: クライアントはオンデマンドで残りのルートを遅延読込みして作成する PRPL は上記 4 つの頭文字をとったものですね。 PRPL は HTTP/2 の Server Push や、PWA の Service Worker など、Web プラットフォームの最新技術を駆使してサイトパフォーマンスをあげよう!というプラクティスです。 PWApps とは、最新の Web 技術を有効に活用し、漸進的 ( Progressive ) に高度なユーザー体験を提供しようとする概念です。この PWApps の概念を具体化する一つの手法として、「 PRPL 」 ( パープル ) と名付けられた開発・提供パターンが提案されました。 (中略) Web Components や、 Service Worker、 HTTP/2 Server Push といった Web の最新技術をフルに活用し、レスポンス性の高いユーザー体験を提供しようというものです。 ref. Google が新たに提唱する Progressive Web Apps の新たな開発パターン「 PRPL 」とは? 周辺知識 - HTTP/2 まずは、周辺知識からおさらいしていきます。PRPL は HTTP/2 の Server Push を利用する、という話でした。そもそも HTTP/2 とはどんなものでしょうか。 Hyper Text Transfer Protocol と呼ばれる TCP 上の通信プロトコルの次世代バージョン 普段私たちが Web サイトを閲覧する際に利用しているプロトコル HTTP/1.1 が 1997 年に策定され、2015 年にようやく /2 が標準化 Express, Apache, Nginx など各 Web サーバ、各ブラウザも対応してきている ref. HTTP の進化 現行の一般的なバージョンは HTTP/1.1 HTTP は普段私たちが Web サイトを閲覧する際に利用する通信プロトコルです。HTTP/2 はその次世代バージョンになります。HTTP/1.1 には以下のような特徴があります。 ステートレスな通信 テキストベースで情報をやりとりする 原則 1 リクエストに対して 1 レスポンスである → 複数リソースを得るために何度もリクエストしてコネクションを貼り直す必要があり パフォーマンス上の課題がある これに対して、1.1 の次期バージョンである HTTP/2 は以下のような特徴があります。 通信時にヘッダを圧縮し使い回す省エネ設計 = 一部ステートがある バイナリベースで情報をやりとりする ストリームという概念で、1 コネクション中で Request / Response を多重化できる → 1 コネクションの中で複数リソースを並行して Request / Response できる! リソースの Server Push が可能 HTTP/2 自体が HTTP/1.1 の課題であった通信のオーバヘッドを改善する規格であることがわかりますね。また「 request / response の多重化」により、1.1 と比較してどの程度「速く」なるのかについては、以下 Akamai 社のブログサイトが参考になります。 HTTP/1.1 HTTP/2 ( request / response の多重化 ) ref. HTTP/2 を活用するパフォーマンス最適化 ADAPTIVE ACCELERATION HTTP/2 の採用事例 ref. caniuse.com 上記対応状況からも分かる通り、モダンブラウザでは一通り対応しています。実際のプロダクションでも 日本ではメルカリさん、世界的なサービスだと Twitter, Facebook, Instagram など SNS サービスや、Slack, Dropbox などが HTTP/2 に対応しているようです。 ジョブメドレーはまだ HTTP/1.1 でのサービス提供しか行っていませんが、ゆくゆくはバージョンアップ対応を行っていきたいと思っています。 周辺知識 - PWA 次に、PWA についておさらいします。PRPL は PWA の Service Worker を利用した実装パターンという話でしたが、そもそも PWA や Service Worker とはどんなものなのでしょうか。 PWA - Progressive Web Application Web プラットフォームの新機能を使って「ネイティブアプリとウェブアプリのいいとこ取りした、UX の高いウェブアプリ」という概念 ウェブアプリの特性 ( Secure, Linkable, Indexable … ) を保ちつつ、ネイティブアプリの多機能さ ( インストール、プッシュ通知、オフライン動作 … ) を最新のブラウザ機能 = JavaScript API で実現する 必ずしも SPA であったり、最新機能の全てを使っている必要はなく、「斬新的に Web 新 API でネイティブな機能を取り入れていける」というコンセプト ref. プログレッシブウェブアプリの紹介 - MDN PWA を構成する新機能たち HTTPS: HyperText Transfer Protocol Secure 、 SSL / TLS による通信の暗号化 Service Worker: Web ページで動作するスクリプトから独立したイベント駆動型の worker Cache API: Request / Response オブジェクトのストレージキャッシュ Push API / Notifications API: サーバーからアプリへの通知送信 マニフェスト: アプリストアを通さず Web アプリをホーム画面にインストール可能 ref. プログレッシブウェブアプリ - MDN 上記以外にも、PWA には様々な API ・機能が存在します。その中でも PWA の、そして PRPL アーキテクチャの中核を成す重要な機能が Service Worker です。 Service Worker とは ブラウザのバックグラウンドプロセスとして動作する Worker Web ページで動作するスクリプトとは独立して動作する サーバサイドでいうところの Worker プロセスと同じような使い方ができる ref. Service Worker の紹介 Web ページの JavaScript プロセスとは切り離された文脈で、予め登録しておいた処理を、様々なイベントに応じて発火させることができるイメージですね。 プッシュ通知など、いわゆる「ネイティブアプリのような機能」は、この Service Worker を利用することで実現しています。 PWA の採用状況 Google からの提唱当初 ( PWA も Google のプロジェクトです ) こそ、先進的すぎてなかなか受け入れられなかった PWA ですが、2020 年現在は各ブラウザの対応状況も少しずつ向上されています。 日本では SUUMO、日経電子版、一休.com、世界的なサービスだと Instagram などが PWA による Web サイトを提供しているようです。 リクルートの『SUUMO』、Android スマートフォン用サイトでプッシュ通知できる機能を実装 PWA で表示速度が 2 倍に! スピード改善を妥協しない日経電子版に学ぶ、PWA のメリット&デメリット なぜ Instagram は PWA を作ったのか? 特に、既にネイティブアプリで大成功している Instagram が、回線・端末スペックの低い新興国をターゲットとした PWA をリリースしているという点はプロダクト観点からもとても興味深いですね。 PRPL パターンの利点 さて、話を戻して PRPL パターンが HTTP/2 や Service Worker を使って、具体的にどのようにサイトパフォーマンスを向上するのか?という点を見ていきます。 Server Push + Service Worker による Pre-cache PRPL の 4 要素を、改めてもう少しわかりやすく記載してみると以下のようになります。 Push 初回コネクションで HTTP/2 Server Push で 必要リソースをまとめて Push Render 上記で受け取った HTML リソースを元に初期画面をレンダリングする Pre-cache 上記初期画面で利用されるリソースは、 Server Push により非同期的に Service Worker が Pre-cache する また、今後利用しそうな追加リソースについても、非同期・投機的に Service Worker が事前に DL 、キャッシュする Lazy load 初期画面以降で必要になった画像などのリソースを、画面スクロールなどを検知し、表示に必要になったタイミングで遅延読み込みする 上記の太字箇所を画像で説明すると、以下のようになります。 HTTP/2 ( Server Push ) HTTP/2 を活用するパフォーマンス最適化 ADAPTIVE ACCELERATION HTTP/2 の Request / Response の多重化だけを利用したケースと比較すると、「ブラウザがページを解析して、必要リソースを Request する」よりも前に「サーバが必要リソースを強制的に Push 」しているのがわかります。 この Push されたリソースを Service Worker が受け取り → キャッシュ化することで 「ページ解析が終わった時点では既に必要リソースがブラウザにキャッシュされている」 状態となり、アプリの初回起動が速くなる、というのが Push & Pre-Cache の速度改善の仕組みです。 Service Worker で必要になりそうなリソースの事前キャッシュ また、初期画面に必ず必要なリソース以外については、「このあと必要になりそう・なるはずの追加リソース」ということで、Service Worker に投機的に事前 DL → Pre-cache されることも可能です。 このあたりのキャッシュ戦略・導入事例は以下の一休さんの記事が詳しいです。 一休.com に Service Worker(Workbox)を導入しました PRPL Pattern の採用状況 さて、そんなパフォーマンスに嬉しい PRPL Pattern ですが、HTTP/2、PWA 自体の普及率も高くなくまだまだプロダクションでの採用事例は少ない印象です。 Google I/O で日経電子版が事例として紹介された話 PRPL パターンを参考にした Service Worker を使ったキャッシュ、HTTP/2 Push でのリソース配信などが採用されている ライブラリでは有名どころだと Gatsby が標準対応、当たり前だが Google の Polymer ライブラリも PRPL パターンで実装されている とはいえ、PWA 化している Web サイトであればパターンの適用はそこまで難しくありません。 また Next.js の PWA 化ライブラリ next-pwa では、Next.js 本体の Code Splitting 機能と連携した「 Service Worker での追加コード読み込み」をサポートするなど、このようなアーキテクチャパターンの潮流は今後も派生していくのかな?という気がしています。 まとめ - HTTP/2 + PWA + PRPL Pattern まとめです。 PWA とは Web プラットフォームの新機能を使った「ネイティブアプリとウェブアプリのいいとこ取りした UX の高いウェブアプリ」という概念 PRPL パターンとは スマートフォンなど回線強度・スペックの低いデバイスのために、Google が UX 向上のために提唱する PWA の設計アーキテクチャ HTTP/2, Service Worker などを使って (リソースの) Server push, Pre-cache, Lazy load を行う プロダクトで使えるのか Web サイトの PWA をする/しているのであれば、サーバの HTTP/2 化をして、リソースの Push、Pre-cache を導入するのはパフォーマンス観点で十分検討できるのでは 但し、SPA + SSR 構成のサイトでは、Next.js などフレームワークのコード分割に寄せるのが今の所無難そうではある 今回は調査のみで、プロダクトへの実践投入は行いませんでしたが、今後プロダクトの PWA 化が企画されるような場合は、ぜひ導入してみたい技術だなと感じました。 以上、ここまで読んでくださり、ありがとうございました。
アバター
こんにちは。メドレーにてジョブメドレー開発エンジニアをしています、矢野と申します。 ジョブメドレーでは、主にバックエンド ( Ruby on Rails ) の改修を担当してます 直近では 「サイトパフォーマンス改善施策」 として、Rails コードのリファクタリングによる TTFB 高速化に取り組んでました 「もう絶対にコケないのが分かってる」ビルドやテストを、手元のコンソールで何度も叩いて「わー。ちゃんと通る!」っていう時間が好きです 今回は、上記の「サイトパフォーマンス改善施策」の文脈で調査した、PWA の実装パターンである PRPL Pattern という リソース提供の設計アーキテクチャ について紹介します。 PRPL Pattern とは ref. Apply instant loading with the PRPL pattern - web.dev PRPL Pattern は、Google I/O 2016 で提案された PWA - Progressive Web Application の構築・配信のための設計アーキテクチャです。 Web サイト・アプリケーションが、回線強度やスペックが高くないスマートフォンなどのデバイスでもストレスなく機能するよう、リソース配信とアプリ起動時のパフォーマンス ( = 高速化 ) に重点を置いています。 PRPL meanings では具体的に「どうやって速くするの?」ということで、PRPL が提唱している 4 つのサイトレンダリング手法について見ていきます。 Push: <link preload> および HTTP/2 を使用して、初期 URL ルートの重要なリソースを Server Push する Render: クライアントが初期ルートをなるべく早くレンダリングする Pre-cache: 残りのルートをクライアントが Service Worker でプリキャッシュする Lazy load: クライアントはオンデマンドで残りのルートを遅延読込みして作成する PRPL は上記 4 つの頭文字をとったものですね。 PRPL は HTTP/2 の Server Push や、PWA の Service Worker など、Web プラットフォームの最新技術を駆使してサイトパフォーマンスをあげよう!というプラクティスです。 PWApps とは、最新の Web 技術を有効に活用し、漸進的 ( Progressive ) に高度なユーザー体験を提供しようとする概念です。この PWApps の概念を具体化する一つの手法として、「 PRPL 」 ( パープル ) と名付けられた開発・提供パターンが提案されました。 (中略) Web Components や、 Service Worker、 HTTP/2 Server Push といった Web の最新技術をフルに活用し、レスポンス性の高いユーザー体験を提供しようというものです。 ref. Google が新たに提唱する Progressive Web Apps の新たな開発パターン「 PRPL 」とは? 周辺知識 - HTTP/2 まずは、周辺知識からおさらいしていきます。PRPL は HTTP/2 の Server Push を利用する、という話でした。そもそも HTTP/2 とはどんなものでしょうか。 Hyper Text Transfer Protocol と呼ばれる TCP 上の通信プロトコルの次世代バージョン 普段私たちが Web サイトを閲覧する際に利用しているプロトコル HTTP/1.1 が 1997 年に策定され、2015 年にようやく /2 が標準化 Express, Apache, Nginx など各 Web サーバ、各ブラウザも対応してきている ref. HTTP の進化 現行の一般的なバージョンは HTTP/1.1 HTTP は普段私たちが Web サイトを閲覧する際に利用する通信プロトコルです。HTTP/2 はその次世代バージョンになります。HTTP/1.1 には以下のような特徴があります。 ステートレスな通信 テキストベースで情報をやりとりする 原則 1 リクエストに対して 1 レスポンスである → 複数リソースを得るために何度もリクエストしてコネクションを貼り直す必要があり パフォーマンス上の課題がある これに対して、1.1 の次期バージョンである HTTP/2 は以下のような特徴があります。 通信時にヘッダを圧縮し使い回す省エネ設計 = 一部ステートがある バイナリベースで情報をやりとりする ストリームという概念で、1 コネクション中で Request / Response を多重化できる → 1 コネクションの中で複数リソースを並行して Request / Response できる! リソースの Server Push が可能 HTTP/2 自体が HTTP/1.1 の課題であった通信のオーバヘッドを改善する規格であることがわかりますね。また「 request / response の多重化」により、1.1 と比較してどの程度「速く」なるのかについては、以下 Akamai 社のブログサイトが参考になります。 HTTP/1.1 HTTP/2 ( request / response の多重化 ) ref. HTTP/2 を活用するパフォーマンス最適化 ADAPTIVE ACCELERATION HTTP/2 の採用事例 ref. caniuse.com 上記対応状況からも分かる通り、モダンブラウザでは一通り対応しています。実際のプロダクションでも 日本ではメルカリさん、世界的なサービスだと Twitter, Facebook, Instagram など SNS サービスや、Slack, Dropbox などが HTTP/2 に対応しているようです。 ジョブメドレーはまだ HTTP/1.1 でのサービス提供しか行っていませんが、ゆくゆくはバージョンアップ対応を行っていきたいと思っています。 周辺知識 - PWA 次に、PWA についておさらいします。PRPL は PWA の Service Worker を利用した実装パターンという話でしたが、そもそも PWA や Service Worker とはどんなものなのでしょうか。 PWA - Progressive Web Application Web プラットフォームの新機能を使って「ネイティブアプリとウェブアプリのいいとこ取りした、UX の高いウェブアプリ」という概念 ウェブアプリの特性 ( Secure, Linkable, Indexable … ) を保ちつつ、ネイティブアプリの多機能さ ( インストール、プッシュ通知、オフライン動作 … ) を最新のブラウザ機能 = JavaScript API で実現する 必ずしも SPA であったり、最新機能の全てを使っている必要はなく、「斬新的に Web 新 API でネイティブな機能を取り入れていける」というコンセプト ref. プログレッシブウェブアプリの紹介 - MDN PWA を構成する新機能たち HTTPS: HyperText Transfer Protocol Secure 、 SSL / TLS による通信の暗号化 Service Worker: Web ページで動作するスクリプトから独立したイベント駆動型の worker Cache API: Request / Response オブジェクトのストレージキャッシュ Push API / Notifications API: サーバーからアプリへの通知送信 マニフェスト: アプリストアを通さず Web アプリをホーム画面にインストール可能 ref. プログレッシブウェブアプリ - MDN 上記以外にも、PWA には様々な API ・機能が存在します。その中でも PWA の、そして PRPL アーキテクチャの中核を成す重要な機能が Service Worker です。 Service Worker とは ブラウザのバックグラウンドプロセスとして動作する Worker Web ページで動作するスクリプトとは独立して動作する サーバサイドでいうところの Worker プロセスと同じような使い方ができる ref. Service Worker の紹介 Web ページの JavaScript プロセスとは切り離された文脈で、予め登録しておいた処理を、様々なイベントに応じて発火させることができるイメージですね。 プッシュ通知など、いわゆる「ネイティブアプリのような機能」は、この Service Worker を利用することで実現しています。 PWA の採用状況 Google からの提唱当初 ( PWA も Google のプロジェクトです ) こそ、先進的すぎてなかなか受け入れられなかった PWA ですが、2020 年現在は各ブラウザの対応状況も少しずつ向上されています。 日本では SUUMO、日経電子版、一休.com、世界的なサービスだと Instagram などが PWA による Web サイトを提供しているようです。 リクルートの『SUUMO』、Android スマートフォン用サイトでプッシュ通知できる機能を実装 PWA で表示速度が 2 倍に! スピード改善を妥協しない日経電子版に学ぶ、PWA のメリット&デメリット なぜ Instagram は PWA を作ったのか? 特に、既にネイティブアプリで大成功している Instagram が、回線・端末スペックの低い新興国をターゲットとした PWA をリリースしているという点はプロダクト観点からもとても興味深いですね。 PRPL パターンの利点 さて、話を戻して PRPL パターンが HTTP/2 や Service Worker を使って、具体的にどのようにサイトパフォーマンスを向上するのか?という点を見ていきます。 Server Push + Service Worker による Pre-cache PRPL の 4 要素を、改めてもう少しわかりやすく記載してみると以下のようになります。 Push 初回コネクションで HTTP/2 Server Push で 必要リソースをまとめて Push Render 上記で受け取った HTML リソースを元に初期画面をレンダリングする Pre-cache 上記初期画面で利用されるリソースは、 Server Push により非同期的に Service Worker が Pre-cache する また、今後利用しそうな追加リソースについても、非同期・投機的に Service Worker が事前に DL 、キャッシュする Lazy load 初期画面以降で必要になった画像などのリソースを、画面スクロールなどを検知し、表示に必要になったタイミングで遅延読み込みする 上記の太字箇所を画像で説明すると、以下のようになります。 HTTP/2 ( Server Push ) HTTP/2 を活用するパフォーマンス最適化 ADAPTIVE ACCELERATION HTTP/2 の Request / Response の多重化だけを利用したケースと比較すると、「ブラウザがページを解析して、必要リソースを Request する」よりも前に「サーバが必要リソースを強制的に Push 」しているのがわかります。 この Push されたリソースを Service Worker が受け取り → キャッシュ化することで 「ページ解析が終わった時点では既に必要リソースがブラウザにキャッシュされている」 状態となり、アプリの初回起動が速くなる、というのが Push & Pre-Cache の速度改善の仕組みです。 Service Worker で必要になりそうなリソースの事前キャッシュ また、初期画面に必ず必要なリソース以外については、「このあと必要になりそう・なるはずの追加リソース」ということで、Service Worker に投機的に事前 DL → Pre-cache されることも可能です。 このあたりのキャッシュ戦略・導入事例は以下の一休さんの記事が詳しいです。 一休.com に Service Worker(Workbox)を導入しました PRPL Pattern の採用状況 さて、そんなパフォーマンスに嬉しい PRPL Pattern ですが、HTTP/2、PWA 自体の普及率も高くなくまだまだプロダクションでの採用事例は少ない印象です。 Google I/O で日経電子版が事例として紹介された話 PRPL パターンを参考にした Service Worker を使ったキャッシュ、HTTP/2 Push でのリソース配信などが採用されている ライブラリでは有名どころだと Gatsby が標準対応、当たり前だが Google の Polymer ライブラリも PRPL パターンで実装されている とはいえ、PWA 化している Web サイトであればパターンの適用はそこまで難しくありません。 また Next.js の PWA 化ライブラリ next-pwa では、Next.js 本体の Code Splitting 機能と連携した「 Service Worker での追加コード読み込み」をサポートするなど、このようなアーキテクチャパターンの潮流は今後も派生していくのかな?という気がしています。 まとめ - HTTP/2 + PWA + PRPL Pattern まとめです。 PWA とは Web プラットフォームの新機能を使った「ネイティブアプリとウェブアプリのいいとこ取りした UX の高いウェブアプリ」という概念 PRPL パターンとは スマートフォンなど回線強度・スペックの低いデバイスのために、Google が UX 向上のために提唱する PWA の設計アーキテクチャ HTTP/2, Service Worker などを使って (リソースの) Server push, Pre-cache, Lazy load を行う プロダクトで使えるのか Web サイトの PWA をする/しているのであれば、サーバの HTTP/2 化をして、リソースの Push、Pre-cache を導入するのはパフォーマンス観点で十分検討できるのでは 但し、SPA + SSR 構成のサイトでは、Next.js などフレームワークのコード分割に寄せるのが今の所無難そうではある 今回は調査のみで、プロダクトへの実践投入は行いませんでしたが、今後プロダクトの PWA 化が企画されるような場合は、ぜひ導入してみたい技術だなと感じました。 以上、ここまで読んでくださり、ありがとうございました。
アバター
こんにちは。メドレーにてジョブメドレー開発エンジニアをしています、矢野と申します。 ジョブメドレーでは、主にバックエンド ( Ruby on Rails ) の改修を担当してます 直近では 「サイトパフォーマンス改善施策」 として、Rails コードのリファクタリングによる TTFB 高速化に取り組んでました 「もう絶対にコケないのが分かってる」ビルドやテストを、手元のコンソールで何度も叩いて「わー。ちゃんと通る!」っていう時間が好きです 今回は、上記の「サイトパフォーマンス改善施策」の文脈で調査した、PWA の実装パターンである PRPL Pattern という リソース提供の設計アーキテクチャ について紹介します。 PRPL Pattern とは ref. Apply instant loading with the PRPL pattern - web.dev PRPL Pattern は、Google I/O 2016 で提案された PWA - Progressive Web Application の構築・配信のための設計アーキテクチャです。 Web サイト・アプリケーションが、回線強度やスペックが高くないスマートフォンなどのデバイスでもストレスなく機能するよう、リソース配信とアプリ起動時のパフォーマンス ( = 高速化 ) に重点を置いています。 PRPL meanings では具体的に「どうやって速くするの?」ということで、PRPL が提唱している 4 つのサイトレンダリング手法について見ていきます。 Push: <link preload> および HTTP/2 を使用して、初期 URL ルートの重要なリソースを Server Push する Render: クライアントが初期ルートをなるべく早くレンダリングする Pre-cache: 残りのルートをクライアントが Service Worker でプリキャッシュする Lazy load: クライアントはオンデマンドで残りのルートを遅延読込みして作成する PRPL は上記 4 つの頭文字をとったものですね。 PRPL は HTTP/2 の Server Push や、PWA の Service Worker など、Web プラットフォームの最新技術を駆使してサイトパフォーマンスをあげよう!というプラクティスです。 PWApps とは、最新の Web 技術を有効に活用し、漸進的 ( Progressive ) に高度なユーザー体験を提供しようとする概念です。この PWApps の概念を具体化する一つの手法として、「 PRPL 」 ( パープル ) と名付けられた開発・提供パターンが提案されました。 (中略) Web Components や、 Service Worker、 HTTP/2 Server Push といった Web の最新技術をフルに活用し、レスポンス性の高いユーザー体験を提供しようというものです。 ref. Google が新たに提唱する Progressive Web Apps の新たな開発パターン「 PRPL 」とは? 周辺知識 - HTTP/2 まずは、周辺知識からおさらいしていきます。PRPL は HTTP/2 の Server Push を利用する、という話でした。そもそも HTTP/2 とはどんなものでしょうか。 Hyper Text Transfer Protocol と呼ばれる TCP 上の通信プロトコルの次世代バージョン 普段私たちが Web サイトを閲覧する際に利用しているプロトコル HTTP/1.1 が 1997 年に策定され、2015 年にようやく /2 が標準化 Express, Apache, Nginx など各 Web サーバ、各ブラウザも対応してきている ref. HTTP の進化 現行の一般的なバージョンは HTTP/1.1 HTTP は普段私たちが Web サイトを閲覧する際に利用する通信プロトコルです。HTTP/2 はその次世代バージョンになります。HTTP/1.1 には以下のような特徴があります。 ステートレスな通信 テキストベースで情報をやりとりする 原則 1 リクエストに対して 1 レスポンスである → 複数リソースを得るために何度もリクエストしてコネクションを貼り直す必要があり パフォーマンス上の課題がある これに対して、1.1 の次期バージョンである HTTP/2 は以下のような特徴があります。 通信時にヘッダを圧縮し使い回す省エネ設計 = 一部ステートがある バイナリベースで情報をやりとりする ストリームという概念で、1 コネクション中で Request / Response を多重化できる → 1 コネクションの中で複数リソースを並行して Request / Response できる! リソースの Server Push が可能 HTTP/2 自体が HTTP/1.1 の課題であった通信のオーバヘッドを改善する規格であることがわかりますね。また「 request / response の多重化」により、1.1 と比較してどの程度「速く」なるのかについては、以下 Akamai 社のブログサイトが参考になります。 HTTP/1.1 HTTP/2 ( request / response の多重化 ) ref. HTTP/2 を活用するパフォーマンス最適化 ADAPTIVE ACCELERATION HTTP/2 の採用事例 ref. caniuse.com 上記対応状況からも分かる通り、モダンブラウザでは一通り対応しています。実際のプロダクションでも 日本ではメルカリさん、世界的なサービスだと Twitter, Facebook, Instagram など SNS サービスや、Slack, Dropbox などが HTTP/2 に対応しているようです。 ジョブメドレーはまだ HTTP/1.1 でのサービス提供しか行っていませんが、ゆくゆくはバージョンアップ対応を行っていきたいと思っています。 周辺知識 - PWA 次に、PWA についておさらいします。PRPL は PWA の Service Worker を利用した実装パターンという話でしたが、そもそも PWA や Service Worker とはどんなものなのでしょうか。 PWA - Progressive Web Application Web プラットフォームの新機能を使って「ネイティブアプリとウェブアプリのいいとこ取りした、UX の高いウェブアプリ」という概念 ウェブアプリの特性 ( Secure, Linkable, Indexable … ) を保ちつつ、ネイティブアプリの多機能さ ( インストール、プッシュ通知、オフライン動作 … ) を最新のブラウザ機能 = JavaScript API で実現する 必ずしも SPA であったり、最新機能の全てを使っている必要はなく、「斬新的に Web 新 API でネイティブな機能を取り入れていける」というコンセプト ref. プログレッシブウェブアプリの紹介 - MDN PWA を構成する新機能たち HTTPS: HyperText Transfer Protocol Secure 、 SSL / TLS による通信の暗号化 Service Worker: Web ページで動作するスクリプトから独立したイベント駆動型の worker Cache API: Request / Response オブジェクトのストレージキャッシュ Push API / Notifications API: サーバーからアプリへの通知送信 マニフェスト: アプリストアを通さず Web アプリをホーム画面にインストール可能 ref. プログレッシブウェブアプリ - MDN 上記以外にも、PWA には様々な API ・機能が存在します。その中でも PWA の、そして PRPL アーキテクチャの中核を成す重要な機能が Service Worker です。 Service Worker とは ブラウザのバックグラウンドプロセスとして動作する Worker Web ページで動作するスクリプトとは独立して動作する サーバサイドでいうところの Worker プロセスと同じような使い方ができる ref. Service Worker の紹介 Web ページの JavaScript プロセスとは切り離された文脈で、予め登録しておいた処理を、様々なイベントに応じて発火させることができるイメージですね。 プッシュ通知など、いわゆる「ネイティブアプリのような機能」は、この Service Worker を利用することで実現しています。 PWA の採用状況 Google からの提唱当初 ( PWA も Google のプロジェクトです ) こそ、先進的すぎてなかなか受け入れられなかった PWA ですが、2020 年現在は各ブラウザの対応状況も少しずつ向上されています。 日本では SUUMO、日経電子版、一休.com、世界的なサービスだと Instagram などが PWA による Web サイトを提供しているようです。 リクルートの『SUUMO』、Android スマートフォン用サイトでプッシュ通知できる機能を実装 PWA で表示速度が 2 倍に! スピード改善を妥協しない日経電子版に学ぶ、PWA のメリット&デメリット なぜ Instagram は PWA を作ったのか? 特に、既にネイティブアプリで大成功している Instagram が、回線・端末スペックの低い新興国をターゲットとした PWA をリリースしているという点はプロダクト観点からもとても興味深いですね。 PRPL パターンの利点 さて、話を戻して PRPL パターンが HTTP/2 や Service Worker を使って、具体的にどのようにサイトパフォーマンスを向上するのか?という点を見ていきます。 Server Push + Service Worker による Pre-cache PRPL の 4 要素を、改めてもう少しわかりやすく記載してみると以下のようになります。 Push 初回コネクションで HTTP/2 Server Push で 必要リソースをまとめて Push Render 上記で受け取った HTML リソースを元に初期画面をレンダリングする Pre-cache 上記初期画面で利用されるリソースは、 Server Push により非同期的に Service Worker が Pre-cache する また、今後利用しそうな追加リソースについても、非同期・投機的に Service Worker が事前に DL 、キャッシュする Lazy load 初期画面以降で必要になった画像などのリソースを、画面スクロールなどを検知し、表示に必要になったタイミングで遅延読み込みする 上記の太字箇所を画像で説明すると、以下のようになります。 HTTP/2 ( Server Push ) HTTP/2 を活用するパフォーマンス最適化 ADAPTIVE ACCELERATION HTTP/2 の Request / Response の多重化だけを利用したケースと比較すると、「ブラウザがページを解析して、必要リソースを Request する」よりも前に「サーバが必要リソースを強制的に Push 」しているのがわかります。 この Push されたリソースを Service Worker が受け取り → キャッシュ化することで 「ページ解析が終わった時点では既に必要リソースがブラウザにキャッシュされている」 状態となり、アプリの初回起動が速くなる、というのが Push & Pre-Cache の速度改善の仕組みです。 Service Worker で必要になりそうなリソースの事前キャッシュ また、初期画面に必ず必要なリソース以外については、「このあと必要になりそう・なるはずの追加リソース」ということで、Service Worker に投機的に事前 DL → Pre-cache されることも可能です。 このあたりのキャッシュ戦略・導入事例は以下の一休さんの記事が詳しいです。 一休.com に Service Worker(Workbox)を導入しました PRPL Pattern の採用状況 さて、そんなパフォーマンスに嬉しい PRPL Pattern ですが、HTTP/2、PWA 自体の普及率も高くなくまだまだプロダクションでの採用事例は少ない印象です。 Google I/O で日経電子版が事例として紹介された話 PRPL パターンを参考にした Service Worker を使ったキャッシュ、HTTP/2 Push でのリソース配信などが採用されている ライブラリでは有名どころだと Gatsby が標準対応、当たり前だが Google の Polymer ライブラリも PRPL パターンで実装されている とはいえ、PWA 化している Web サイトであればパターンの適用はそこまで難しくありません。 また Next.js の PWA 化ライブラリ next-pwa では、Next.js 本体の Code Splitting 機能と連携した「 Service Worker での追加コード読み込み」をサポートするなど、このようなアーキテクチャパターンの潮流は今後も派生していくのかな?という気がしています。 まとめ - HTTP/2 + PWA + PRPL Pattern まとめです。 PWA とは Web プラットフォームの新機能を使った「ネイティブアプリとウェブアプリのいいとこ取りした UX の高いウェブアプリ」という概念 PRPL パターンとは スマートフォンなど回線強度・スペックの低いデバイスのために、Google が UX 向上のために提唱する PWA の設計アーキテクチャ HTTP/2, Service Worker などを使って (リソースの) Server push, Pre-cache, Lazy load を行う プロダクトで使えるのか Web サイトの PWA をする/しているのであれば、サーバの HTTP/2 化をして、リソースの Push、Pre-cache を導入するのはパフォーマンス観点で十分検討できるのでは 但し、SPA + SSR 構成のサイトでは、Next.js などフレームワークのコード分割に寄せるのが今の所無難そうではある 今回は調査のみで、プロダクトへの実践投入は行いませんでしたが、今後プロダクトの PWA 化が企画されるような場合は、ぜひ導入してみたい技術だなと感じました。 以上、ここまで読んでくださり、ありがとうございました。
アバター
こんにちは。メドレーにてジョブメドレー開発エンジニアをしています、矢野と申します。 ジョブメドレーでは、主にバックエンド ( Ruby on Rails ) の改修を担当してます 直近では 「サイトパフォーマンス改善施策」 として、Rails コードのリファクタリングによる TTFB 高速化に取り組んでました 「もう絶対にコケないのが分かってる」ビルドやテストを、手元のコンソールで何度も叩いて「わー。ちゃんと通る!」っていう時間が好きです 今回は、上記の「サイトパフォーマンス改善施策」の文脈で調査した、PWA の実装パターンである PRPL Pattern という リソース提供の設計アーキテクチャ について紹介します。 PRPL Pattern とは ref. Apply instant loading with the PRPL pattern - web.dev PRPL Pattern は、Google I/O 2016 で提案された PWA - Progressive Web Application の構築・配信のための設計アーキテクチャです。 Web サイト・アプリケーションが、回線強度やスペックが高くないスマートフォンなどのデバイスでもストレスなく機能するよう、リソース配信とアプリ起動時のパフォーマンス ( = 高速化 ) に重点を置いています。 PRPL meanings では具体的に「どうやって速くするの?」ということで、PRPL が提唱している 4 つのサイトレンダリング手法について見ていきます。 Push: <link preload> および HTTP/2 を使用して、初期 URL ルートの重要なリソースを Server Push する Render: クライアントが初期ルートをなるべく早くレンダリングする Pre-cache: 残りのルートをクライアントが Service Worker でプリキャッシュする Lazy load: クライアントはオンデマンドで残りのルートを遅延読込みして作成する PRPL は上記 4 つの頭文字をとったものですね。 PRPL は HTTP/2 の Server Push や、PWA の Service Worker など、Web プラットフォームの最新技術を駆使してサイトパフォーマンスをあげよう!というプラクティスです。 PWApps とは、最新の Web 技術を有効に活用し、漸進的 ( Progressive ) に高度なユーザー体験を提供しようとする概念です。この PWApps の概念を具体化する一つの手法として、「 PRPL 」 ( パープル ) と名付けられた開発・提供パターンが提案されました。 (中略) Web Components や、 Service Worker、 HTTP/2 Server Push といった Web の最新技術をフルに活用し、レスポンス性の高いユーザー体験を提供しようというものです。 ref. Google が新たに提唱する Progressive Web Apps の新たな開発パターン「 PRPL 」とは? 周辺知識 - HTTP/2 まずは、周辺知識からおさらいしていきます。PRPL は HTTP/2 の Server Push を利用する、という話でした。そもそも HTTP/2 とはどんなものでしょうか。 Hyper Text Transfer Protocol と呼ばれる TCP 上の通信プロトコルの次世代バージョン 普段私たちが Web サイトを閲覧する際に利用しているプロトコル HTTP/1.1 が 1997 年に策定され、2015 年にようやく /2 が標準化 Express, Apache, Nginx など各 Web サーバ、各ブラウザも対応してきている ref. HTTP の進化 現行の一般的なバージョンは HTTP/1.1 HTTP は普段私たちが Web サイトを閲覧する際に利用する通信プロトコルです。HTTP/2 はその次世代バージョンになります。HTTP/1.1 には以下のような特徴があります。 ステートレスな通信 テキストベースで情報をやりとりする 原則 1 リクエストに対して 1 レスポンスである → 複数リソースを得るために何度もリクエストしてコネクションを貼り直す必要があり パフォーマンス上の課題がある これに対して、1.1 の次期バージョンである HTTP/2 は以下のような特徴があります。 通信時にヘッダを圧縮し使い回す省エネ設計 = 一部ステートがある バイナリベースで情報をやりとりする ストリームという概念で、1 コネクション中で Request / Response を多重化できる → 1 コネクションの中で複数リソースを並行して Request / Response できる! リソースの Server Push が可能 HTTP/2 自体が HTTP/1.1 の課題であった通信のオーバヘッドを改善する規格であることがわかりますね。また「 request / response の多重化」により、1.1 と比較してどの程度「速く」なるのかについては、以下 Akamai 社のブログサイトが参考になります。 HTTP/1.1 HTTP/2 ( request / response の多重化 ) ref. HTTP/2 を活用するパフォーマンス最適化 ADAPTIVE ACCELERATION HTTP/2 の採用事例 ref. caniuse.com 上記対応状況からも分かる通り、モダンブラウザでは一通り対応しています。実際のプロダクションでも 日本ではメルカリさん、世界的なサービスだと Twitter, Facebook, Instagram など SNS サービスや、Slack, Dropbox などが HTTP/2 に対応しているようです。 ジョブメドレーはまだ HTTP/1.1 でのサービス提供しか行っていませんが、ゆくゆくはバージョンアップ対応を行っていきたいと思っています。 周辺知識 - PWA 次に、PWA についておさらいします。PRPL は PWA の Service Worker を利用した実装パターンという話でしたが、そもそも PWA や Service Worker とはどんなものなのでしょうか。 PWA - Progressive Web Application Web プラットフォームの新機能を使って「ネイティブアプリとウェブアプリのいいとこ取りした、UX の高いウェブアプリ」という概念 ウェブアプリの特性 ( Secure, Linkable, Indexable … ) を保ちつつ、ネイティブアプリの多機能さ ( インストール、プッシュ通知、オフライン動作 … ) を最新のブラウザ機能 = JavaScript API で実現する 必ずしも SPA であったり、最新機能の全てを使っている必要はなく、「斬新的に Web 新 API でネイティブな機能を取り入れていける」というコンセプト ref. プログレッシブウェブアプリの紹介 - MDN PWA を構成する新機能たち HTTPS: HyperText Transfer Protocol Secure 、 SSL / TLS による通信の暗号化 Service Worker: Web ページで動作するスクリプトから独立したイベント駆動型の worker Cache API: Request / Response オブジェクトのストレージキャッシュ Push API / Notifications API: サーバーからアプリへの通知送信 マニフェスト: アプリストアを通さず Web アプリをホーム画面にインストール可能 ref. プログレッシブウェブアプリ - MDN 上記以外にも、PWA には様々な API ・機能が存在します。その中でも PWA の、そして PRPL アーキテクチャの中核を成す重要な機能が Service Worker です。 Service Worker とは ブラウザのバックグラウンドプロセスとして動作する Worker Web ページで動作するスクリプトとは独立して動作する サーバサイドでいうところの Worker プロセスと同じような使い方ができる ref. Service Worker の紹介 Web ページの JavaScript プロセスとは切り離された文脈で、予め登録しておいた処理を、様々なイベントに応じて発火させることができるイメージですね。 プッシュ通知など、いわゆる「ネイティブアプリのような機能」は、この Service Worker を利用することで実現しています。 PWA の採用状況 Google からの提唱当初 ( PWA も Google のプロジェクトです ) こそ、先進的すぎてなかなか受け入れられなかった PWA ですが、2020 年現在は各ブラウザの対応状況も少しずつ向上されています。 日本では SUUMO、日経電子版、一休.com、世界的なサービスだと Instagram などが PWA による Web サイトを提供しているようです。 リクルートの『SUUMO』、Android スマートフォン用サイトでプッシュ通知できる機能を実装 PWA で表示速度が 2 倍に! スピード改善を妥協しない日経電子版に学ぶ、PWA のメリット&デメリット なぜ Instagram は PWA を作ったのか? 特に、既にネイティブアプリで大成功している Instagram が、回線・端末スペックの低い新興国をターゲットとした PWA をリリースしているという点はプロダクト観点からもとても興味深いですね。 PRPL パターンの利点 さて、話を戻して PRPL パターンが HTTP/2 や Service Worker を使って、具体的にどのようにサイトパフォーマンスを向上するのか?という点を見ていきます。 Server Push + Service Worker による Pre-cache PRPL の 4 要素を、改めてもう少しわかりやすく記載してみると以下のようになります。 Push 初回コネクションで HTTP/2 Server Push で 必要リソースをまとめて Push Render 上記で受け取った HTML リソースを元に初期画面をレンダリングする Pre-cache 上記初期画面で利用されるリソースは、 Server Push により非同期的に Service Worker が Pre-cache する また、今後利用しそうな追加リソースについても、非同期・投機的に Service Worker が事前に DL 、キャッシュする Lazy load 初期画面以降で必要になった画像などのリソースを、画面スクロールなどを検知し、表示に必要になったタイミングで遅延読み込みする 上記の太字箇所を画像で説明すると、以下のようになります。 HTTP/2 ( Server Push ) HTTP/2 を活用するパフォーマンス最適化 ADAPTIVE ACCELERATION HTTP/2 の Request / Response の多重化だけを利用したケースと比較すると、「ブラウザがページを解析して、必要リソースを Request する」よりも前に「サーバが必要リソースを強制的に Push 」しているのがわかります。 この Push されたリソースを Service Worker が受け取り → キャッシュ化することで 「ページ解析が終わった時点では既に必要リソースがブラウザにキャッシュされている」 状態となり、アプリの初回起動が速くなる、というのが Push & Pre-Cache の速度改善の仕組みです。 Service Worker で必要になりそうなリソースの事前キャッシュ また、初期画面に必ず必要なリソース以外については、「このあと必要になりそう・なるはずの追加リソース」ということで、Service Worker に投機的に事前 DL → Pre-cache されることも可能です。 このあたりのキャッシュ戦略・導入事例は以下の一休さんの記事が詳しいです。 一休.com に Service Worker(Workbox)を導入しました PRPL Pattern の採用状況 さて、そんなパフォーマンスに嬉しい PRPL Pattern ですが、HTTP/2、PWA 自体の普及率も高くなくまだまだプロダクションでの採用事例は少ない印象です。 Google I/O で日経電子版が事例として紹介された話 PRPL パターンを参考にした Service Worker を使ったキャッシュ、HTTP/2 Push でのリソース配信などが採用されている ライブラリでは有名どころだと Gatsby が標準対応、当たり前だが Google の Polymer ライブラリも PRPL パターンで実装されている とはいえ、PWA 化している Web サイトであればパターンの適用はそこまで難しくありません。 また Next.js の PWA 化ライブラリ next-pwa では、Next.js 本体の Code Splitting 機能と連携した「 Service Worker での追加コード読み込み」をサポートするなど、このようなアーキテクチャパターンの潮流は今後も派生していくのかな?という気がしています。 まとめ - HTTP/2 + PWA + PRPL Pattern まとめです。 PWA とは Web プラットフォームの新機能を使った「ネイティブアプリとウェブアプリのいいとこ取りした UX の高いウェブアプリ」という概念 PRPL パターンとは スマートフォンなど回線強度・スペックの低いデバイスのために、Google が UX 向上のために提唱する PWA の設計アーキテクチャ HTTP/2, Service Worker などを使って (リソースの) Server push, Pre-cache, Lazy load を行う プロダクトで使えるのか Web サイトの PWA をする/しているのであれば、サーバの HTTP/2 化をして、リソースの Push、Pre-cache を導入するのはパフォーマンス観点で十分検討できるのでは 但し、SPA + SSR 構成のサイトでは、Next.js などフレームワークのコード分割に寄せるのが今の所無難そうではある 今回は調査のみで、プロダクトへの実践投入は行いませんでしたが、今後プロダクトの PWA 化が企画されるような場合は、ぜひ導入してみたい技術だなと感じました。 以上、ここまで読んでくださり、ありがとうございました。
アバター
こんにちは。メドレーにてジョブメドレー開発エンジニアをしています、矢野と申します。 ジョブメドレーでは、主にバックエンド ( Ruby on Rails ) の改修を担当してます 直近では 「サイトパフォーマンス改善施策」 として、Rails コードのリファクタリングによる TTFB 高速化に取り組んでました 「もう絶対にコケないのが分かってる」ビルドやテストを、手元のコンソールで何度も叩いて「わー。ちゃんと通る!」っていう時間が好きです 今回は、上記の「サイトパフォーマンス改善施策」の文脈で調査した、PWA の実装パターンである PRPL Pattern という リソース提供の設計アーキテクチャ について紹介します。 PRPL Pattern とは ref. Apply instant loading with the PRPL pattern - web.dev PRPL Pattern は、Google I/O 2016 で提案された PWA - Progressive Web Application の構築・配信のための設計アーキテクチャです。 Web サイト・アプリケーションが、回線強度やスペックが高くないスマートフォンなどのデバイスでもストレスなく機能するよう、リソース配信とアプリ起動時のパフォーマンス ( = 高速化 ) に重点を置いています。 PRPL meanings では具体的に「どうやって速くするの?」ということで、PRPL が提唱している 4 つのサイトレンダリング手法について見ていきます。 Push: <link preload> および HTTP/2 を使用して、初期 URL ルートの重要なリソースを Server Push する Render: クライアントが初期ルートをなるべく早くレンダリングする Pre-cache: 残りのルートをクライアントが Service Worker でプリキャッシュする Lazy load: クライアントはオンデマンドで残りのルートを遅延読込みして作成する PRPL は上記 4 つの頭文字をとったものですね。 PRPL は HTTP/2 の Server Push や、PWA の Service Worker など、Web プラットフォームの最新技術を駆使してサイトパフォーマンスをあげよう!というプラクティスです。 PWApps とは、最新の Web 技術を有効に活用し、漸進的 ( Progressive ) に高度なユーザー体験を提供しようとする概念です。この PWApps の概念を具体化する一つの手法として、「 PRPL 」 ( パープル ) と名付けられた開発・提供パターンが提案されました。 (中略) Web Components や、 Service Worker、 HTTP/2 Server Push といった Web の最新技術をフルに活用し、レスポンス性の高いユーザー体験を提供しようというものです。 ref. Google が新たに提唱する Progressive Web Apps の新たな開発パターン「 PRPL 」とは? 周辺知識 - HTTP/2 まずは、周辺知識からおさらいしていきます。PRPL は HTTP/2 の Server Push を利用する、という話でした。そもそも HTTP/2 とはどんなものでしょうか。 Hyper Text Transfer Protocol と呼ばれる TCP 上の通信プロトコルの次世代バージョン 普段私たちが Web サイトを閲覧する際に利用しているプロトコル HTTP/1.1 が 1997 年に策定され、2015 年にようやく /2 が標準化 Express, Apache, Nginx など各 Web サーバ、各ブラウザも対応してきている ref. HTTP の進化 現行の一般的なバージョンは HTTP/1.1 HTTP は普段私たちが Web サイトを閲覧する際に利用する通信プロトコルです。HTTP/2 はその次世代バージョンになります。HTTP/1.1 には以下のような特徴があります。 ステートレスな通信 テキストベースで情報をやりとりする 原則 1 リクエストに対して 1 レスポンスである → 複数リソースを得るために何度もリクエストしてコネクションを貼り直す必要があり パフォーマンス上の課題がある これに対して、1.1 の次期バージョンである HTTP/2 は以下のような特徴があります。 通信時にヘッダを圧縮し使い回す省エネ設計 = 一部ステートがある バイナリベースで情報をやりとりする ストリームという概念で、1 コネクション中で Request / Response を多重化できる → 1 コネクションの中で複数リソースを並行して Request / Response できる! リソースの Server Push が可能 HTTP/2 自体が HTTP/1.1 の課題であった通信のオーバヘッドを改善する規格であることがわかりますね。また「 request / response の多重化」により、1.1 と比較してどの程度「速く」なるのかについては、以下 Akamai 社のブログサイトが参考になります。 HTTP/1.1 HTTP/2 ( request / response の多重化 ) ref. HTTP/2 を活用するパフォーマンス最適化 ADAPTIVE ACCELERATION HTTP/2 の採用事例 ref. caniuse.com 上記対応状況からも分かる通り、モダンブラウザでは一通り対応しています。実際のプロダクションでも 日本ではメルカリさん、世界的なサービスだと Twitter, Facebook, Instagram など SNS サービスや、Slack, Dropbox などが HTTP/2 に対応しているようです。 ジョブメドレーはまだ HTTP/1.1 でのサービス提供しか行っていませんが、ゆくゆくはバージョンアップ対応を行っていきたいと思っています。 周辺知識 - PWA 次に、PWA についておさらいします。PRPL は PWA の Service Worker を利用した実装パターンという話でしたが、そもそも PWA や Service Worker とはどんなものなのでしょうか。 PWA - Progressive Web Application Web プラットフォームの新機能を使って「ネイティブアプリとウェブアプリのいいとこ取りした、UX の高いウェブアプリ」という概念 ウェブアプリの特性 ( Secure, Linkable, Indexable … ) を保ちつつ、ネイティブアプリの多機能さ ( インストール、プッシュ通知、オフライン動作 … ) を最新のブラウザ機能 = JavaScript API で実現する 必ずしも SPA であったり、最新機能の全てを使っている必要はなく、「斬新的に Web 新 API でネイティブな機能を取り入れていける」というコンセプト ref. プログレッシブウェブアプリの紹介 - MDN PWA を構成する新機能たち HTTPS: HyperText Transfer Protocol Secure 、 SSL / TLS による通信の暗号化 Service Worker: Web ページで動作するスクリプトから独立したイベント駆動型の worker Cache API: Request / Response オブジェクトのストレージキャッシュ Push API / Notifications API: サーバーからアプリへの通知送信 マニフェスト: アプリストアを通さず Web アプリをホーム画面にインストール可能 ref. プログレッシブウェブアプリ - MDN 上記以外にも、PWA には様々な API ・機能が存在します。その中でも PWA の、そして PRPL アーキテクチャの中核を成す重要な機能が Service Worker です。 Service Worker とは ブラウザのバックグラウンドプロセスとして動作する Worker Web ページで動作するスクリプトとは独立して動作する サーバサイドでいうところの Worker プロセスと同じような使い方ができる ref. Service Worker の紹介 Web ページの JavaScript プロセスとは切り離された文脈で、予め登録しておいた処理を、様々なイベントに応じて発火させることができるイメージですね。 プッシュ通知など、いわゆる「ネイティブアプリのような機能」は、この Service Worker を利用することで実現しています。 PWA の採用状況 Google からの提唱当初 ( PWA も Google のプロジェクトです ) こそ、先進的すぎてなかなか受け入れられなかった PWA ですが、2020 年現在は各ブラウザの対応状況も少しずつ向上されています。 日本では SUUMO、日経電子版、一休.com、世界的なサービスだと Instagram などが PWA による Web サイトを提供しているようです。 リクルートの『SUUMO』、Android スマートフォン用サイトでプッシュ通知できる機能を実装 PWA で表示速度が 2 倍に! スピード改善を妥協しない日経電子版に学ぶ、PWA のメリット&デメリット なぜ Instagram は PWA を作ったのか? 特に、既にネイティブアプリで大成功している Instagram が、回線・端末スペックの低い新興国をターゲットとした PWA をリリースしているという点はプロダクト観点からもとても興味深いですね。 PRPL パターンの利点 さて、話を戻して PRPL パターンが HTTP/2 や Service Worker を使って、具体的にどのようにサイトパフォーマンスを向上するのか?という点を見ていきます。 Server Push + Service Worker による Pre-cache PRPL の 4 要素を、改めてもう少しわかりやすく記載してみると以下のようになります。 Push 初回コネクションで HTTP/2 Server Push で 必要リソースをまとめて Push Render 上記で受け取った HTML リソースを元に初期画面をレンダリングする Pre-cache 上記初期画面で利用されるリソースは、 Server Push により非同期的に Service Worker が Pre-cache する また、今後利用しそうな追加リソースについても、非同期・投機的に Service Worker が事前に DL 、キャッシュする Lazy load 初期画面以降で必要になった画像などのリソースを、画面スクロールなどを検知し、表示に必要になったタイミングで遅延読み込みする 上記の太字箇所を画像で説明すると、以下のようになります。 HTTP/2 ( Server Push ) HTTP/2 を活用するパフォーマンス最適化 ADAPTIVE ACCELERATION HTTP/2 の Request / Response の多重化だけを利用したケースと比較すると、「ブラウザがページを解析して、必要リソースを Request する」よりも前に「サーバが必要リソースを強制的に Push 」しているのがわかります。 この Push されたリソースを Service Worker が受け取り → キャッシュ化することで 「ページ解析が終わった時点では既に必要リソースがブラウザにキャッシュされている」 状態となり、アプリの初回起動が速くなる、というのが Push & Pre-Cache の速度改善の仕組みです。 Service Worker で必要になりそうなリソースの事前キャッシュ また、初期画面に必ず必要なリソース以外については、「このあと必要になりそう・なるはずの追加リソース」ということで、Service Worker に投機的に事前 DL → Pre-cache されることも可能です。 このあたりのキャッシュ戦略・導入事例は以下の一休さんの記事が詳しいです。 一休.com に Service Worker(Workbox)を導入しました PRPL Pattern の採用状況 さて、そんなパフォーマンスに嬉しい PRPL Pattern ですが、HTTP/2、PWA 自体の普及率も高くなくまだまだプロダクションでの採用事例は少ない印象です。 Google I/O で日経電子版が事例として紹介された話 PRPL パターンを参考にした Service Worker を使ったキャッシュ、HTTP/2 Push でのリソース配信などが採用されている ライブラリでは有名どころだと Gatsby が標準対応、当たり前だが Google の Polymer ライブラリも PRPL パターンで実装されている とはいえ、PWA 化している Web サイトであればパターンの適用はそこまで難しくありません。 また Next.js の PWA 化ライブラリ next-pwa では、Next.js 本体の Code Splitting 機能と連携した「 Service Worker での追加コード読み込み」をサポートするなど、このようなアーキテクチャパターンの潮流は今後も派生していくのかな?という気がしています。 まとめ - HTTP/2 + PWA + PRPL Pattern まとめです。 PWA とは Web プラットフォームの新機能を使った「ネイティブアプリとウェブアプリのいいとこ取りした UX の高いウェブアプリ」という概念 PRPL パターンとは スマートフォンなど回線強度・スペックの低いデバイスのために、Google が UX 向上のために提唱する PWA の設計アーキテクチャ HTTP/2, Service Worker などを使って (リソースの) Server push, Pre-cache, Lazy load を行う プロダクトで使えるのか Web サイトの PWA をする/しているのであれば、サーバの HTTP/2 化をして、リソースの Push、Pre-cache を導入するのはパフォーマンス観点で十分検討できるのでは 但し、SPA + SSR 構成のサイトでは、Next.js などフレームワークのコード分割に寄せるのが今の所無難そうではある 今回は調査のみで、プロダクトへの実践投入は行いませんでしたが、今後プロダクトの PWA 化が企画されるような場合は、ぜひ導入してみたい技術だなと感じました。 以上、ここまで読んでくださり、ありがとうございました。
アバター
こんにちは。メドレーにてジョブメドレー開発エンジニアをしています、矢野と申します。 ジョブメドレーでは、主にバックエンド ( Ruby on Rails ) の改修を担当してます 直近では 「サイトパフォーマンス改善施策」 として、Rails コードのリファクタリングによる TTFB 高速化に取り組んでました 「もう絶対にコケないのが分かってる」ビルドやテストを、手元のコンソールで何度も叩いて「わー。ちゃんと通る!」っていう時間が好きです 今回は、上記の「サイトパフォーマンス改善施策」の文脈で調査した、PWA の実装パターンである PRPL Pattern という リソース提供の設計アーキテクチャ について紹介します。 PRPL Pattern とは ref. Apply instant loading with the PRPL pattern - web.dev PRPL Pattern は、Google I/O 2016 で提案された PWA - Progressive Web Application の構築・配信のための設計アーキテクチャです。 Web サイト・アプリケーションが、回線強度やスペックが高くないスマートフォンなどのデバイスでもストレスなく機能するよう、リソース配信とアプリ起動時のパフォーマンス ( = 高速化 ) に重点を置いています。 PRPL meanings では具体的に「どうやって速くするの?」ということで、PRPL が提唱している 4 つのサイトレンダリング手法について見ていきます。 Push: <link preload> および HTTP/2 を使用して、初期 URL ルートの重要なリソースを Server Push する Render: クライアントが初期ルートをなるべく早くレンダリングする Pre-cache: 残りのルートをクライアントが Service Worker でプリキャッシュする Lazy load: クライアントはオンデマンドで残りのルートを遅延読込みして作成する PRPL は上記 4 つの頭文字をとったものですね。 PRPL は HTTP/2 の Server Push や、PWA の Service Worker など、Web プラットフォームの最新技術を駆使してサイトパフォーマンスをあげよう!というプラクティスです。 PWApps とは、最新の Web 技術を有効に活用し、漸進的 ( Progressive ) に高度なユーザー体験を提供しようとする概念です。この PWApps の概念を具体化する一つの手法として、「 PRPL 」 ( パープル ) と名付けられた開発・提供パターンが提案されました。 (中略) Web Components や、 Service Worker、 HTTP/2 Server Push といった Web の最新技術をフルに活用し、レスポンス性の高いユーザー体験を提供しようというものです。 ref. Google が新たに提唱する Progressive Web Apps の新たな開発パターン「 PRPL 」とは? 周辺知識 - HTTP/2 まずは、周辺知識からおさらいしていきます。PRPL は HTTP/2 の Server Push を利用する、という話でした。そもそも HTTP/2 とはどんなものでしょうか。 Hyper Text Transfer Protocol と呼ばれる TCP 上の通信プロトコルの次世代バージョン 普段私たちが Web サイトを閲覧する際に利用しているプロトコル HTTP/1.1 が 1997 年に策定され、2015 年にようやく /2 が標準化 Express, Apache, Nginx など各 Web サーバ、各ブラウザも対応してきている ref. HTTP の進化 現行の一般的なバージョンは HTTP/1.1 HTTP は普段私たちが Web サイトを閲覧する際に利用する通信プロトコルです。HTTP/2 はその次世代バージョンになります。HTTP/1.1 には以下のような特徴があります。 ステートレスな通信 テキストベースで情報をやりとりする 原則 1 リクエストに対して 1 レスポンスである → 複数リソースを得るために何度もリクエストしてコネクションを貼り直す必要があり パフォーマンス上の課題がある これに対して、1.1 の次期バージョンである HTTP/2 は以下のような特徴があります。 通信時にヘッダを圧縮し使い回す省エネ設計 = 一部ステートがある バイナリベースで情報をやりとりする ストリームという概念で、1 コネクション中で Request / Response を多重化できる → 1 コネクションの中で複数リソースを並行して Request / Response できる! リソースの Server Push が可能 HTTP/2 自体が HTTP/1.1 の課題であった通信のオーバヘッドを改善する規格であることがわかりますね。また「 request / response の多重化」により、1.1 と比較してどの程度「速く」なるのかについては、以下 Akamai 社のブログサイトが参考になります。 HTTP/1.1 HTTP/2 ( request / response の多重化 ) ref. HTTP/2 を活用するパフォーマンス最適化 ADAPTIVE ACCELERATION HTTP/2 の採用事例 ref. caniuse.com 上記対応状況からも分かる通り、モダンブラウザでは一通り対応しています。実際のプロダクションでも 日本ではメルカリさん、世界的なサービスだと Twitter, Facebook, Instagram など SNS サービスや、Slack, Dropbox などが HTTP/2 に対応しているようです。 ジョブメドレーはまだ HTTP/1.1 でのサービス提供しか行っていませんが、ゆくゆくはバージョンアップ対応を行っていきたいと思っています。 周辺知識 - PWA 次に、PWA についておさらいします。PRPL は PWA の Service Worker を利用した実装パターンという話でしたが、そもそも PWA や Service Worker とはどんなものなのでしょうか。 PWA - Progressive Web Application Web プラットフォームの新機能を使って「ネイティブアプリとウェブアプリのいいとこ取りした、UX の高いウェブアプリ」という概念 ウェブアプリの特性 ( Secure, Linkable, Indexable … ) を保ちつつ、ネイティブアプリの多機能さ ( インストール、プッシュ通知、オフライン動作 … ) を最新のブラウザ機能 = JavaScript API で実現する 必ずしも SPA であったり、最新機能の全てを使っている必要はなく、「斬新的に Web 新 API でネイティブな機能を取り入れていける」というコンセプト ref. プログレッシブウェブアプリの紹介 - MDN PWA を構成する新機能たち HTTPS: HyperText Transfer Protocol Secure 、 SSL / TLS による通信の暗号化 Service Worker: Web ページで動作するスクリプトから独立したイベント駆動型の worker Cache API: Request / Response オブジェクトのストレージキャッシュ Push API / Notifications API: サーバーからアプリへの通知送信 マニフェスト: アプリストアを通さず Web アプリをホーム画面にインストール可能 ref. プログレッシブウェブアプリ - MDN 上記以外にも、PWA には様々な API ・機能が存在します。その中でも PWA の、そして PRPL アーキテクチャの中核を成す重要な機能が Service Worker です。 Service Worker とは ブラウザのバックグラウンドプロセスとして動作する Worker Web ページで動作するスクリプトとは独立して動作する サーバサイドでいうところの Worker プロセスと同じような使い方ができる ref. Service Worker の紹介 Web ページの JavaScript プロセスとは切り離された文脈で、予め登録しておいた処理を、様々なイベントに応じて発火させることができるイメージですね。 プッシュ通知など、いわゆる「ネイティブアプリのような機能」は、この Service Worker を利用することで実現しています。 PWA の採用状況 Google からの提唱当初 ( PWA も Google のプロジェクトです ) こそ、先進的すぎてなかなか受け入れられなかった PWA ですが、2020 年現在は各ブラウザの対応状況も少しずつ向上されています。 日本では SUUMO、日経電子版、一休.com、世界的なサービスだと Instagram などが PWA による Web サイトを提供しているようです。 リクルートの『SUUMO』、Android スマートフォン用サイトでプッシュ通知できる機能を実装 PWA で表示速度が 2 倍に! スピード改善を妥協しない日経電子版に学ぶ、PWA のメリット&デメリット なぜ Instagram は PWA を作ったのか? 特に、既にネイティブアプリで大成功している Instagram が、回線・端末スペックの低い新興国をターゲットとした PWA をリリースしているという点はプロダクト観点からもとても興味深いですね。 PRPL パターンの利点 さて、話を戻して PRPL パターンが HTTP/2 や Service Worker を使って、具体的にどのようにサイトパフォーマンスを向上するのか?という点を見ていきます。 Server Push + Service Worker による Pre-cache PRPL の 4 要素を、改めてもう少しわかりやすく記載してみると以下のようになります。 Push 初回コネクションで HTTP/2 Server Push で 必要リソースをまとめて Push Render 上記で受け取った HTML リソースを元に初期画面をレンダリングする Pre-cache 上記初期画面で利用されるリソースは、 Server Push により非同期的に Service Worker が Pre-cache する また、今後利用しそうな追加リソースについても、非同期・投機的に Service Worker が事前に DL 、キャッシュする Lazy load 初期画面以降で必要になった画像などのリソースを、画面スクロールなどを検知し、表示に必要になったタイミングで遅延読み込みする 上記の太字箇所を画像で説明すると、以下のようになります。 HTTP/2 ( Server Push ) HTTP/2 を活用するパフォーマンス最適化 ADAPTIVE ACCELERATION HTTP/2 の Request / Response の多重化だけを利用したケースと比較すると、「ブラウザがページを解析して、必要リソースを Request する」よりも前に「サーバが必要リソースを強制的に Push 」しているのがわかります。 この Push されたリソースを Service Worker が受け取り → キャッシュ化することで 「ページ解析が終わった時点では既に必要リソースがブラウザにキャッシュされている」 状態となり、アプリの初回起動が速くなる、というのが Push & Pre-Cache の速度改善の仕組みです。 Service Worker で必要になりそうなリソースの事前キャッシュ また、初期画面に必ず必要なリソース以外については、「このあと必要になりそう・なるはずの追加リソース」ということで、Service Worker に投機的に事前 DL → Pre-cache されることも可能です。 このあたりのキャッシュ戦略・導入事例は以下の一休さんの記事が詳しいです。 一休.com に Service Worker(Workbox)を導入しました PRPL Pattern の採用状況 さて、そんなパフォーマンスに嬉しい PRPL Pattern ですが、HTTP/2、PWA 自体の普及率も高くなくまだまだプロダクションでの採用事例は少ない印象です。 Google I/O で日経電子版が事例として紹介された話 PRPL パターンを参考にした Service Worker を使ったキャッシュ、HTTP/2 Push でのリソース配信などが採用されている ライブラリでは有名どころだと Gatsby が標準対応、当たり前だが Google の Polymer ライブラリも PRPL パターンで実装されている とはいえ、PWA 化している Web サイトであればパターンの適用はそこまで難しくありません。 また Next.js の PWA 化ライブラリ next-pwa では、Next.js 本体の Code Splitting 機能と連携した「 Service Worker での追加コード読み込み」をサポートするなど、このようなアーキテクチャパターンの潮流は今後も派生していくのかな?という気がしています。 まとめ - HTTP/2 + PWA + PRPL Pattern まとめです。 PWA とは Web プラットフォームの新機能を使った「ネイティブアプリとウェブアプリのいいとこ取りした UX の高いウェブアプリ」という概念 PRPL パターンとは スマートフォンなど回線強度・スペックの低いデバイスのために、Google が UX 向上のために提唱する PWA の設計アーキテクチャ HTTP/2, Service Worker などを使って (リソースの) Server push, Pre-cache, Lazy load を行う プロダクトで使えるのか Web サイトの PWA をする/しているのであれば、サーバの HTTP/2 化をして、リソースの Push、Pre-cache を導入するのはパフォーマンス観点で十分検討できるのでは 但し、SPA + SSR 構成のサイトでは、Next.js などフレームワークのコード分割に寄せるのが今の所無難そうではある 今回は調査のみで、プロダクトへの実践投入は行いませんでしたが、今後プロダクトの PWA 化が企画されるような場合は、ぜひ導入してみたい技術だなと感じました。 以上、ここまで読んでくださり、ありがとうございました。
アバター
こんにちは。メドレーにてジョブメドレー開発エンジニアをしています、矢野と申します。 ジョブメドレーでは、主にバックエンド ( Ruby on Rails ) の改修を担当してます 直近では 「サイトパフォーマンス改善施策」 として、Rails コードのリファクタリングによる TTFB 高速化に取り組んでました 「もう絶対にコケないのが分かってる」ビルドやテストを、手元のコンソールで何度も叩いて「わー。ちゃんと通る!」っていう時間が好きです 今回は、上記の「サイトパフォーマンス改善施策」の文脈で調査した、PWA の実装パターンである PRPL Pattern という リソース提供の設計アーキテクチャ について紹介します。 PRPL Pattern とは ref. Apply instant loading with the PRPL pattern - web.dev PRPL Pattern は、Google I/O 2016 で提案された PWA - Progressive Web Application の構築・配信のための設計アーキテクチャです。 Web サイト・アプリケーションが、回線強度やスペックが高くないスマートフォンなどのデバイスでもストレスなく機能するよう、リソース配信とアプリ起動時のパフォーマンス ( = 高速化 ) に重点を置いています。 PRPL meanings では具体的に「どうやって速くするの?」ということで、PRPL が提唱している 4 つのサイトレンダリング手法について見ていきます。 Push: <link preload> および HTTP/2 を使用して、初期 URL ルートの重要なリソースを Server Push する Render: クライアントが初期ルートをなるべく早くレンダリングする Pre-cache: 残りのルートをクライアントが Service Worker でプリキャッシュする Lazy load: クライアントはオンデマンドで残りのルートを遅延読込みして作成する PRPL は上記 4 つの頭文字をとったものですね。 PRPL は HTTP/2 の Server Push や、PWA の Service Worker など、Web プラットフォームの最新技術を駆使してサイトパフォーマンスをあげよう!というプラクティスです。 PWApps とは、最新の Web 技術を有効に活用し、漸進的 ( Progressive ) に高度なユーザー体験を提供しようとする概念です。この PWApps の概念を具体化する一つの手法として、「 PRPL 」 ( パープル ) と名付けられた開発・提供パターンが提案されました。 (中略) Web Components や、 Service Worker、 HTTP/2 Server Push といった Web の最新技術をフルに活用し、レスポンス性の高いユーザー体験を提供しようというものです。 ref. Google が新たに提唱する Progressive Web Apps の新たな開発パターン「 PRPL 」とは? 周辺知識 - HTTP/2 まずは、周辺知識からおさらいしていきます。PRPL は HTTP/2 の Server Push を利用する、という話でした。そもそも HTTP/2 とはどんなものでしょうか。 Hyper Text Transfer Protocol と呼ばれる TCP 上の通信プロトコルの次世代バージョン 普段私たちが Web サイトを閲覧する際に利用しているプロトコル HTTP/1.1 が 1997 年に策定され、2015 年にようやく /2 が標準化 Express, Apache, Nginx など各 Web サーバ、各ブラウザも対応してきている ref. HTTP の進化 現行の一般的なバージョンは HTTP/1.1 HTTP は普段私たちが Web サイトを閲覧する際に利用する通信プロトコルです。HTTP/2 はその次世代バージョンになります。HTTP/1.1 には以下のような特徴があります。 ステートレスな通信 テキストベースで情報をやりとりする 原則 1 リクエストに対して 1 レスポンスである → 複数リソースを得るために何度もリクエストしてコネクションを貼り直す必要があり パフォーマンス上の課題がある これに対して、1.1 の次期バージョンである HTTP/2 は以下のような特徴があります。 通信時にヘッダを圧縮し使い回す省エネ設計 = 一部ステートがある バイナリベースで情報をやりとりする ストリームという概念で、1 コネクション中で Request / Response を多重化できる → 1 コネクションの中で複数リソースを並行して Request / Response できる! リソースの Server Push が可能 HTTP/2 自体が HTTP/1.1 の課題であった通信のオーバヘッドを改善する規格であることがわかりますね。また「 request / response の多重化」により、1.1 と比較してどの程度「速く」なるのかについては、以下 Akamai 社のブログサイトが参考になります。 HTTP/1.1 HTTP/2 ( request / response の多重化 ) ref. HTTP/2 を活用するパフォーマンス最適化 ADAPTIVE ACCELERATION HTTP/2 の採用事例 ref. caniuse.com 上記対応状況からも分かる通り、モダンブラウザでは一通り対応しています。実際のプロダクションでも 日本ではメルカリさん、世界的なサービスだと Twitter, Facebook, Instagram など SNS サービスや、Slack, Dropbox などが HTTP/2 に対応しているようです。 ジョブメドレーはまだ HTTP/1.1 でのサービス提供しか行っていませんが、ゆくゆくはバージョンアップ対応を行っていきたいと思っています。 周辺知識 - PWA 次に、PWA についておさらいします。PRPL は PWA の Service Worker を利用した実装パターンという話でしたが、そもそも PWA や Service Worker とはどんなものなのでしょうか。 PWA - Progressive Web Application Web プラットフォームの新機能を使って「ネイティブアプリとウェブアプリのいいとこ取りした、UX の高いウェブアプリ」という概念 ウェブアプリの特性 ( Secure, Linkable, Indexable … ) を保ちつつ、ネイティブアプリの多機能さ ( インストール、プッシュ通知、オフライン動作 … ) を最新のブラウザ機能 = JavaScript API で実現する 必ずしも SPA であったり、最新機能の全てを使っている必要はなく、「斬新的に Web 新 API でネイティブな機能を取り入れていける」というコンセプト ref. プログレッシブウェブアプリの紹介 - MDN PWA を構成する新機能たち HTTPS: HyperText Transfer Protocol Secure 、 SSL / TLS による通信の暗号化 Service Worker: Web ページで動作するスクリプトから独立したイベント駆動型の worker Cache API: Request / Response オブジェクトのストレージキャッシュ Push API / Notifications API: サーバーからアプリへの通知送信 マニフェスト: アプリストアを通さず Web アプリをホーム画面にインストール可能 ref. プログレッシブウェブアプリ - MDN 上記以外にも、PWA には様々な API ・機能が存在します。その中でも PWA の、そして PRPL アーキテクチャの中核を成す重要な機能が Service Worker です。 Service Worker とは ブラウザのバックグラウンドプロセスとして動作する Worker Web ページで動作するスクリプトとは独立して動作する サーバサイドでいうところの Worker プロセスと同じような使い方ができる ref. Service Worker の紹介 Web ページの JavaScript プロセスとは切り離された文脈で、予め登録しておいた処理を、様々なイベントに応じて発火させることができるイメージですね。 プッシュ通知など、いわゆる「ネイティブアプリのような機能」は、この Service Worker を利用することで実現しています。 PWA の採用状況 Google からの提唱当初 ( PWA も Google のプロジェクトです ) こそ、先進的すぎてなかなか受け入れられなかった PWA ですが、2020 年現在は各ブラウザの対応状況も少しずつ向上されています。 日本では SUUMO、日経電子版、一休.com、世界的なサービスだと Instagram などが PWA による Web サイトを提供しているようです。 リクルートの『SUUMO』、Android スマートフォン用サイトでプッシュ通知できる機能を実装 PWA で表示速度が 2 倍に! スピード改善を妥協しない日経電子版に学ぶ、PWA のメリット&デメリット なぜ Instagram は PWA を作ったのか? 特に、既にネイティブアプリで大成功している Instagram が、回線・端末スペックの低い新興国をターゲットとした PWA をリリースしているという点はプロダクト観点からもとても興味深いですね。 PRPL パターンの利点 さて、話を戻して PRPL パターンが HTTP/2 や Service Worker を使って、具体的にどのようにサイトパフォーマンスを向上するのか?という点を見ていきます。 Server Push + Service Worker による Pre-cache PRPL の 4 要素を、改めてもう少しわかりやすく記載してみると以下のようになります。 Push 初回コネクションで HTTP/2 Server Push で 必要リソースをまとめて Push Render 上記で受け取った HTML リソースを元に初期画面をレンダリングする Pre-cache 上記初期画面で利用されるリソースは、 Server Push により非同期的に Service Worker が Pre-cache する また、今後利用しそうな追加リソースについても、非同期・投機的に Service Worker が事前に DL 、キャッシュする Lazy load 初期画面以降で必要になった画像などのリソースを、画面スクロールなどを検知し、表示に必要になったタイミングで遅延読み込みする 上記の太字箇所を画像で説明すると、以下のようになります。 HTTP/2 ( Server Push ) HTTP/2 を活用するパフォーマンス最適化 ADAPTIVE ACCELERATION HTTP/2 の Request / Response の多重化だけを利用したケースと比較すると、「ブラウザがページを解析して、必要リソースを Request する」よりも前に「サーバが必要リソースを強制的に Push 」しているのがわかります。 この Push されたリソースを Service Worker が受け取り → キャッシュ化することで 「ページ解析が終わった時点では既に必要リソースがブラウザにキャッシュされている」 状態となり、アプリの初回起動が速くなる、というのが Push & Pre-Cache の速度改善の仕組みです。 Service Worker で必要になりそうなリソースの事前キャッシュ また、初期画面に必ず必要なリソース以外については、「このあと必要になりそう・なるはずの追加リソース」ということで、Service Worker に投機的に事前 DL → Pre-cache されることも可能です。 このあたりのキャッシュ戦略・導入事例は以下の一休さんの記事が詳しいです。 一休.com に Service Worker(Workbox)を導入しました PRPL Pattern の採用状況 さて、そんなパフォーマンスに嬉しい PRPL Pattern ですが、HTTP/2、PWA 自体の普及率も高くなくまだまだプロダクションでの採用事例は少ない印象です。 Google I/O で日経電子版が事例として紹介された話 PRPL パターンを参考にした Service Worker を使ったキャッシュ、HTTP/2 Push でのリソース配信などが採用されている ライブラリでは有名どころだと Gatsby が標準対応、当たり前だが Google の Polymer ライブラリも PRPL パターンで実装されている とはいえ、PWA 化している Web サイトであればパターンの適用はそこまで難しくありません。 また Next.js の PWA 化ライブラリ next-pwa では、Next.js 本体の Code Splitting 機能と連携した「 Service Worker での追加コード読み込み」をサポートするなど、このようなアーキテクチャパターンの潮流は今後も派生していくのかな?という気がしています。 まとめ - HTTP/2 + PWA + PRPL Pattern まとめです。 PWA とは Web プラットフォームの新機能を使った「ネイティブアプリとウェブアプリのいいとこ取りした UX の高いウェブアプリ」という概念 PRPL パターンとは スマートフォンなど回線強度・スペックの低いデバイスのために、Google が UX 向上のために提唱する PWA の設計アーキテクチャ HTTP/2, Service Worker などを使って (リソースの) Server push, Pre-cache, Lazy load を行う プロダクトで使えるのか Web サイトの PWA をする/しているのであれば、サーバの HTTP/2 化をして、リソースの Push、Pre-cache を導入するのはパフォーマンス観点で十分検討できるのでは 但し、SPA + SSR 構成のサイトでは、Next.js などフレームワークのコード分割に寄せるのが今の所無難そうではある 今回は調査のみで、プロダクトへの実践投入は行いませんでしたが、今後プロダクトの PWA 化が企画されるような場合は、ぜひ導入してみたい技術だなと感じました。 以上、ここまで読んでくださり、ありがとうございました。
アバター
株式会社メドレーのエンジニアの阪本です。 緊急事態宣言も開け、普段の生活を取り戻しつつあるこの時期、 皆さんはいかがお過ごしでしょうか? 私は野球観戦(虎党)を毎日の楽しみとしています。 今年はコロナ渦の影響で開幕予定が遅延したものの、自粛期間を経て 6 月中旬にめでたくシーズン開幕を迎えることができました。 ここまでの「長い冬」が明け、テレビをつけると野球が見られる。 これで私自身も 2020 年が開幕したなと実感しています。 今回は、私がインフラ開発時に直面した問題と解決までの事例について紹介させて頂きます。 背景 私はジョブメドレーのサービス開発を行っています。 このシステムは多くの機能で構成された大規模なもので、AWS の Elastic Container Service(以下 ECS)にて稼働しています。 このシステムに対し既存機能のリプレース案件に携わる機会がありました。 現在のシステムは多くの時間をかけて多くの機能を実装した結果、かなり大きなコードとなっています。 これにより、一つの変更が及ぼす影響が甚大なものになり得る状況だったため、リプレース対象の機能を新システムとして別アプリケーションに切り出して開発することにしました。 しかし、別システムとして一部の機能を切り出すものの、この機能は 既存システムとの連携が必要となります。 そのため、この連携をシステム間の API リクエストで実現することにしました。 課題 ここで1つの問題が発生しました。 システム間の通信が必要になりましたが、お互い ECS サービスで分離した構成となるため このままではアドレスの解決が出来ないことに気づきました。 同一 ECS サービス内でかつ、ネットワークモードが awsvpc モードであれば ポート番号を分ける事により相互でアクセスが可能であるものの 異なるサービスであればポート以前にアドレス解決ができません。 そのため、何らかの手段を持ってお互いの場所を認識できる状態にする必要があります。 そこで、これを実現できる幾つかの方法を検討しました。 アプローチ その1 全て1つの ECS のサービスにまとめる 上記の通り、既存システムが動いている ECS サービス/タスクに新システム(のコンテナ)を全て混ぜる方法です。 この場合、全てのポートを個別に割り振ることで 127.0.0.1:port によるアクセスが可能となるため 相互のリクエストも実現できることになります。 ただ、インフラ的には2つのシステムが1つの塊として構成される事になるため デプロイの単位やスケールの単位を常に双方共有することになります。 こうなると、せっかくアプリケーションを分けたにも関わらず 運用の部分では何もメリットを得られないどころか制約が増えただけのようになりそうなのが問題です。 その2 内部 Application Load Balancer を経由する VPC 内部に internal な Application Load Balancer(以下 ALB) を設置し、接続先となる既存システムを TargetGroup に登録します。 この方法であれば、ALB のエンドポイントに向けてリクエストすることで配下の既存システムにアクセスする経路が確保できます。 また ECS サービスと TargetGroup が紐づくことにより既存システム側のデプロイやスケールが自動的に ALB 側にも連動することになるため、新システム側は既存システムのステータスを意識する必要は少なくなります。 これだと不自然な点も無くアプリケーション間の通信経路も確保できると期待しましたが・・・新たに問題が発生しました。 検証時に ALB/TargetGroup を新規作成。 ECS サービスについては 後付けで TargetGroup 脱着はできない 複数 TargetGroup の付与は AWS コンソールでは対応していない といった理由のために AWS CLI での作成作業を行ったのですが、下記エラーが発生してしまいました。 An error occurred (InvalidParameterException) when calling the CreateService operation: load balancers can have at most 5 items. これは AWS による制限で、1 つの ECS サービスに関連付けることのできる TargetGroup は最大 5 つまでという事を表しています。 つまり既存システムは多くの機能やコンテナが同居している ECS サービスとなっていたため、既に TargetGroup が 5 つ存在しており上限に達していたのです。 サービスで使用するロードバランサーを表すロードバランサーオブジェクト。Application Load Balancer または Network Load Balancer を使用するサービスの場合、サービスにアタッチできる 5 つのターゲットグループの制限があります。 Amazon ECS サービス定義パラメータ - Amazon Elastic Container Service Amazon ECS サービスの実行方法を定義するサービス定義パラメータについて説明します。 docs.aws.amazon.com この方法を取るなら不要な TargetGroup を削るかまとめるかの手を打つ必要がありますが、 周辺環境に対する影響があまりにも大きい為に現実的ではありませんでした。 そのため、新たな選択肢を探すことにしました。 その3 Amazon ECS サービスディスカバリを使用する そんな中、ECS の機能としてサービスディスカバリ(サービス検出)というものを見つけました。 Amazon ECS サービスディスカバリ | Amazon Web Services Amazon ECS でサービスディスカバリがサポートされました。これにより、ECS サービスが A […] aws.amazon.com これは ECS サービスと Route53 内部ホスト空間を紐付ける機能です。 また ECS サービスの起動・停止・スケールといった対象が変動した場合にも、自動的にホスト空間のレコードを登録/解除し最新の状態に追従してくれるものです。 この場合、別々のサービス間でもお互い相手の名称を把握することができる上、 TargetGroup も新規に必要としないため、今回のニーズに適した方法になりそうです。 導入してみた結果 試しに ECS サービスにサービスディスカバリを導入し、疎通できるか試してみます。 既に存在するサービスに後付でのサービスディスカバリは出来ないため、新規にサービスを作成 することになります。 今回は初めてのサービスディスカバリとなるので、名前空間も同時に作成することになります。 ひとまず名前空間を「 medley-blog.local 」、サービス検出名を「 service-discovery 」としてみます。 このまま ECS サービスを作成すると、Route 53 にて新たな名前空間「 medley-blog.local 」が作成されていることが確認できます。 この状態でサービスのタスクを 1 つ起動ししばらく待つと、 サービス検出名.名前空間 となる service-discovery.medley-blog.local に A レコードが追加されています。 このレコードに紐づく IP アドレスこそ、ECS タスクに紐付けられている IP アドレスになります。 あとはこの名称で別環境から疎通できるか試してみます。 curl コマンドで service-discovery.medley-blog.local で通信してみると、見事にレスポンスを受け取ることが出来ました。 ※ここでは検証のため、接続先アプリケーションは Nginx コンテナを配置しています これにより、異なる ECS サービス間での通信を実現することができました。 今後の予定 現段階では検証段階のため評価環境への導入のみとなりますが、今の所は大きな問題も発生せず順調に稼働しています。 このまま特に問題無く稼働できれば、本番環境への導入も目指したいと思います。 さいごに メドレーのエンジニアは大小問わず課題に対して真摯に向き合い、試行錯誤し、突破口を開く取り組みを常に続けています。 そんな我々と一緒に働きたいと思った方、まずは下記リンクからご応募いただきカジュアルにお話しませんか? www.medley.jp www.medley.jp
アバター
株式会社メドレーのエンジニアの阪本です。 緊急事態宣言も開け、普段の生活を取り戻しつつあるこの時期、 皆さんはいかがお過ごしでしょうか? 私は野球観戦(虎党)を毎日の楽しみとしています。 今年はコロナ渦の影響で開幕予定が遅延したものの、自粛期間を経て 6 月中旬にめでたくシーズン開幕を迎えることができました。 ここまでの「長い冬」が明け、テレビをつけると野球が見られる。 これで私自身も 2020 年が開幕したなと実感しています。 今回は、私がインフラ開発時に直面した問題と解決までの事例について紹介させて頂きます。 背景 私はジョブメドレーのサービス開発を行っています。 このシステムは多くの機能で構成された大規模なもので、AWS の Elastic Container Service(以下 ECS)にて稼働しています。 このシステムに対し既存機能のリプレース案件に携わる機会がありました。 現在のシステムは多くの時間をかけて多くの機能を実装した結果、かなり大きなコードとなっています。 これにより、一つの変更が及ぼす影響が甚大なものになり得る状況だったため、リプレース対象の機能を新システムとして別アプリケーションに切り出して開発することにしました。 しかし、別システムとして一部の機能を切り出すものの、この機能は 既存システムとの連携が必要となります。 そのため、この連携をシステム間の API リクエストで実現することにしました。 課題 ここで1つの問題が発生しました。 システム間の通信が必要になりましたが、お互い ECS サービスで分離した構成となるため このままではアドレスの解決が出来ないことに気づきました。 同一 ECS サービス内でかつ、ネットワークモードが awsvpc モードであれば ポート番号を分ける事により相互でアクセスが可能であるものの 異なるサービスであればポート以前にアドレス解決ができません。 そのため、何らかの手段を持ってお互いの場所を認識できる状態にする必要があります。 そこで、これを実現できる幾つかの方法を検討しました。 アプローチ その1 全て1つの ECS のサービスにまとめる 上記の通り、既存システムが動いている ECS サービス/タスクに新システム(のコンテナ)を全て混ぜる方法です。 この場合、全てのポートを個別に割り振ることで 127.0.0.1:port によるアクセスが可能となるため 相互のリクエストも実現できることになります。 ただ、インフラ的には2つのシステムが1つの塊として構成される事になるため デプロイの単位やスケールの単位を常に双方共有することになります。 こうなると、せっかくアプリケーションを分けたにも関わらず 運用の部分では何もメリットを得られないどころか制約が増えただけのようになりそうなのが問題です。 その2 内部 Application Load Balancer を経由する VPC 内部に internal な Application Load Balancer(以下 ALB) を設置し、接続先となる既存システムを TargetGroup に登録します。 この方法であれば、ALB のエンドポイントに向けてリクエストすることで配下の既存システムにアクセスする経路が確保できます。 また ECS サービスと TargetGroup が紐づくことにより既存システム側のデプロイやスケールが自動的に ALB 側にも連動することになるため、新システム側は既存システムのステータスを意識する必要は少なくなります。 これだと不自然な点も無くアプリケーション間の通信経路も確保できると期待しましたが・・・新たに問題が発生しました。 検証時に ALB/TargetGroup を新規作成。 ECS サービスについては 後付けで TargetGroup 脱着はできない 複数 TargetGroup の付与は AWS コンソールでは対応していない といった理由のために AWS CLI での作成作業を行ったのですが、下記エラーが発生してしまいました。 An error occurred (InvalidParameterException) when calling the CreateService operation: load balancers can have at most 5 items. これは AWS による制限で、1 つの ECS サービスに関連付けることのできる TargetGroup は最大 5 つまでという事を表しています。 つまり既存システムは多くの機能やコンテナが同居している ECS サービスとなっていたため、既に TargetGroup が 5 つ存在しており上限に達していたのです。 サービスで使用するロードバランサーを表すロードバランサーオブジェクト。Application Load Balancer または Network Load Balancer を使用するサービスの場合、サービスにアタッチできる 5 つのターゲットグループの制限があります。 Amazon ECS サービス定義パラメータ - Amazon Elastic Container Service Amazon ECS サービスの実行方法を定義するサービス定義パラメータについて説明します。 docs.aws.amazon.com この方法を取るなら不要な TargetGroup を削るかまとめるかの手を打つ必要がありますが、 周辺環境に対する影響があまりにも大きい為に現実的ではありませんでした。 そのため、新たな選択肢を探すことにしました。 その3 Amazon ECS サービスディスカバリを使用する そんな中、ECS の機能としてサービスディスカバリ(サービス検出)というものを見つけました。 Amazon ECS サービスディスカバリ | Amazon Web Services Amazon ECS でサービスディスカバリがサポートされました。これにより、ECS サービスが A […] aws.amazon.com これは ECS サービスと Route53 内部ホスト空間を紐付ける機能です。 また ECS サービスの起動・停止・スケールといった対象が変動した場合にも、自動的にホスト空間のレコードを登録/解除し最新の状態に追従してくれるものです。 この場合、別々のサービス間でもお互い相手の名称を把握することができる上、 TargetGroup も新規に必要としないため、今回のニーズに適した方法になりそうです。 導入してみた結果 試しに ECS サービスにサービスディスカバリを導入し、疎通できるか試してみます。 既に存在するサービスに後付でのサービスディスカバリは出来ないため、新規にサービスを作成 することになります。 今回は初めてのサービスディスカバリとなるので、名前空間も同時に作成することになります。 ひとまず名前空間を「 medley-blog.local 」、サービス検出名を「 service-discovery 」としてみます。 このまま ECS サービスを作成すると、Route 53 にて新たな名前空間「 medley-blog.local 」が作成されていることが確認できます。 この状態でサービスのタスクを 1 つ起動ししばらく待つと、 サービス検出名.名前空間 となる service-discovery.medley-blog.local に A レコードが追加されています。 このレコードに紐づく IP アドレスこそ、ECS タスクに紐付けられている IP アドレスになります。 あとはこの名称で別環境から疎通できるか試してみます。 curl コマンドで service-discovery.medley-blog.local で通信してみると、見事にレスポンスを受け取ることが出来ました。 ※ここでは検証のため、接続先アプリケーションは Nginx コンテナを配置しています これにより、異なる ECS サービス間での通信を実現することができました。 今後の予定 現段階では検証段階のため評価環境への導入のみとなりますが、今の所は大きな問題も発生せず順調に稼働しています。 このまま特に問題無く稼働できれば、本番環境への導入も目指したいと思います。 さいごに メドレーのエンジニアは大小問わず課題に対して真摯に向き合い、試行錯誤し、突破口を開く取り組みを常に続けています。 そんな我々と一緒に働きたいと思った方、まずは下記リンクからご応募いただきカジュアルにお話しませんか? www.medley.jp www.medley.jp
アバター
株式会社メドレーのエンジニアの阪本です。 緊急事態宣言も開け、普段の生活を取り戻しつつあるこの時期、 皆さんはいかがお過ごしでしょうか? 私は野球観戦(虎党)を毎日の楽しみとしています。 今年はコロナ渦の影響で開幕予定が遅延したものの、自粛期間を経て 6 月中旬にめでたくシーズン開幕を迎えることができました。 ここまでの「長い冬」が明け、テレビをつけると野球が見られる。 これで私自身も 2020 年が開幕したなと実感しています。 今回は、私がインフラ開発時に直面した問題と解決までの事例について紹介させて頂きます。 背景 私はジョブメドレーのサービス開発を行っています。 このシステムは多くの機能で構成された大規模なもので、AWS の Elastic Container Service(以下 ECS)にて稼働しています。 このシステムに対し既存機能のリプレース案件に携わる機会がありました。 現在のシステムは多くの時間をかけて多くの機能を実装した結果、かなり大きなコードとなっています。 これにより、一つの変更が及ぼす影響が甚大なものになり得る状況だったため、リプレース対象の機能を新システムとして別アプリケーションに切り出して開発することにしました。 しかし、別システムとして一部の機能を切り出すものの、この機能は 既存システムとの連携が必要となります。 そのため、この連携をシステム間の API リクエストで実現することにしました。 課題 ここで1つの問題が発生しました。 システム間の通信が必要になりましたが、お互い ECS サービスで分離した構成となるため このままではアドレスの解決が出来ないことに気づきました。 同一 ECS サービス内でかつ、ネットワークモードが awsvpc モードであれば ポート番号を分ける事により相互でアクセスが可能であるものの 異なるサービスであればポート以前にアドレス解決ができません。 そのため、何らかの手段を持ってお互いの場所を認識できる状態にする必要があります。 そこで、これを実現できる幾つかの方法を検討しました。 アプローチ その1 全て1つの ECS のサービスにまとめる 上記の通り、既存システムが動いている ECS サービス/タスクに新システム(のコンテナ)を全て混ぜる方法です。 この場合、全てのポートを個別に割り振ることで 127.0.0.1:port によるアクセスが可能となるため 相互のリクエストも実現できることになります。 ただ、インフラ的には2つのシステムが1つの塊として構成される事になるため デプロイの単位やスケールの単位を常に双方共有することになります。 こうなると、せっかくアプリケーションを分けたにも関わらず 運用の部分では何もメリットを得られないどころか制約が増えただけのようになりそうなのが問題です。 その2 内部 Application Load Balancer を経由する VPC 内部に internal な Application Load Balancer(以下 ALB) を設置し、接続先となる既存システムを TargetGroup に登録します。 この方法であれば、ALB のエンドポイントに向けてリクエストすることで配下の既存システムにアクセスする経路が確保できます。 また ECS サービスと TargetGroup が紐づくことにより既存システム側のデプロイやスケールが自動的に ALB 側にも連動することになるため、新システム側は既存システムのステータスを意識する必要は少なくなります。 これだと不自然な点も無くアプリケーション間の通信経路も確保できると期待しましたが・・・新たに問題が発生しました。 検証時に ALB/TargetGroup を新規作成。 ECS サービスについては 後付けで TargetGroup 脱着はできない 複数 TargetGroup の付与は AWS コンソールでは対応していない といった理由のために AWS CLI での作成作業を行ったのですが、下記エラーが発生してしまいました。 An error occurred (InvalidParameterException) when calling the CreateService operation: load balancers can have at most 5 items. これは AWS による制限で、1 つの ECS サービスに関連付けることのできる TargetGroup は最大 5 つまでという事を表しています。 つまり既存システムは多くの機能やコンテナが同居している ECS サービスとなっていたため、既に TargetGroup が 5 つ存在しており上限に達していたのです。 サービスで使用するロードバランサーを表すロードバランサーオブジェクト。Application Load Balancer または Network Load Balancer を使用するサービスの場合、サービスにアタッチできる 5 つのターゲットグループの制限があります。 Amazon ECS サービス定義パラメータ - Amazon Elastic Container Service Amazon ECS サービスの実行方法を定義するサービス定義パラメータについて説明します。 docs.aws.amazon.com この方法を取るなら不要な TargetGroup を削るかまとめるかの手を打つ必要がありますが、 周辺環境に対する影響があまりにも大きい為に現実的ではありませんでした。 そのため、新たな選択肢を探すことにしました。 その3 Amazon ECS サービスディスカバリを使用する そんな中、ECS の機能としてサービスディスカバリ(サービス検出)というものを見つけました。 Amazon ECS サービスディスカバリ | Amazon Web Services Amazon ECS でサービスディスカバリがサポートされました。これにより、ECS サービスが A […] aws.amazon.com これは ECS サービスと Route53 内部ホスト空間を紐付ける機能です。 また ECS サービスの起動・停止・スケールといった対象が変動した場合にも、自動的にホスト空間のレコードを登録/解除し最新の状態に追従してくれるものです。 この場合、別々のサービス間でもお互い相手の名称を把握することができる上、 TargetGroup も新規に必要としないため、今回のニーズに適した方法になりそうです。 導入してみた結果 試しに ECS サービスにサービスディスカバリを導入し、疎通できるか試してみます。 既に存在するサービスに後付でのサービスディスカバリは出来ないため、新規にサービスを作成 することになります。 今回は初めてのサービスディスカバリとなるので、名前空間も同時に作成することになります。 ひとまず名前空間を「 medley-blog.local 」、サービス検出名を「 service-discovery 」としてみます。 このまま ECS サービスを作成すると、Route 53 にて新たな名前空間「 medley-blog.local 」が作成されていることが確認できます。 この状態でサービスのタスクを 1 つ起動ししばらく待つと、 サービス検出名.名前空間 となる service-discovery.medley-blog.local に A レコードが追加されています。 このレコードに紐づく IP アドレスこそ、ECS タスクに紐付けられている IP アドレスになります。 あとはこの名称で別環境から疎通できるか試してみます。 curl コマンドで service-discovery.medley-blog.local で通信してみると、見事にレスポンスを受け取ることが出来ました。 ※ここでは検証のため、接続先アプリケーションは Nginx コンテナを配置しています これにより、異なる ECS サービス間での通信を実現することができました。 今後の予定 現段階では検証段階のため評価環境への導入のみとなりますが、今の所は大きな問題も発生せず順調に稼働しています。 このまま特に問題無く稼働できれば、本番環境への導入も目指したいと思います。 さいごに メドレーのエンジニアは大小問わず課題に対して真摯に向き合い、試行錯誤し、突破口を開く取り組みを常に続けています。 そんな我々と一緒に働きたいと思った方、まずは下記リンクからご応募いただきカジュアルにお話しませんか? www.medley.jp www.medley.jp
アバター
株式会社メドレーのエンジニアの阪本です。 緊急事態宣言も開け、普段の生活を取り戻しつつあるこの時期、 皆さんはいかがお過ごしでしょうか? 私は野球観戦(虎党)を毎日の楽しみとしています。 今年はコロナ渦の影響で開幕予定が遅延したものの、自粛期間を経て 6 月中旬にめでたくシーズン開幕を迎えることができました。 ここまでの「長い冬」が明け、テレビをつけると野球が見られる。 これで私自身も 2020 年が開幕したなと実感しています。 今回は、私がインフラ開発時に直面した問題と解決までの事例について紹介させて頂きます。 背景 私はジョブメドレーのサービス開発を行っています。 このシステムは多くの機能で構成された大規模なもので、AWS の Elastic Container Service(以下 ECS)にて稼働しています。 このシステムに対し既存機能のリプレース案件に携わる機会がありました。 現在のシステムは多くの時間をかけて多くの機能を実装した結果、かなり大きなコードとなっています。 これにより、一つの変更が及ぼす影響が甚大なものになり得る状況だったため、リプレース対象の機能を新システムとして別アプリケーションに切り出して開発することにしました。 しかし、別システムとして一部の機能を切り出すものの、この機能は 既存システムとの連携が必要となります。 そのため、この連携をシステム間の API リクエストで実現することにしました。 課題 ここで1つの問題が発生しました。 システム間の通信が必要になりましたが、お互い ECS サービスで分離した構成となるため このままではアドレスの解決が出来ないことに気づきました。 同一 ECS サービス内でかつ、ネットワークモードが awsvpc モードであれば ポート番号を分ける事により相互でアクセスが可能であるものの 異なるサービスであればポート以前にアドレス解決ができません。 そのため、何らかの手段を持ってお互いの場所を認識できる状態にする必要があります。 そこで、これを実現できる幾つかの方法を検討しました。 アプローチ その1 全て1つの ECS のサービスにまとめる 上記の通り、既存システムが動いている ECS サービス/タスクに新システム(のコンテナ)を全て混ぜる方法です。 この場合、全てのポートを個別に割り振ることで 127.0.0.1:port によるアクセスが可能となるため 相互のリクエストも実現できることになります。 ただ、インフラ的には2つのシステムが1つの塊として構成される事になるため デプロイの単位やスケールの単位を常に双方共有することになります。 こうなると、せっかくアプリケーションを分けたにも関わらず 運用の部分では何もメリットを得られないどころか制約が増えただけのようになりそうなのが問題です。 その2 内部 Application Load Balancer を経由する VPC 内部に internal な Application Load Balancer(以下 ALB) を設置し、接続先となる既存システムを TargetGroup に登録します。 この方法であれば、ALB のエンドポイントに向けてリクエストすることで配下の既存システムにアクセスする経路が確保できます。 また ECS サービスと TargetGroup が紐づくことにより既存システム側のデプロイやスケールが自動的に ALB 側にも連動することになるため、新システム側は既存システムのステータスを意識する必要は少なくなります。 これだと不自然な点も無くアプリケーション間の通信経路も確保できると期待しましたが・・・新たに問題が発生しました。 検証時に ALB/TargetGroup を新規作成。 ECS サービスについては 後付けで TargetGroup 脱着はできない 複数 TargetGroup の付与は AWS コンソールでは対応していない といった理由のために AWS CLI での作成作業を行ったのですが、下記エラーが発生してしまいました。 An error occurred (InvalidParameterException) when calling the CreateService operation: load balancers can have at most 5 items. これは AWS による制限で、1 つの ECS サービスに関連付けることのできる TargetGroup は最大 5 つまでという事を表しています。 つまり既存システムは多くの機能やコンテナが同居している ECS サービスとなっていたため、既に TargetGroup が 5 つ存在しており上限に達していたのです。 サービスで使用するロードバランサーを表すロードバランサーオブジェクト。Application Load Balancer または Network Load Balancer を使用するサービスの場合、サービスにアタッチできる 5 つのターゲットグループの制限があります。 Amazon ECS サービス定義パラメータ - Amazon Elastic Container Service Amazon ECS サービスの実行方法を定義するサービス定義パラメータについて説明します。 docs.aws.amazon.com この方法を取るなら不要な TargetGroup を削るかまとめるかの手を打つ必要がありますが、 周辺環境に対する影響があまりにも大きい為に現実的ではありませんでした。 そのため、新たな選択肢を探すことにしました。 その3 Amazon ECS サービスディスカバリを使用する そんな中、ECS の機能としてサービスディスカバリ(サービス検出)というものを見つけました。 Amazon ECS サービスディスカバリ | Amazon Web Services Amazon ECS でサービスディスカバリがサポートされました。これにより、ECS サービスが A […] aws.amazon.com これは ECS サービスと Route53 内部ホスト空間を紐付ける機能です。 また ECS サービスの起動・停止・スケールといった対象が変動した場合にも、自動的にホスト空間のレコードを登録/解除し最新の状態に追従してくれるものです。 この場合、別々のサービス間でもお互い相手の名称を把握することができる上、 TargetGroup も新規に必要としないため、今回のニーズに適した方法になりそうです。 導入してみた結果 試しに ECS サービスにサービスディスカバリを導入し、疎通できるか試してみます。 既に存在するサービスに後付でのサービスディスカバリは出来ないため、新規にサービスを作成 することになります。 今回は初めてのサービスディスカバリとなるので、名前空間も同時に作成することになります。 ひとまず名前空間を「 medley-blog.local 」、サービス検出名を「 service-discovery 」としてみます。 このまま ECS サービスを作成すると、Route 53 にて新たな名前空間「 medley-blog.local 」が作成されていることが確認できます。 この状態でサービスのタスクを 1 つ起動ししばらく待つと、 サービス検出名.名前空間 となる service-discovery.medley-blog.local に A レコードが追加されています。 このレコードに紐づく IP アドレスこそ、ECS タスクに紐付けられている IP アドレスになります。 あとはこの名称で別環境から疎通できるか試してみます。 curl コマンドで service-discovery.medley-blog.local で通信してみると、見事にレスポンスを受け取ることが出来ました。 ※ここでは検証のため、接続先アプリケーションは Nginx コンテナを配置しています これにより、異なる ECS サービス間での通信を実現することができました。 今後の予定 現段階では検証段階のため評価環境への導入のみとなりますが、今の所は大きな問題も発生せず順調に稼働しています。 このまま特に問題無く稼働できれば、本番環境への導入も目指したいと思います。 さいごに メドレーのエンジニアは大小問わず課題に対して真摯に向き合い、試行錯誤し、突破口を開く取り組みを常に続けています。 そんな我々と一緒に働きたいと思った方、まずは下記リンクからご応募いただきカジュアルにお話しませんか? www.medley.jp www.medley.jp
アバター
株式会社メドレーのエンジニアの阪本です。 緊急事態宣言も開け、普段の生活を取り戻しつつあるこの時期、 皆さんはいかがお過ごしでしょうか? 私は野球観戦(虎党)を毎日の楽しみとしています。 今年はコロナ渦の影響で開幕予定が遅延したものの、自粛期間を経て 6 月中旬にめでたくシーズン開幕を迎えることができました。 ここまでの「長い冬」が明け、テレビをつけると野球が見られる。 これで私自身も 2020 年が開幕したなと実感しています。 今回は、私がインフラ開発時に直面した問題と解決までの事例について紹介させて頂きます。 背景 私はジョブメドレーのサービス開発を行っています。 このシステムは多くの機能で構成された大規模なもので、AWS の Elastic Container Service(以下 ECS)にて稼働しています。 このシステムに対し既存機能のリプレース案件に携わる機会がありました。 現在のシステムは多くの時間をかけて多くの機能を実装した結果、かなり大きなコードとなっています。 これにより、一つの変更が及ぼす影響が甚大なものになり得る状況だったため、リプレース対象の機能を新システムとして別アプリケーションに切り出して開発することにしました。 しかし、別システムとして一部の機能を切り出すものの、この機能は 既存システムとの連携が必要となります。 そのため、この連携をシステム間の API リクエストで実現することにしました。 課題 ここで1つの問題が発生しました。 システム間の通信が必要になりましたが、お互い ECS サービスで分離した構成となるため このままではアドレスの解決が出来ないことに気づきました。 同一 ECS サービス内でかつ、ネットワークモードが awsvpc モードであれば ポート番号を分ける事により相互でアクセスが可能であるものの 異なるサービスであればポート以前にアドレス解決ができません。 そのため、何らかの手段を持ってお互いの場所を認識できる状態にする必要があります。 そこで、これを実現できる幾つかの方法を検討しました。 アプローチ その1 全て1つの ECS のサービスにまとめる 上記の通り、既存システムが動いている ECS サービス/タスクに新システム(のコンテナ)を全て混ぜる方法です。 この場合、全てのポートを個別に割り振ることで 127.0.0.1:port によるアクセスが可能となるため 相互のリクエストも実現できることになります。 ただ、インフラ的には2つのシステムが1つの塊として構成される事になるため デプロイの単位やスケールの単位を常に双方共有することになります。 こうなると、せっかくアプリケーションを分けたにも関わらず 運用の部分では何もメリットを得られないどころか制約が増えただけのようになりそうなのが問題です。 その2 内部 Application Load Balancer を経由する VPC 内部に internal な Application Load Balancer(以下 ALB) を設置し、接続先となる既存システムを TargetGroup に登録します。 この方法であれば、ALB のエンドポイントに向けてリクエストすることで配下の既存システムにアクセスする経路が確保できます。 また ECS サービスと TargetGroup が紐づくことにより既存システム側のデプロイやスケールが自動的に ALB 側にも連動することになるため、新システム側は既存システムのステータスを意識する必要は少なくなります。 これだと不自然な点も無くアプリケーション間の通信経路も確保できると期待しましたが・・・新たに問題が発生しました。 検証時に ALB/TargetGroup を新規作成。 ECS サービスについては 後付けで TargetGroup 脱着はできない 複数 TargetGroup の付与は AWS コンソールでは対応していない といった理由のために AWS CLI での作成作業を行ったのですが、下記エラーが発生してしまいました。 An error occurred (InvalidParameterException) when calling the CreateService operation: load balancers can have at most 5 items. これは AWS による制限で、1 つの ECS サービスに関連付けることのできる TargetGroup は最大 5 つまでという事を表しています。 つまり既存システムは多くの機能やコンテナが同居している ECS サービスとなっていたため、既に TargetGroup が 5 つ存在しており上限に達していたのです。 サービスで使用するロードバランサーを表すロードバランサーオブジェクト。Application Load Balancer または Network Load Balancer を使用するサービスの場合、サービスにアタッチできる 5 つのターゲットグループの制限があります。 https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/service_definition_parameters.html この方法を取るなら不要な TargetGroup を削るかまとめるかの手を打つ必要がありますが、 周辺環境に対する影響があまりにも大きい為に現実的ではありませんでした。 そのため、新たな選択肢を探すことにしました。 その3 Amazon ECS サービスディスカバリを使用する そんな中、ECS の機能としてサービスディスカバリ(サービス検出)というものを見つけました。 https://aws.amazon.com/jp/blogs/news/amazon-ecs-service-discovery/ これは ECS サービスと Route53 内部ホスト空間を紐付ける機能です。 また ECS サービスの起動・停止・スケールといった対象が変動した場合にも、自動的にホスト空間のレコードを登録/解除し最新の状態に追従してくれるものです。 この場合、別々のサービス間でもお互い相手の名称を把握することができる上、 TargetGroup も新規に必要としないため、今回のニーズに適した方法になりそうです。 導入してみた結果 試しに ECS サービスにサービスディスカバリを導入し、疎通できるか試してみます。 既に存在するサービスに後付でのサービスディスカバリは出来ないため、新規にサービスを作成 することになります。 今回は初めてのサービスディスカバリとなるので、名前空間も同時に作成することになります。 ひとまず名前空間を「 medley-blog.local 」、サービス検出名を「 service-discovery 」としてみます。 このまま ECS サービスを作成すると、Route 53 にて新たな名前空間「 medley-blog.local 」が作成されていることが確認できます。 この状態でサービスのタスクを 1 つ起動ししばらく待つと、 サービス検出名.名前空間 となる service-discovery.medley-blog.local に A レコードが追加されています。 このレコードに紐づく IP アドレスこそ、ECS タスクに紐付けられている IP アドレスになります。 あとはこの名称で別環境から疎通できるか試してみます。 curl コマンドで service-discovery.medley-blog.local で通信してみると、見事にレスポンスを受け取ることが出来ました。 ※ここでは検証のため、接続先アプリケーションは Nginx コンテナを配置しています これにより、異なる ECS サービス間での通信を実現することができました。 今後の予定 現段階では検証段階のため評価環境への導入のみとなりますが、今の所は大きな問題も発生せず順調に稼働しています。 このまま特に問題無く稼働できれば、本番環境への導入も目指したいと思います。 さいごに メドレーのエンジニアは大小問わず課題に対して真摯に向き合い、試行錯誤し、突破口を開く取り組みを常に続けています。 そんな我々と一緒に働きたいと思った方、まずは下記リンクからご応募いただきカジュアルにお話しませんか? https://www.medley.jp/jobs/engineer1.html
アバター
株式会社メドレーのエンジニアの阪本です。 緊急事態宣言も開け、普段の生活を取り戻しつつあるこの時期、 皆さんはいかがお過ごしでしょうか? 私は野球観戦(虎党)を毎日の楽しみとしています。 今年はコロナ渦の影響で開幕予定が遅延したものの、自粛期間を経て 6 月中旬にめでたくシーズン開幕を迎えることができました。 ここまでの「長い冬」が明け、テレビをつけると野球が見られる。 これで私自身も 2020 年が開幕したなと実感しています。 今回は、私がインフラ開発時に直面した問題と解決までの事例について紹介させて頂きます。 背景 私はジョブメドレーのサービス開発を行っています。 このシステムは多くの機能で構成された大規模なもので、AWS の Elastic Container Service(以下 ECS)にて稼働しています。 このシステムに対し既存機能のリプレース案件に携わる機会がありました。 現在のシステムは多くの時間をかけて多くの機能を実装した結果、かなり大きなコードとなっています。 これにより、一つの変更が及ぼす影響が甚大なものになり得る状況だったため、リプレース対象の機能を新システムとして別アプリケーションに切り出して開発することにしました。 しかし、別システムとして一部の機能を切り出すものの、この機能は 既存システムとの連携が必要となります。 そのため、この連携をシステム間の API リクエストで実現することにしました。 課題 ここで1つの問題が発生しました。 システム間の通信が必要になりましたが、お互い ECS サービスで分離した構成となるため このままではアドレスの解決が出来ないことに気づきました。 同一 ECS サービス内でかつ、ネットワークモードが awsvpc モードであれば ポート番号を分ける事により相互でアクセスが可能であるものの 異なるサービスであればポート以前にアドレス解決ができません。 そのため、何らかの手段を持ってお互いの場所を認識できる状態にする必要があります。 そこで、これを実現できる幾つかの方法を検討しました。 アプローチ その1 全て1つの ECS のサービスにまとめる 上記の通り、既存システムが動いている ECS サービス/タスクに新システム(のコンテナ)を全て混ぜる方法です。 この場合、全てのポートを個別に割り振ることで 127.0.0.1:port によるアクセスが可能となるため 相互のリクエストも実現できることになります。 ただ、インフラ的には2つのシステムが1つの塊として構成される事になるため デプロイの単位やスケールの単位を常に双方共有することになります。 こうなると、せっかくアプリケーションを分けたにも関わらず 運用の部分では何もメリットを得られないどころか制約が増えただけのようになりそうなのが問題です。 その2 内部 Application Load Balancer を経由する VPC 内部に internal な Application Load Balancer(以下 ALB) を設置し、接続先となる既存システムを TargetGroup に登録します。 この方法であれば、ALB のエンドポイントに向けてリクエストすることで配下の既存システムにアクセスする経路が確保できます。 また ECS サービスと TargetGroup が紐づくことにより既存システム側のデプロイやスケールが自動的に ALB 側にも連動することになるため、新システム側は既存システムのステータスを意識する必要は少なくなります。 これだと不自然な点も無くアプリケーション間の通信経路も確保できると期待しましたが・・・新たに問題が発生しました。 検証時に ALB/TargetGroup を新規作成。 ECS サービスについては 後付けで TargetGroup 脱着はできない 複数 TargetGroup の付与は AWS コンソールでは対応していない といった理由のために AWS CLI での作成作業を行ったのですが、下記エラーが発生してしまいました。 An error occurred (InvalidParameterException) when calling the CreateService operation: load balancers can have at most 5 items. これは AWS による制限で、1 つの ECS サービスに関連付けることのできる TargetGroup は最大 5 つまでという事を表しています。 つまり既存システムは多くの機能やコンテナが同居している ECS サービスとなっていたため、既に TargetGroup が 5 つ存在しており上限に達していたのです。 サービスで使用するロードバランサーを表すロードバランサーオブジェクト。Application Load Balancer または Network Load Balancer を使用するサービスの場合、サービスにアタッチできる 5 つのターゲットグループの制限があります。 Amazon ECS サービス定義パラメータ - Amazon Elastic Container Service Amazon ECS サービスの実行方法を定義するサービス定義パラメータについて説明します。 docs.aws.amazon.com この方法を取るなら不要な TargetGroup を削るかまとめるかの手を打つ必要がありますが、 周辺環境に対する影響があまりにも大きい為に現実的ではありませんでした。 そのため、新たな選択肢を探すことにしました。 その3 Amazon ECS サービスディスカバリを使用する そんな中、ECS の機能としてサービスディスカバリ(サービス検出)というものを見つけました。 Amazon ECS サービスディスカバリ | Amazon Web Services Amazon ECS でサービスディスカバリがサポートされました。これにより、ECS サービスが A […] aws.amazon.com これは ECS サービスと Route53 内部ホスト空間を紐付ける機能です。 また ECS サービスの起動・停止・スケールといった対象が変動した場合にも、自動的にホスト空間のレコードを登録/解除し最新の状態に追従してくれるものです。 この場合、別々のサービス間でもお互い相手の名称を把握することができる上、 TargetGroup も新規に必要としないため、今回のニーズに適した方法になりそうです。 導入してみた結果 試しに ECS サービスにサービスディスカバリを導入し、疎通できるか試してみます。 既に存在するサービスに後付でのサービスディスカバリは出来ないため、新規にサービスを作成 することになります。 今回は初めてのサービスディスカバリとなるので、名前空間も同時に作成することになります。 ひとまず名前空間を「 medley-blog.local 」、サービス検出名を「 service-discovery 」としてみます。 このまま ECS サービスを作成すると、Route 53 にて新たな名前空間「 medley-blog.local 」が作成されていることが確認できます。 この状態でサービスのタスクを 1 つ起動ししばらく待つと、 サービス検出名.名前空間 となる service-discovery.medley-blog.local に A レコードが追加されています。 このレコードに紐づく IP アドレスこそ、ECS タスクに紐付けられている IP アドレスになります。 あとはこの名称で別環境から疎通できるか試してみます。 curl コマンドで service-discovery.medley-blog.local で通信してみると、見事にレスポンスを受け取ることが出来ました。 ※ここでは検証のため、接続先アプリケーションは Nginx コンテナを配置しています これにより、異なる ECS サービス間での通信を実現することができました。 今後の予定 現段階では検証段階のため評価環境への導入のみとなりますが、今の所は大きな問題も発生せず順調に稼働しています。 このまま特に問題無く稼働できれば、本番環境への導入も目指したいと思います。 さいごに メドレーのエンジニアは大小問わず課題に対して真摯に向き合い、試行錯誤し、突破口を開く取り組みを常に続けています。 そんな我々と一緒に働きたいと思った方、まずは下記リンクからご応募いただきカジュアルにお話しませんか? www.medley.jp www.medley.jp
アバター
株式会社メドレーのエンジニアの阪本です。 緊急事態宣言も開け、普段の生活を取り戻しつつあるこの時期、 皆さんはいかがお過ごしでしょうか? 私は野球観戦(虎党)を毎日の楽しみとしています。 今年はコロナ渦の影響で開幕予定が遅延したものの、自粛期間を経て 6 月中旬にめでたくシーズン開幕を迎えることができました。 ここまでの「長い冬」が明け、テレビをつけると野球が見られる。 これで私自身も 2020 年が開幕したなと実感しています。 今回は、私がインフラ開発時に直面した問題と解決までの事例について紹介させて頂きます。 背景 私はジョブメドレーのサービス開発を行っています。 このシステムは多くの機能で構成された大規模なもので、AWS の Elastic Container Service(以下 ECS)にて稼働しています。 このシステムに対し既存機能のリプレース案件に携わる機会がありました。 現在のシステムは多くの時間をかけて多くの機能を実装した結果、かなり大きなコードとなっています。 これにより、一つの変更が及ぼす影響が甚大なものになり得る状況だったため、リプレース対象の機能を新システムとして別アプリケーションに切り出して開発することにしました。 しかし、別システムとして一部の機能を切り出すものの、この機能は 既存システムとの連携が必要となります。 そのため、この連携をシステム間の API リクエストで実現することにしました。 課題 ここで1つの問題が発生しました。 システム間の通信が必要になりましたが、お互い ECS サービスで分離した構成となるため このままではアドレスの解決が出来ないことに気づきました。 同一 ECS サービス内でかつ、ネットワークモードが awsvpc モードであれば ポート番号を分ける事により相互でアクセスが可能であるものの 異なるサービスであればポート以前にアドレス解決ができません。 そのため、何らかの手段を持ってお互いの場所を認識できる状態にする必要があります。 そこで、これを実現できる幾つかの方法を検討しました。 アプローチ その1 全て1つの ECS のサービスにまとめる 上記の通り、既存システムが動いている ECS サービス/タスクに新システム(のコンテナ)を全て混ぜる方法です。 この場合、全てのポートを個別に割り振ることで 127.0.0.1:port によるアクセスが可能となるため 相互のリクエストも実現できることになります。 ただ、インフラ的には2つのシステムが1つの塊として構成される事になるため デプロイの単位やスケールの単位を常に双方共有することになります。 こうなると、せっかくアプリケーションを分けたにも関わらず 運用の部分では何もメリットを得られないどころか制約が増えただけのようになりそうなのが問題です。 その2 内部 Application Load Balancer を経由する VPC 内部に internal な Application Load Balancer(以下 ALB) を設置し、接続先となる既存システムを TargetGroup に登録します。 この方法であれば、ALB のエンドポイントに向けてリクエストすることで配下の既存システムにアクセスする経路が確保できます。 また ECS サービスと TargetGroup が紐づくことにより既存システム側のデプロイやスケールが自動的に ALB 側にも連動することになるため、新システム側は既存システムのステータスを意識する必要は少なくなります。 これだと不自然な点も無くアプリケーション間の通信経路も確保できると期待しましたが・・・新たに問題が発生しました。 検証時に ALB/TargetGroup を新規作成。 ECS サービスについては 後付けで TargetGroup 脱着はできない 複数 TargetGroup の付与は AWS コンソールでは対応していない といった理由のために AWS CLI での作成作業を行ったのですが、下記エラーが発生してしまいました。 An error occurred (InvalidParameterException) when calling the CreateService operation: load balancers can have at most 5 items. これは AWS による制限で、1 つの ECS サービスに関連付けることのできる TargetGroup は最大 5 つまでという事を表しています。 つまり既存システムは多くの機能やコンテナが同居している ECS サービスとなっていたため、既に TargetGroup が 5 つ存在しており上限に達していたのです。 サービスで使用するロードバランサーを表すロードバランサーオブジェクト。Application Load Balancer または Network Load Balancer を使用するサービスの場合、サービスにアタッチできる 5 つのターゲットグループの制限があります。 Amazon ECS サービス定義パラメータ - Amazon Elastic Container Service Amazon ECS サービスの実行方法を定義するサービス定義パラメータについて説明します。 docs.aws.amazon.com この方法を取るなら不要な TargetGroup を削るかまとめるかの手を打つ必要がありますが、 周辺環境に対する影響があまりにも大きい為に現実的ではありませんでした。 そのため、新たな選択肢を探すことにしました。 その3 Amazon ECS サービスディスカバリを使用する そんな中、ECS の機能としてサービスディスカバリ(サービス検出)というものを見つけました。 Amazon ECS サービスディスカバリ | Amazon Web Services Amazon ECS でサービスディスカバリがサポートされました。これにより、ECS サービスが A […] aws.amazon.com これは ECS サービスと Route53 内部ホスト空間を紐付ける機能です。 また ECS サービスの起動・停止・スケールといった対象が変動した場合にも、自動的にホスト空間のレコードを登録/解除し最新の状態に追従してくれるものです。 この場合、別々のサービス間でもお互い相手の名称を把握することができる上、 TargetGroup も新規に必要としないため、今回のニーズに適した方法になりそうです。 導入してみた結果 試しに ECS サービスにサービスディスカバリを導入し、疎通できるか試してみます。 既に存在するサービスに後付でのサービスディスカバリは出来ないため、新規にサービスを作成 することになります。 今回は初めてのサービスディスカバリとなるので、名前空間も同時に作成することになります。 ひとまず名前空間を「 medley-blog.local 」、サービス検出名を「 service-discovery 」としてみます。 このまま ECS サービスを作成すると、Route 53 にて新たな名前空間「 medley-blog.local 」が作成されていることが確認できます。 この状態でサービスのタスクを 1 つ起動ししばらく待つと、 サービス検出名.名前空間 となる service-discovery.medley-blog.local に A レコードが追加されています。 このレコードに紐づく IP アドレスこそ、ECS タスクに紐付けられている IP アドレスになります。 あとはこの名称で別環境から疎通できるか試してみます。 curl コマンドで service-discovery.medley-blog.local で通信してみると、見事にレスポンスを受け取ることが出来ました。 ※ここでは検証のため、接続先アプリケーションは Nginx コンテナを配置しています これにより、異なる ECS サービス間での通信を実現することができました。 今後の予定 現段階では検証段階のため評価環境への導入のみとなりますが、今の所は大きな問題も発生せず順調に稼働しています。 このまま特に問題無く稼働できれば、本番環境への導入も目指したいと思います。 さいごに メドレーのエンジニアは大小問わず課題に対して真摯に向き合い、試行錯誤し、突破口を開く取り組みを常に続けています。 そんな我々と一緒に働きたいと思った方、まずは下記リンクからご応募いただきカジュアルにお話しませんか? www.medley.jp www.medley.jp
アバター