私は PHP で作業しており、記事に含まれるソース コードも PHP に関連しているため、Zuning モデレーターが不適切だと判断した場合は、転送にご協力ください。
広告の疑いを避けるため、会社紹介部分を削除しました
なお、当時共有された質問と回答の一部は転送されていません
原文を読むには、以下のリンクをクリックしてください。アカウントの記事
WeChat 公開アカウントにアクセスして原文を読んでください
この段階で、ナイスサーバーは主に次の課題に直面しています:
変化に直面するシステム設計は、「製品探索段階」でのニーズの多様性を適切にサポートできなければなりません。
安定性: 既存のユーザーに損害を与える安定性の問題を回避すると同時に、急激なビジネスの成長にも対処する必要があります。
コラボレーション、スズメは小さいですが、サーバーはクライアント、戦略提案、ビッグデータ、QA、運用、製品、その他のチーム間の架け橋として機能します。技術的手段または非技術的手段。
「プッシュして再スタート」:nice の再建への道のり
nice に入社してすぐに、ビジネス全体とサーバーの枠組みを再構築するという非常に挑戦的なタスクを受け取りました。多くの起業家チームと同様に、私たちは成長するにつれて一連の技術的負債を蓄積してきました。
旧システムは CI フレームワークを使用して記述されており、モジュールの分割や明確な階層化はなく、入り口で直接実行され、再利用はほとんどありませんでした。
API のバージョン管理はディレクトリの直接コピーです ビジネスの発展に伴い、10 を超えるバージョンのインターフェイス コードを同時に維持する必要があり、これは非常に困難です。
コードには、if ($isAndroid && $appVersion >= 3) のような互換性ロジックが満載です。
そのため、クライアント/サーバー共同デバッグは基本的にシャウトに依存しています。スタートアップ企業に勤める多くの友人がこうした問題を経験していると思います。
古いシステム アーキテクチャ
古いシステム アーキテクチャは、最も典型的な統合アプリケーション アーキテクチャです。バックエンド、HTML5、インターフェイスがすべて混在しています。
当時の状況に直面し、私たちはまず解決すべき問題を分析し、以下の 3 つの課題が重要であると考えました。
構造的な問題。コード構造が複雑で再利用できません。
クライアントの差異管理。インターフェイスのバージョンをコピーすると、大量の重複コードが発生します。これは主に、特定のクライアント/グレースケール/低トラフィックなどの問題の特別なニーズを目的としています。
クライアント/サーバーの RD コラボレーションの問題。
階層化とモジュール性
まず、大きな観点から考えると、最初の問題は単純な 2 層アーキテクチャで解決できます。
アプリケーション層とサービス層はコーディング レベルで分割されます。
アプリケーション層は、対話プロトコル、認証、スパム対策、その他の一般的なサービス アクセスなどの入り口の問題と、各エンドの個別のニーズを解決します。
サービス層はビジネスロジックの問題を解決し、ビジネスに応じてサービス層を垂直モジュールに分割します。
レベルとモジュールの分割により、コード管理が明確になり、ロジックの再利用性が大幅に向上します。同時に、事業部門はその後の事業分離や階層管理の基礎的なサポートも行います。
2 つの基本コンポーネント
前述のクライアント差異管理とクライアントとサーバーのコラボレーションは、フレームワークの 2 つの基本コンポーネントによって解決されます:
ClientAdapter: クライアント アダプター。ロジックの質問によって引き起こされるすべてのクライアント差異を処理するために使用されます。 。
CKCR: CheckAndCorrect、データの検査と修正。入出力プロトコルを制御し、クライアント/サーバー RD コラボレーションの技術的問題を解決するために使用されます。
ClientAdapter コンポーネント
まず、ClientAdapter のアプリケーション シナリオを見てみましょう。
上記の構成を例として、以下の一般的に使用される同様のルールを実装できます。
すべてのクライアントはバージョン 3.1.0 以降であり、「Say Hello」機能をサポートしています。
すべてのクライアントはバージョン 3.1.0 以降であり、グレースケール チャネル abc36032 はバージョン 3.1.0 であり、「絵文字」機能をサポートしています。
上記の nice コードを見てください。このメソッドを通じて、nice は特定のクライアント環境ではなくさまざまな「機能」を論理的に扱います。上記の例は、ClientAdapter の適用シナリオです。
ClientAdapter 全体の構造
ClientAdapter 最も基本的な部分は、「クライアント ランタイム環境」の概念を抽象化し、それを使用して、システム、アプリのバージョンなど、各リクエストを開始するクライアントに関するさまざまな情報を記述することです。 、IP、ネットワーク規格、ネットワークオペレータ、地理的位置など。さらに、制限されたクライアント環境を記述するための簡単な記述ルールも提供します。
アプリケーション レベルでは、現在のクライアントが指定された記述ルールを満たしているかどうかを確認するために checkEnv() インターフェイスのみを公開します。このインフラストラクチャの上には、優れた上位層にさまざまな種類のアプリケーションがあります。
たとえば、元のクライアントの違いにより、NiceFeature を通じて、フィーチャー メカニズムの下で、RD は実際に製品イテレーションからのフィーチャーに直面することになります。もう 1 つの例は、CDN の統合スケジューリングを実装する NiceUrl で、ClientAdapter を通じて、各リージョンを柔軟に制御して、異なるスケジューリング戦略を採用できます。
さらに、ユーザーの迂回を処理するという点で、このメカニズムによってもたらされる柔軟性は、複数の側面に従って実験的にユーザーを抽出するという Nice のニーズにも応えることができます。
ClientAdapter オープンソース アドレス
ClientAdapter このコンポーネントは実装が非常に簡単で、わずか 200 行です。コードは抽出され、参照用に github に置かれています。URL は http://t.cn/RGnqnpj です。
また、ClientAdapter の設計は C 言語の一般的なメソッドを参照しています。 autoconf ステージでは、システムの各種環境情報が各種 HAVE_XXX として定義されます。これにより、環境自体の複雑さを実際のビジネス コードから切り離すという目的が達成されます。
CKCR の導入
上記の質問 3、クライアント/サーバー RD コラボレーションの問題、この問題は 2 つの部分に分かれています。
技術レベル: プロトコル層の制約。
プロセスレベル: 協力する方法。
技術レベルで解決すべき問題は、インターフェイス プロトコルの実行をどのように保証するかです。入力の観点から見ると、契約が確立されている限り、クライアントが「悪者」に支配されてサービスに損害を与えることを防ぐためのルールに従わなければなりません。出力の観点から見ると、一致せずクラッシュを引き起こす一般的な型など、クライアントでの予期せぬ結果を避けるために、ビジネス層から返されたデータはプロトコルに従ってクライアントに送信される必要があります。
簡単に言うと、入力データと出力データのチェックサムを修正することです。したがって、Nice はここで CKCR と呼ばれるコンポーネントの層を導入しました。その完全名は ChecK && CorRect です。
CKCR 実装
CKCR 記述的な文法ルールの小さなセットを実装します。この構文セットを使用して、データに対して実行されるチェックサム修正を記述します。チェックサム修正動作は自由に拡張可能で、ここではその応用例を示します。
この例では、$data は処理されるデータを表し、$ckcrDesc はこの文法規則の説明文字列です。説明されているルールは次のとおりです。
全体のデータは KV 配列 (マッピング) であり、2 つのサブキー ユーザーと表示のデータのみを保持します。
user も KV 配列であり、その ID は int 型、名前は str 型です。
shows は配列であり、配列内の各要素は KV 配列であり、その ID サブキーと URL サブキーをフィルターで除外し、imgCdnUrl のカスタム処理を適用します (cdn スケジューリングを実行します)。
protobuf および Thrift スキームとの類似点と相違点があります。主な違いは、CKCR がスケーラブルなデータ検証/修正に対する一般的なアプローチを提供することです。このスケーラビリティにより、共通レイヤで共通データについてより多くの記事を実行できます。たとえば、上記の例の imgCdnUrl は、優れた CDN スケジューリングのための統合フック ポイントです。
CKCRの内部構造と文法規則
以上がCKCRの基本的な機能です。その後、アプリケーションで、システムのさまざまなシナリオで、システム コア データ出力のデータ構造がほぼ同じであることがわかりました。したがって、CKCR 記述文字列の再利用性が問題になります。
この問題を解決するために、nice は CKCR コンパイルの前に前処理メカニズムを導入しました。固定データ構造の説明は、特別な構文を通じて参照できます。このメカニズムの導入後、システムの中核となるデータ構造を簡素化するという追加の利点がもたらされました。
クライアント/サーバーのコラボレーションの問題は、このコンポーネントによって技術的に解決されます。では、人間のコラボレーションの問題をどのように解決するのでしょうか?
まず、CKCR の記述ルールは簡潔です。したがって、そのままインターフェースドキュメントとして出力することができます。
第二に、インターフェイス文書に基づいて、ナイスサーバーとクライアントRDの間のコラボレーションプロセスの明確な計画があります。
契約: 両当事者は RD と通信し、インターフェース契約に同意して文書を提供し、両当事者は設計段階に入ります。
フェイクデータ: サーバー RD は、クライアント RD の基本機能を自己テストするためのモックデータの疑似インターフェイスを迅速に提供します。
リアル インターフェイス: サーバー RD は、双方による共同デバッグのためのリアル インターフェイスを提供します。
この段階的な開発方法は、「共同デバッグがシャウトに依存している」という問題を基本的に解決します。両者の作業は基本的に分離されており、基本的には双方の開発進捗には影響を与えません。
CKCR オープンソース アドレス
CKCR このコンポーネントのソース コードは抽出され、github に配置されています。URL は http://t.cn/RGn57Xk です。
第 1 フェーズの概要
上記は、第 1 フェーズの 3 つの問題に対する Nice の解決策です:
階層化とモジュール化: 2 層アーキテクチャを通じて構造的問題を解決します。
クライアントアダプター: クライアントの違いの問題を解決します。
CKCR: CKCR とコラボレーション プロセスを通じて、クライアント/サーバー RD コラボレーションの問題が解決されます。
現段階では、開発上の問題は主に全体的な再構築を通じて解決され、将来のアーキテクチャ調整への道が開かれます。
当時の考え方は「全てを置き換えてやり直す」というもので、今思えば当時の状況を踏まえるとこの選択は正しかったです。その頃、私たちはシステムをリファクタリングしませんでしたが、システムが大きくなるにつれて、残された問題はさらに難しくなりました。
とはいえ、そうは言っても結局のところ、「リプレースと再構築」への道は依然としてリスクに満ちています。そのような決定を下す前に、適切なリソースとリスクの評価を行う必要があります。
それらの穴は安定のために埋められました
全体的な再構築を完了した後、nice はビジネスの急速な発展に入りました。私たちは 2015 年 3 月にも 1 か月間 SpeciaForce に取り組みました。研究開発チームのほぼ全員が会社の近くに住んでおり、作業負荷は 7*14 時間を超えていました。この期間のスプリントにより、製品の日々のアクティビティなどの重要なデータが改善され、インターフェースの PV も 1 日あたり 5 億のピークに達しました。
2015 年 8 月まで、サービスの安定性は大きなテストを受けました。正直に言うと、その時点で最も重要な問題は次のとおりです。
1. MySQL はそれを処理できません
nice の MySQL クラスターは、当初、単一のインスタンス、単一のデータベース、1 つのマスター、4 つのスレーブ、および機械式ハード ドライブで構成されていました。 2015 年 4 月、ビジネスが急速に成長している多くのチームと同様に、問題を迅速に解決するために、OP はすべての DB を SSD に置き換えました。そのメリットは非常に大きかったです。
また、単一データベースを考慮しているため、サービスを分離できず、メインデータベースへの書き込みもボトルネックになっています。 2015 年 3 月頃、Nice はデータベース/テーブルのシャーディングを検討し始めました。サブ図書館計画は主に垂直業務ごとに分かれています。
技術的負債は本当に多すぎます! ! !
分岐プロセス全体には 2 人の学生がほぼ半年かかりました。次に、システムのコア テーブルを分割するのにさらに約 4 分の 1 かかりました。
MySQL に関して、私たちのレッスンは次のとおりです。
ハードウェアの問題の解決は非常に費用対効果が高くなります。
図書館の事業分野を分割し、テーブルのサイズを評価することは不注意であってはなりません。事前に実行した場合はさらに数人日かかる可能性があり、後で実行した場合は、完了までにさらに 1 人年以上かかる可能性があります。
その一方で、nice は Redis にも大きく依存しています。データの一部は通常のキャッシュ使用量です。オンライン ビジネス アクセス キャッシュが存在しない場合、自動的に DB にフォールバックしてキャッシュをフラッシュします。データの別の部分は準永続データです。当社のオンライン ビジネスのこの部分は DB にフォールバックしません。
2. Redis では処理できません
nice の Redis も単一クラスターです。 2015 年の 4 月から 5 月頃、ビジネスの急速な反復と多くの新機能のリリースにより、Redis に対するプレッシャーが急速に高まり、Redis の障害が時折発生するようになりました。当時、Nice は Redis サービスの分割を開始しました。ビジネス モデルが比較的シンプルであるため、Redis の分割速度は比較的高速です。
しかし同時に、障害時のデータ損失のため、Redis の高可用性の観点から独自の開発を行うことにしました。主にスムーズな拡張や自動フェイルオーバーなどを目的としています。
この分野での経験が不十分なため、かなりの問題が発生しました。最も深刻だったのは、オンライン試運転段階では問題が見つからなかったが、フルキャパシティーに切り替えた後、複数のクラスターノードで次々と問題が発生したことです。 2日ほど悩んだ末、ついに耐えられなくなって元に戻りました。ただし、当時はマシン リソースの問題があり、一度に切り替えることはできず、クラスターごとに切り替え、複数の RD を使用してほぼすべての準永続データの回復スクリプトを作成するしかありませんでした。
Redis で学んだ教訓は非常に痛ましいもので、2015 年の落とし穴の経験から判断すると、私たちの利益は次のとおりです。
圧力と能力の評価の経験
圧力関連の問題は、やはり分離/分割アプローチを使用して解決する必要があります。
基本的なサービスの監視は必須です。CPU、メモリ、ディスク、帯域幅などの基本的なリソースを監視するコストは高くありませんが、多くの場合、問題を事前に発見するのに役立ちます。
サービスの能力評価には慎重な検討が必要です。オンラインビジネスの場合、DBのキャッシュビジネスへのフォールバックが発生し、障害後の侵入リスクに注意する必要があります。
データ関連の経験
準永続データの場合、Redis に災害復旧計画がない場合は、完全なデータ復旧のためのレコードを準備するのが最善です。そうしないと、何か問題が発生した場合、コードを書くだけでひざまずくことになります。
オンライン データを移動したい場合は、ロールバック計画を準備する必要があります。そうしないと、何か問題が発生した場合に大惨事になる可能性があります。
最後に、独自の研究開発について話しましょう。技術規模が達成できないという前提の下で、既存の成熟したソリューションを使用することをお勧めします。たとえ厳しい条件が揃ったとしても、あらゆる段階で細心の注意を払う必要があります。
3. フロントエンド マシンは耐えられません
最後の質問は、フロントエンド マシンの圧力です。
まず第一に、スタートアップ企業が比較的小規模な場合、一般にアクセス層の問題は少なくなりますが、それでも「悪者」に対する基本的な予防策や計画を立てることをお勧めします。
フロントエンド クラスターを見ると、私たちが遭遇した問題は基本的に 2 つのカテゴリに分類できます。
クライアントのポーリングに問題があり、ユーザーがサーバーに対して大量のリクエストを行っています。
バックエンド サービスが失敗すると、フロントエンド マシンの処理が遅くなったり、単に接続できなくなったりします。これにより、フロントエンド マシンのプロセス プールが簡単にいっぱいになる可能性があります。
サービスリソースを分割し、業務をモジュール化しているため、比較的対応が容易です。一般的な考え方は次のとおりです。
フロントエンドマシンはビジネスに従ってグレード分けされています。通常、中核事業の変化は少なく、他の事業の変化による障害が中核事業に影響を与えることは避けられます。
ダウングレード: 問題が発生した場合は、オンラインですぐにダウングレードできる一連のプランが用意されています。主に 2 つの方法があります。
a. リクエスタ: 特定のユーザー グループまたは特定のビジネスの問題に対応する場合:
b. 依存するバックエンド サービスが失敗する。
バックエンド サービスの災害復旧: 現在、nice はバックエンド サービス (MySQL/Redis 内部サービス用) のフェイルオーバーを行うために LVS のレイヤーを追加しています。フロントエンド アプリケーション側 バックエンド サービスのスコアリング メカニズムにより、アプリケーション側でのみ検出できる問題が無視されるのを防ぎます。
上記の 2 つの段階を完了してください。現在のサーバーサイドアーキテクチャの状況はおおよそ次のとおりです。
nice 現在の問題点と次のステップ
2015 年 8 月以降、RD と OP の共同努力により、サービスの安定性の問題は保証されています。同時に、技術チームは急速に成長し、完全なデータおよび戦略チームを擁しています。複数の当事者がドッキングする過程で、サービス化は徐々に重要性を増していきます。
さらに、私たち自身のチームの規模も拡大しており、すべてのオンラインビジネスコードが一緒になり、時には10人以上が一度に変更を加えなければならないこともあります。コードベースの結合も明らかな問題となっています。
Nice が現在直面している最も重要な問題は、サービス化とコード分割です。
この問題に対し、現在の当社の基本的な考え方は以下の通りです。
サービス指向であり、万能ではありません。サービスのリモート呼び出しをサポートしながら、同じマシン上の現在の展開もサポートできます。サービスが多すぎたり、サービス管理の問題が時期尚早に発生したりすることは避けてください。
コード分割、アプリケーション開発フレームワークのアップグレード。ライブラリ/フレームワーク/ビジネスを分離し、独立して保守し、ライブラリの依存関係管理ツールを導入します。
起業家精神に参加して1年以上の間。たくさんの洞察があります。
起業家精神は生き方です。いつでもさまざまな問題に直面しますが、その中には得意なこともあれば、不得意なこともあります。しかし、何があってもステップアップしなければなりません。なぜなら、自分で選んだのであれば、それに耐えなければならないからです。
この共有は主に現実的な問題についてのものであり、同じように起業家精神に携わっている友人がこの共有を見た後、寄り道をしないように願っています。
学びましょう!
全然分かりません
応援してます! ! ! !
ちょっと理解できません、まだまだ学ぶことがたくさんあるようです
ちょっと理解できない
文章が上手い