8

一般に、アプリケーションを適切にスケーリングするには、どのような設計上の決定が必要でしょうか?

(注: Big O Notationについて学んだばかりなので、ここでプログラミングのより多くの原則を収集しようとしています。以下の私自身の質問に答えて Big O Notation を説明しようとしましたが、コミュニティにこの質問と両方を改善してもらいたいです。回答。)

これまでの回答
1) スケーリングを定義します。仮想環境で多数のユーザー、トラフィック、オブジェクトをスケーリングする必要がありますか?
2) アルゴリズムを見てください。彼らが行う作業量は、実際の作業量 (つまり、ループする項目の数、ユーザー数など) に比例しますか?
3) ハードウェアを見てください。アプリケーションは、1 台のマシンが追いつかなくなった場合に複数のマシンで実行できるように設計されていますか?

二次的な考え
1) あまりにも早く最適化しすぎないでください - 最初にテストしてください。思わぬところでボトルネックが発生するかもしれません。
2) スケーリングの必要性がムーアの法則を上回らない可能性があり、ハードウェアのアップグレードはリファクタリングよりも安価になる可能性があります。

4

7 に答える 7

11

私が言える唯一のことは、最初からクラスターにデプロイできるようにアプリケーションを作成することです。それ以上のものは、時期尚早の最適化です。最初の仕事は、スケーリングの問題が発生するのに十分な数のユーザーを獲得することです。

最初にできる限り単純なコードを作成し、次にシステムをプロファイリングして、明らかなパフォーマンスの問題がある場合にのみ最適化します。

多くの場合、コードのプロファイリングからの数字は直感に反します。ボトルネックは、遅くなるとは思わなかったモジュールに存在する傾向があります。最適化に関しては、データが王様です。遅くなると思われる部分を最適化すると、間違った部分を最適化することがよくあります。

于 2008-09-03T09:41:49.140 に答える
6

わかりました。これで、「big O 記法」を使用する際の重要なポイントに到達しました。注意を怠ると、それは確かに後ろから噛まれる可能性のある1つの次元です. 一部の人々が「大きなO」メガネを通して見ない他の次元も作用しています(しかし、よく見ると、それらは実際に見えます).

そのディメンションの簡単な例は、データベース結合です。たとえば、SQL をより効率的に実行するのに役立つ左内部結合の構築には、「ベスト プラクティス」があります。リレーショナル計算を分解したり、説明計画 (Oracle) を見たりすると、どのインデックスがどの順序で使用されているか、テーブル スキャンやネストされた操作が発生しているかどうかを簡単に確認できます。

プロファイリングの概念も重要です。非効率性を特定して修正するには、アーキテクチャのすべての可動部分にわたって適切な粒度で徹底的に計測する必要があります。たとえば、アプリと DB の間の OR マッパーと共に、AJAX とクライアント側処理を自由に使用して、3 層、マルチスレッド、MVC2 Web ベースのアプリケーションを構築しているとします。単純化された線形の単一のリクエスト/レスポンス フローは次のようになります。

ブラウザー -> Web サーバー -> アプリ サーバー -> DB -> アプリ サーバー -> XSLT -> Web サーバー -> ブラウザー JS エンジンの実行とレンダリング

ボックスおよび OS レベル (CPU、メモリ、ディスク i/o、など)、ただし、各層のサービスに固有です。したがって、Web サーバーでは、使用している Web サーバーのすべてのカウンターを知る必要があります。アプリ層では、それに加えて、使用している仮想マシン (jvm、clr など) を可視化する必要があります。ほとんどの OR マッパーは仮想マシン内でマニフェストを実行するため、そのレイヤーで表示される場合は、すべての詳細に注意を払うようにしてください。DBの内部では、すべてを知る必要があります実行されているものと、DB のフレーバーに固有のすべてのチューニング パラメーター。あなたが大金を持っているなら、BMC Patrolはそのほとんどにかなり良い賭けです(適切な知識モジュール(KM)を備えています)。安価なエンドでは、確かに自分でロールバックできますが、マイレージは専門知識の深さによって異なります.

