オンラインストアを1時間あたり280,000人の訪問者に耐えさせるにはどうすればよいですか?



こんにちは、Habr!



残念ながら、わが国でのWebプログラミングの開発のこの段階では、プロジェクトのリファクタリングは「すべてが悪い」モードでのプログラマーの仕事として認識されることが多く、サイトがすでに危機的な状態にあるときにのみ実行されます。 2012年に同様の状況に対処しなければなりませんでした。ロシアの大手オンラインストアの1つが次の問題でサービスを開始しました。 。 再起動後、サイトは少し動作し、その後再びクラッシュしました。 特に深刻なのは、新年が近づいているという事実、すべての販売サイトのハイシーズンであり、この場合、「10分で会社が数万ドルを失う」というフレーズは冗談ではありませんでした。





私たちの話から一息ついて、開発者が非常に幸せな人々になったという事実について話しましょう。 最後に、サーバーの容量は非常に安価になったため、リソースのないシステムは希望のサイズに簡単に拡張できます。 プログラムに何か問題がありますか? パーセントあたりの負荷が増加しましたか? さて、サーバーにプロセスを追加しましょう。 十分ではありませんか? 工作員を追加しましょう。 リソース不足の問題は問題ではありません。



あなたがたの多くは、人々がダイヤルアップに座って、思慮深くモデムの音を聞いて、最初のメモから接続できたか、再接続する必要があるかを判断したことをよく覚えています。 そのとき、(サイトの文字通りの意味で)それを待つのは非常に高価だったので、遅いサイトは1分後に単純に閉じました。 今日、遅いサイトとは、チャネルの速度に関係なく3秒以上開かれるサイトです。 世界はスピードアップしており、時間がかかります。 しかし、サイトの速度が不足している場合はどうでしょうか? 素晴らしいアクセラレーターと、より強力で非常に安価なサーバーが同時に存在します。たとえば、同じ1C-BitrixからのWebクラスターがあり、同じ目的のためのソフトウェアの海であるピンチにあります。 コードの品質を監視できなくなり、開発者のレベルを大幅に低下させ、会社の予算を大幅に節約できないようです。



しかし、それだけのようです。 Web開発者の現実である私たちの現実では、最も強力なハードウェアのいずれにも、独自の無限のサイクルと素晴らしいフレームワークがあります。 そして、最も強力なハードウェアでさえ、書かれたコードを引き出せない状況がしばしばあります。



ですから、最初に言及した大規模なオンラインストアであるクライアントの場合です。 彼には6台の強力なサーバーがあり、それぞれが自由にスケーリングできることがわかりました。 その時点で最も論理的かつ最速のアクションは、サーバーをさらに2つ追加することでした。 ただし、予定どおりサイトは引き続き下落しました。



通常の操作で何らかのタイムアウトを取得するために、私たちは最初にプロジェクトを新年に耐えられるように何らかの形で安定させることを決定し、次にグローバルなリエンジニアリングとリファクタリングを実行しました。



入り口には何がありましたか?



システムのさまざまな部分でのロードスケジュールは、かなりスムーズでなければならないことがわかっていました。 たとえば、次のとおりです。







これは、1秒間に1人のサイトにゼロユーザーが存在することは非常にまれであり、次の瞬間には110,000ユーザーすべてがピーク負荷になるという事実によるものです。



しかし、クライアントのプロジェクトで私たちが見たものは、私たちのすべてのプラクティスに反していました。すべてのスケジュールが急増し、忙しい生活を送っていました。

次のようになりました。



Apache:





おそらく、スケジュールへの負荷の増加-より多くの訪問者、より多くのお金-を喜ぶ価値があるだろうが、Google Analyticsは訪問者の数が増加しなかっただけでなく、減少したとも述べた。



原則として、システムの安定した正しい状態では、Apacheの負荷の増加はMySQLの負荷の増加と相関しています。 しかし、私たちの場合、すべてが異なって見えました。



MySQL:





次に、MySQLとApacheのグラフを比較してみましょう。





明らかに何かがおかしかった。 そして、問題を探し始めました。



何を見つけましたか?



