はじめに
エキサイト株式会社 バックエンドエンジニアの山縣(@zsp2088dev)です。 新卒入社から早いもので2年が経過しました。
最近、エキサイトブログの大規模なメンテナンスが完了し、無事にクラウドとデータベースの移行が終わりました。 クラウドはAzureからAWSへ、データベースはSQL ServerからPostgreSQLへと移行しました。
このプロジェクトでは、私を含む3名で取り組み、2年間の努力の末に移行作業を達成できました。 チーム全員が一丸となって取り組んだ結果、このような大きなプロジェクトを成功させることができたことを嬉しく思います。
本記事ではエキサイトブログの2年間の移行作業を振り返り、移行のためにチームで取り組んできたことについて紹介します。
エキサイトブログとは
エキサイトブログは2004年から提供しているサービスで、2023年現在で19年間稼働しています。 エキサイトブログは多くの機能を提供しており、特にブロガーが自分自身のブログのデザインやメニューなどを自由にカスタマイズできる魅力的なサービスです。
エキサイトブログのリビルド経緯
エキサイトブログは19年間運営されており、その間にデータベースには大量のデータが蓄積されました。 そして、アプリケーションコードは開発が進むにつれて徐々に複雑化していきました。 現在アプリケーションコードはGitでバージョン管理されていますが、2015年頃まではSVNで管理されていたため、移行前の差分を参照することができず、過去のコードの変更履歴を追跡することができません。
現在使用しているファイルの中には、最長で9年間、変更されていないファイルもあります。 このように長期間にわたってサービスの運営をしていると、データベースへの大量のデータの蓄積やアプリケーションコードの複雑化などが起こり、 メンテナンスや移行作業が困難となっていました。
アプリケーション、データベース、クラウドに着目すると、以下の課題がありました。
- アプリケーション
- データベース
- SQL Serverのライセンス費用が高額であり利益を圧迫している
- SQL Serverの構成が非推奨であるプリンシバル/ミラー構成になっている
- クラウド
SQL Serverのライセンス費用が高額である件については、フリーライセンスのデータベースであるPostgreSQLに移行することが望まれていました。 また、社内標準でないAzureを使用している件については、Azure固有の問題に対して知見を共有できず対応に時間がかかってしまうといった問題点がありました。
上記の理由から、今後もエキサイトブログを運営していくために、2021年3月にエキサイトブログをリビルドすることに決定しました。
リビルドするために取り組んだこと
Azure/SQL ServerからAWS/PostgreSQLに移行するにあたり、取り組まなければならないことが非常に多くありました。
- データベースの処理はAPIサーバーで行う
- ストアドプロシージャからの脱却
- SQL ServerとPostgreSQLで使用可能なクエリーにする
- Azure VM → Azure Container Apps
- Azure Container Apps → AWS ECS
それぞれの詳細について、以下でまとめていきます。
データベースの処理はAPIサーバーで行う
エキサイトブログにはトップ面、ブロガー面、ブロガー管理画面、管理者ツールなど数多くのアプリケーションがあります。 それらすべてのWebサーバーがデータベースの処理を行っていました。 データ移行時の困難さや今後の継続的な開発を考慮した結果、Webサーバーではフロントエンドの表示に集中させ、データベースの処理やビジネスロジックをAPIサーバーで実装することに決めました。 この時、静的型付け言語であることや所属部署の開発責任者がJavaに精通していることを理由に、APIサーバーをJavaで構築することになりました。 さらに、データベースへの依存度が高いストアドプロシージャはJavaで再実装を行うことに決めまりました。
リビルド前とリビルド後の構成図を以下に示します。
ストアドプロシージャからの脱却については、次節で詳細にまとめます。
ストアドプロシージャからの脱却
ストアドプロシージャとは、データベースに保存される手続きです。 SQL ServerとPostgreSQLで書き方が大きく異なるため、データベース移行をするのに一番の障壁となります。 前節のとおり、今後はストアドプロシージャを使用しない方針としたため、ストアドプロシージャの処理をJavaで再実装することにしました。
まずはSQL Serverに登録されているストアドプロシージャの数を数えるところからはじめました。 この時、約300個のストアドプロシージャがあることがわかりました。
使用していないストアドプロシージャをすべて移行するのは大変な作業です。 そこで、ストアドプロシージャを呼び出している箇所にログを仕込み、使用しているストアドプロシージャのみを移行することにしました。 調査の結果、約3割のストアドプロシージャを使用していることが判明したので、 これらのストアドプロシージャをJavaで再実装することにしました。 この時、再実装するストアドプロシージャをスプレッドシートで管理しながら1つ1つ実装していきました。
ストアドプロシージャはSQLクエリーの組み合わせであるため、再実装することはそこまで難しくないと考えていました。
実際にいくつかのストアドプロシージャは「ある値がAならレコードを追加するが、Bならレコードを更新する」といった簡単なものも多かったです。
しかし、SUBSTRING
関数やCHARINDEX
関数を使用した文字列の処理、WHILE
文を使用した繰り返し処理など読み解くのが難しいクエリーも多く存在しました。
この作業は、他の作業と並行して行っていましたが、すべてのストアドプロシージャから脱却するまで半年がかかり、長期にわたる移行作業となりました。 そして、使用しているすべてのストアドプロシージャをJavaで再実装できた時には、社内カンファレンスで「アプリケーションをコンテナ化するまでの取り組み ─ストアド・プロシージャ脱却編─」というタイトルで発表しました。
SQL ServerとPostgreSQLで使用可能なクエリーにする
SQLServerからPostgreSQLにデータベースを移行する場合、SQLクエリーの書き方は基本的に同じですが、データベース固有の書き方や関数などによって、同じSQLクエリーが動作しないことがあります。 そのため、SQLServerとPostgreSQLの文法や機能の違いに注意しながら、移行先のPostgreSQLに合わせてSQLクエリーを修正しなければなりませんでした。
以下に示す表は、実際に対応しなくてはならなかった一部のクエリーの一覧です。
SQL Server | PostgreSQL | 説明 |
---|---|---|
TOP | LIMIT | 取得件数の指定 |
ISNULL | COALESCE | NULL値の時の対応 |
CONVERT | TO_CHAR | 文字列の変換 |
NEWID | RANDOM | ランダム値の生成 |
WITH (NOLOCK) | ── | トランザクション分離レベルの指定 |
SCOPE_IDENTITY | RETURNING [id] | 最後に更新されたID値の取得 |
取得件数を指定するTOP
とLIMIT
については、どちらのデータベースでも使用できるOFFSET
を使用することで対応することにしました。
一方で、どちらのデータベースでも使用可能なSQLクエリーにできない場合は、それぞれで動作するSQLクエリーを用意することにしました。
データベースとのやり取りにはMyBatisを使用しています。
MyBatisには、以下のようにdatabaseId
を指定することで接続先のデータベースに応じてSQLクエリーを切り替えることのできる機能があります。
これにより、例えばSQL Serverの場合はCONVERT
関数を使用し、PostgreSQLの場合はTO_CHAR
関数を使用することができるようになります。
@Select(value = """ SELECT CONVERT(VARCHAR(7), date, 23) AS month FROM sample_data """, databaseId = "sqlserver" ) @Select(value = """ SELECT TO_CHAR(date, 'YYYY-MM') AS month FROM sample_data """, databaseId = "postgres" ) List<Result> getSampleDataMonth();
databaseId
の詳細については、以下のドキュメントをご参照ください。
Azure VM → Azure Container Apps
アプリケーションをコンテナ化して運用するにあたり、Azure VMからAWS ECSの移行は環境の差異が大きすぎるため、まずはAzureのコンテナサービスでコンテナを稼働させることにしました。
以下に示す図は、移行前のAzure VMの構成です。 1つのVMで複数のアプリケーションが稼働しています。 そのため、1つのアプリケーションの負荷が増大したときにスケールアウトするのが難しく、事前に大きなサイズのVMを用意する必要がありました。
Azureにはいくつかのコンテナサービスがあります。 その中でスケールアウトが容易にできることや、アイドル時間の料金が安いことを条件に選定した結果、Azure Container Appsを採用することに決めました。
スケールアウトが容易にできることについては、Azure Container Appsではリクエスト数やCPU使用率などを条件にスケールアウトの条件を簡単に設定することができます。 またアイドル時間の料金が安いことについては、開発や動作確認で使用するテストとステージング環境と非常に相性がよかったです。
次に示す図は移行後のAzure Container Appsの構成です。 Azure VMからAzure Container Appsに移行したことで、上記の問題点を解決することができました。 また、CI/CD環境の整備をしたりコンテナ環境のコード化をしたりと、AWS ECSに移行しやすいように整備することもできました。
Azure VMからAzure Container Appsの移行については、以下の記事で詳しく説明しています。
また、移行して3ヶ月経過したときの使用感についても以下の記事にまとめています。
Azure Container Apps → AWS ECS
Azureで安定したコンテナ稼働ができるようになった段階で、AWS ECSの構築を開始しました。 AWS ECSの構築については、社内に多くの知見があるため、他サービスのメンバーと協力しながら構築を進めました。
アプリケーションをコンテナ化していたため環境差異を抑えられ、素早くテスト環境を構築することができました。 実際に移行したものを下記にまとめます。
以下のとおり、全体的な構成を大きく変えることなくクラウド移行を実施することができました。
Azure | AWS | 説明 |
---|---|---|
Azure Container Registry | Amazon ECR | コンテナレジストリ |
Azure Container Apps | Amazon ECS | コンテナ実行環境 |
Azure Application Gateway | Application Load Balancer | L7ロードバランサー |
Azure Cache for Redis | Amazon ElastiCache for Redis | キャッシュ |
SQL Server 2016 | Amazon Aurora PostgreSQL | データベース |
当日の様子
ここまでですべての準備が整いました。 最後の仕上げであるAzureからAWSの切り替えを行います。
クラウドの切り替え時には、ユーザー影響を最小限に留めるために、ブログ記事の閲覧のみを許可するような仕組みを導入することにしました。 具体的には、データの参照のみを許可し、データの追加/更新/削除を許可しないようにしました。
以下に示す図は、メンテナンス前のAzureの構成図です。 すべてのリクエストがAzureを向いています。
続いて、メンテナンス予定時刻になったら、ブログ記事の閲覧のみを許可するようにしました。 データベースの処理はAPIサーバーに集中しているため、APIサーバーでGETリクエストのみを受け付けるようにしてデータの参照のみをできるようにしました。 これにより、データの追加/更新/削除が行われなくなります。 また、Webサーバーではブロガー管理画面やコメントページ等をメンテナンスページにリダイレクトさせるといった処理を行いました。
続いて、データベースの参照のみを許可しているときに、Embulkを使用してSQLServerからPostgreSQLのデータ移行を行いました。 データ移行が終わり、SQL ServerとPostgreSQLのデータの差分がなくなったことを確認しました。
データ移行後は、DNSの向き先を変更しました。 この時、AWS上でもメンテナンスモードを継続して行っています。 これは、不具合があった場合にすぐにAzureに戻せるようにするためです。
最後に、メンテナンスを解除してすべての機能が利用できるようにしました。
2年間の移行作業を終えての感想
まずは、2年間の移行作業が無事完了したことが何よりも嬉しいです!🎉
私は、新卒で入社して2週間後からエキサイトブログのリビルドに参画し、初期の段階から携わっていました。 当初はエキサイトブログに対するドメイン知識が十分でない状態から進みましたが、 リビルドを通してエキサイトブログのシステムを学んでいくことも多くありました。
最後に、一緒にプロジェクトに取り組んでくれたメンバーや、協力していただいた他サービスのメンバーの皆様、ありがとうございました。
おわりに
本記事では、Azure/SQL ServerからAWS/PostgreSQLへの2年間の移行作業についてまとめました。
旧APIサーバーから新APIサーバーへのリビルド、ストアドプロシージャからの脱却、DB互換のあるクエリーの対応およびクエリーチューニング、 Azure VMからAzure Container Appsの移行、AzureContainer AppsからAWS ECSの移行、AzureからAWSのクラウド移行、 SQL ServerからPostgreSQLのデータ移行を実施しました。
今後は、AWSのサーバー構成/費用の最適化や新機能の開発等に着手していく予定です。 最後まで読んでいただき、ありがとうございました。
お知らせ
エキサイトブログの移行プロジェクトのメンバーである中尾が、JJUG CCC 2023 Spring に「Spring Boot × MyBatis × FreeMarker を使って、データベースの接続先を安全に変更します。」といったテーマで登壇します。 こちらのセッションでは、エキサイトブログの移行に関わるデータベースの処理周りについて話をする予定です。 ご興味ある方は、ぜひご参加ください!
採用アナウンス
エキサイトではフロントエンジニア、バックエンドエンジニア、アプリエンジニアを随時募集しています。 また、長期インターンも歓迎しています。
カジュアル面談からもOKです。少しでもご興味がございましたら、お気軽にご連絡頂ければ幸いです。
▼ 募集職種一覧 ▼ recruit.jobcan.jp