すべてが同期している (待機する必要があるキューベースの処理が行われていない) と仮定すると、パフォーマンスやスケーラビリティの問題が発生する可能性がたくさんあります。しかし、あなたの投稿はスケーラビリティに関するものなので、Web サーバーから別の要求/応答を呼び出すリモート XHR 呼び出しを除いて、ブラウザーを無視しましょう。

この問題の領域を考えると、スケーラビリティを支援するためにどのような決定を下すことができるでしょうか?

  1. 接続処理。これは、セッション管理と認証にもバインドされています。セキュリティを損なうことなく、できるだけクリーンで軽量でなければなりません。メトリックは、単位時間あたりの最大接続数です。

  2. 各層でのセッション フェイルオーバー。必要かどうか?各層は、何らかの負荷分散メカニズムの下で水平に配置されたボックスのクラスターであると想定しています。通常、ロード バランシングは非常に軽量ですが、セッション フェイルオーバーの一部の実装は、必要以上に重くなる場合があります。また、スティッキー セッションで実行しているかどうかは、アーキテクチャのより深いオプションに影響を与える可能性があります。また、Web サーバーを特定のアプリ サーバーに結び付けるかどうかも決定する必要があります。.NET リモート処理の世界では、それらをつなぎ合わせる方がおそらく簡単です。Microsoft スタックを使用する場合、2 層 (リモーティングをスキップ) を行う方がスケーラブルである可能性がありますが、実質的なセキュリティのトレードオフを行う必要があります。Java 側では、私は常に少なくとも 3 層を見てきました。それ以外の理由はありません。

  3. オブジェクト階層。アプリ内では、可能な限りクリーンで軽量なオブジェクト構造が必要です。必要なときに必要なデータだけを持ってきてください。不必要または余分なデータの取得を悪意を持って削除します。

  4. OR マッパーの非効率性。オブジェクト設計とリレーショナル設計の間にはインピーダンスの不一致があります。RDBMS の多対多構造は、オブジェクト階層 (person.address と location.resident) と直接衝突します。データ構造が複雑になるほど、OR マッパーの効率は低下します。ある時点で、特定の環境からより多くのパフォーマンスやスケーラビリティを絞り出すために、1 回限りの状況で餌を切り、より...ええと...プリミティブなデータ アクセス アプローチ (ストアド プロシージャ + データ アクセス レイヤー) を実行する必要がある場合があります。醜いモジュール。関連するコストを理解し、意識的に決定してください。

  5. XSL 変換。XML はデータ トランスポート用の正規化された素晴らしいメカニズムですが、非常にパフォーマンスの高い犬になることもできます。持ち歩いているデータの量、選択したパーサー、および構造の複雑さによっては、XSLT を非常に暗い隅に追いやることは簡単です。はい、学術的にはプレゼンテーション レイヤーを実行するための非常にクリーンな方法ですが、現実の世界では、これに特に注意を払わないと破滅的なパフォーマンスの問題が発生する可能性があります。XSLT だけでシステムがトランザクション時間の 30% 以上を消費するのを見てきました。追加のボックスを購入せずにユーザー ベースを 4 倍にしようとしている場合は、あまり良くありません。

  6. スケーラビリティのジャムから抜け出す方法を購入できますか? 絶対。認めたくないほど何度もそれが起こるのを見てきました。ムーアの法則 (既に述べたように) は今日でも有効です。万が一に備えて多めの現金を用意しておきましょう。

  7. キャッシングは、エンジンへの負担を軽減する優れたツールです (速度とスループットの向上は便利な副作用です)。ただし、キャッシュが古くなったときにキャッシュを無効にする際のメモリ フットプリントと複雑さの点でコストがかかります。私の決定は、完全にクリーンな状態から始めて、自分にとって役立つと判断した場所にのみキャッシュをゆっくりと追加することです。多くの場合、複雑さは過小評価されており、パフォーマンスの問題を修正する方法として開始されたことが、機能上の問題を引き起こすことが判明しています。また、データ使用のコメントに戻ります。毎分ギガバイト単位のオブジェクトを作成している場合、キャッシュするかどうかは問題ではありません。すぐにメモリ フットプリントを使い果たし、ガベージ コレクションで 1 日が台無しになります。要点は、正確に何を理解しているかを確認することだと思います。」