まず、修正された1MS-Bitrix CMSコアを発見し、キャッシュで動作する部分で変更されたため、キャッシュでの不正な操作の可能性がありました。 原則として、これは何らかのロジックでした-キャッシュがクラッシュしてフラッシュした場合、これらの瞬間にApacheが急増します。 しかし、その後、MySQLにより多くのバーストがあったはずですが、何もありませんでした。

第二に、CMSコアが変更されたため、プロジェクトが更新されていないため、プロジェクトは数年間更新されていません。

第三に、サーバーが正しく構成されていません。 私たちの話はリファクタリングに関するものなので、この点については詳しく説明しません。

第4に、このプロジェクトは2005年から2006年頃に作成され、現在の負荷の10分の1である完全に異なる負荷で計算されました。 プロジェクトのアーキテクチャとコードは、負荷の増加に合わせて完全には設計されていません。 新しい負荷がすでに4〜15秒で、スローログに落ちたときに、古い負荷の下で0.5〜1秒の許容範囲内にあったという要求。

そして第五に、プロジェクトの長年にわたるさまざまな請負業者との顧客の協力の過程で、多くの重複コードがその中に現れ、余分なサイクルと非効率的なキャッシュがありました。



実際、小さなデバッガー、数ギガバイトのログ、少なくとも60 kgの体重のライブアナリスト、塩、胡pepper、ミックス-プロジェクトの迅速な安定化のための優れたレシピがありました。 彼は新年のピークを乗り切ることができ、小さいがまだ安全性のマージンを獲得しました。





彼らは他のすべてをどのように修正しましたか?



プロジェクトは1C-Bitrixにあったことを思い出してください。 まず、CMSのバージョンを最新に更新しました。これにより、最初に想定したように、機能の大部分が機能しなくなったため、復元する必要がありました。 基本的な分析の結果、カーネルお​​よび標準コンポーネントで1000を超えるファイルが変更されたことが判明しました。 アップグレード後、最初のステップは、サイトを完全に機能するバージョンに復元することでした。 しかし、これにより、Webクラスターモジュールをすべての利点と接続することができました。



第2段階では、プロジェクトアーキテクチャ、データベースクエリ、およびコードを分析し、アーキテクチャの特定の構成により、キャッシュのない3000から4000のデータベースクエリが1つのカタログページから生成され、キャッシュは約200リクエストであることがわかりました。 同時に、最適ではなく、コンテンツが更新されるとリセットされました。



データベースクエリを最適化するには、情報ブロックの構造を変更する必要がありました。データの一部を非正規化し、データの一部を別のテーブルに移動します。 これにより、30〜40秒の実行速度で最も重い結合を取り除き、それらをいくつかのクイック選択に置き換えることができました。 また、最も使用されているデータにインデックスを付け、古い構造から不要なデータを削除しました。 これにより、クエリ実行の全体的な速度が大幅に向上しました。



また、プロジェクトのその後の開発者にボーナスを追加しました:コードを将来読みやすくするために、数千のコードシートを別々のクラスとファイルに分散し、それらにコメントを付け、古いファイルを削除しました。



最後に何が起こったのですか?



リストされたすべての作品を順番に実行するのに約6ヶ月かかりました。 次に、サイトで負荷テストを実施しました。 テストは、外部ネットワークとクラスター内の両方から行われました(テストに対するチャネル速度の影響を平準化するため)。



テストのグラフでは、25人の同時ユーザーの負荷でシステムをリファクタリングおよびリエンジニアリングする前に、ページが約8秒、その後わずか4.2秒でロードされることが、外部から確認できます。

宛先:



後:





クラスター内からのテストのグラフでは、たとえば、メインページが40秒間ロードされ、40万人の訪問者が200,000人、1.9秒がロードされ始めたことがわかります。

宛先:



後:





開発者は何に満足していますか?



キャッシュを使用する場合と使用しない場合のデータベースへのクエリの数を減らしました。 コードの可読性が向上しました。 プロジェクトの内部構造を簡素化しました。 古いデータを削除しました。 14,000以上のファイルを変更しました。 簡素化されたプロジェクトのスケーリング。 そして最後に-彼らは負荷を増やすためにプロジェクトに大きなマージンを与えました。



そのため、記事の最後ですべてのWeb開発者にアドバイスしたいと思います。





Natalya Chilikina、ADVヘッド/ Webエンジニアリングビトリクス開発部門



All Articles