質問

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

(注記:について学んだばかりで、 ビッグオー表記, ここではプログラミングの原則をさらに集めてみたいと思います。以下に私自身の質問に答えることで Big O Notation を説明しようとしましたが、コミュニティにはこの質問と回答の両方を改善してもらいたいと思っています。)

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

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

役に立ちましたか?

解決

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

最初にできるだけ単純なコードを構築し、次にシステムのプロファイリングを行い、明らかなパフォーマンス上の問題がある場合にのみ最適化します。

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

他のヒント

さて、「ビッグオー記法」を使用する上で重要なポイントを押さえました。これは、注意を払わないと確実に後部に刺さる可能性がある次元の1つです。また、一部の人々には「ビッグオー」メガネを通しては見えない他の次元も作用しています(しかし、よく見ると実際には見えています)。

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

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

browser -> web server -> app server -> DB -> app server -> XSLT -> web server -> browser JS engine execution & rendering

ボックスや 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 と場所.居住者)。データ構造が複雑になればなるほど、OR マッパーの効率は低下します。ある時点で、特定のパフォーマンスやスケーラビリティをさらに絞り出すために、1 回限りの状況で餌をやめ、より...ええと...原始的なデータ アクセス アプローチ (ストアド プロシージャ + データ アクセス層) を実行する必要があるかもしれません。醜いモジュール。かかるコストを理解し、意識的に決定してください。

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

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

  7. キャッシュは、エンジンへの負担を軽減する優れたツールです (速度とスループットの向上は便利な副作用です)。ただし、メモリ使用量と、キャッシュが古い場合にキャッシュを無効にする複雑さの点でコストがかかります。私の決断は、完全にクリーンな状態から始めて、有益だと判断した場合にのみキャッシュを徐々に追加することです。複雑さが過小評価されることが多く、パフォーマンスの問題を解決する方法として始めたものが機能的な問題を引き起こすことが判明します。また、データ使用量のコメントに戻ります。毎分ギガバイト相当のオブジェクトを作成している場合、キャッシュするかどうかは関係ありません。すぐにメモリ使用量が最大になってしまい、ガベージ コレクションによって 1 日が台無しになってしまいます。したがって、重要なのは、仮想マシン内で何が起こっているのか (オブジェクトの作成、破棄、GC など) を正確に理解し、最善の決定を下せるようにすることだと思います。

冗長ですみません。ちょうど転がっていて、見上げることを忘れていました。これがあなたの質問の精神に触れるものであり、あまりにも初歩的な会話ではないことを願っています。

さて、こんなブログがあります 高い拡張性 このトピックに関する多くの情報が含まれています。いくつかの便利なもの。

多くの場合、これを行うための最も効果的な方法は、スケーリングを一部として考慮した設計を行うことです。

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

これを使用して開発作業に集中します

FWIW、ほとんどのシステムは、問題になるまでこれを無視することで最も効果的に拡張できます。ムーアの法則は今でも有効であり、トラフィックがムーアの法則よりも速く増加していない限り、通常は、より大きなボックスを購入するほうが安くなります (1 台あたり 2 ドルまたは 3,000 ドル)ポップ)開発者にお金を払うよりも。

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

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

1 つの良いアイデアは、追加タスクごとにどれだけの作業が発生するかを判断することです。これはアルゴリズムの構造によって異なります。

たとえば、都市に数台の仮想車があると想像してください。いつでも、各車にすべての車の位置を示す地図が必要になります。

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

    for each car {
       determine my position;  
       for each car {  
         add my position to this car's map;  
       }
    }

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

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

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

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

    for each car {  
      add my position to a list;  
    }  
    for each car {    
      give me an updated copy of the master list;  
    }

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

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

この概念はスケーラビリティのみを考慮しており、各車両のステップ数の最適化は考慮していないことに注意してください。ここでは、車 1 台につき 5 歩かかるか 50 歩かかるかは気にしません。重要なのは、N 台の車が (X * N) 歩かかるのではなく、(X * N) 歩かかるということです。2).

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top