冗長で申し訳ありません。転がっていて、見上げるのを忘れていました。これがあなたの調査の精神に触れ、あまりにも初歩的な会話ではないことを願っています.

于 2008-09-16T21:21:31.017 に答える
4

High Scalibilityというブログがあり、このトピックに関する多くの情報が含まれています。いくつかの便利なもの。

于 2008-09-03T09:38:25.717 に答える
3

多くの場合、これを行う最も効果的な方法は、スケーリングがその一部である設計をよく考えることです。

スケーリングがプロジェクトにとって実際に何を意味するかを決定します。無限のユーザー数ですか? Web サイトでスラッシュドットを処理できますか? それは開発サイクルですか?

これを使用して、開発作業に集中してください

于 2008-09-03T09:38:39.757 に答える
2

Jeff と Joel がStack Overflow Podcast #19でスケーリングについて説明しています。

于 2008-09-03T09:33:13.360 に答える
1

良いアイデアの 1 つは、各追加タスクが作成する作業量を決定することです。これは、アルゴリズムの構造によって異なります。

たとえば、都市にいくつかの仮想車があるとします。いつでも、すべての車がどこにあるかを示すマップを各車に持たせたいとします。

これにアプローチする1つの方法は次のとおりです。

    各車の{
       私の位置を決定します。  
       各車の{  
         この車の地図に自分の位置を追加します。  
       }
    }

これは簡単に思えます: 最初の車の位置を見て、それを他のすべての車のマップに追加します。次に、2 台目の車の位置を見て、他のすべての車のマップに追加します。等。

しかし、スケーラビリティの問題があります。車が 2 台ある場合、この戦略では 4 つの「位置を追加」ステップが必要です。車が 3 台ある場合は 9 歩かかります。「位置の更新」ごとに、車のリスト全体を循環する必要があり、すべての車の位置を更新する必要があります。

各車に対して他にいくつの処理を行う必要があるかを無視すると (たとえば、個々の車の位置を計算するために一定のステップ数が必要になる場合があります)、N 台の車の場合、このアルゴリズムを実行するには N 2 回の「車への訪問」が必要です。 . これは、5 台の車と 25 のステップがある場合には問題ありません。しかし、車を追加すると、システムが動かなくなることがわかります。100 台の車は 10,000 歩、101 台の車は 10,201 歩になります。

より良いアプローチは、for ループのネストを元に戻すことです。

    各車の{  
      私の位置をリストに追加します。  
    }  
    各車の{    
      マスター リストの最新のコピーをくれ。  
    }

この方法では、ステップ数は N 2ではなく、N の倍数になります。したがって、100 台の車は 1 台の車の 100 倍の作業が必要です。10,000 倍の作業ではありません

この概念は、「ビッグ O 記法」で表現されることがあります。必要なステップ数は、「N のビッグ O」または「N 2のビッグ O 」です。

この概念はスケーラビリティのみに関係していることに注意してください。各車のステップ数を最適化するわけではありません。ここでは、車ごとに 5 ステップか 50 ステップかは気にしません。主なことは、N 台の車が (X * N 2 )ではなく (X * N) ステップを取ることです。

于 2008-09-03T09:56:07.500 に答える
1

FWIW、ほとんどのシステムは、問題が発生するまでこれを無視することで最も効果的にスケーリングします-ムーアの法則は依然として有効であり、トラフィックがムーアの法則よりも速く成長していない限り、通常はより大きなボックスを購入する方が安くなります($ 2または$ 3Kでpop) 開発者に支払うよりも。

とはいえ、注目すべき最も重要な場所はデータ層です。これは、アプリケーションのスケールアウトが最も難しい部分です。通常、信頼できる必要があり、クラスター化された商用データベースは非常に高価です。オープン ソースのバリエーションは、通常、正しく行うのが非常に難しいです。

アプリケーションのスケーリングが必要になる可能性が高いと思われる場合は、開発の比較的早い段階で memcached や map reduce などのシステムを調べるのが賢明かもしれません。

于 2008-09-03T09:57:30.320 に答える