web-dev-qa-db-ja.com

Javaでスケーラビリティの高いWebサービスを設計するにはどうすればよいですか?

2000人の同時ユーザーがいるWebサービスをいくつか作成しています。これらのサービスは無料で提供されるため、大規模なユーザーベースを獲得することが期待されています。将来的には、最大50,000ユーザーまで拡張することが必要になる可能性があります。

- https://stackoverflow.com/questions/2567254/building-highly-scalable-web-services のような問題に対処する他のいくつかの質問がすでにあります

ただし、私の要件は上記の質問とは異なります。

たとえば、私のアプリケーションにはユーザーインターフェイスがないため、画像、CSS、JavaScriptは問題になりません。これはJavaにあるため、HipHopを使用してPHPをネイティブコードに変換するなどの提案は役に立ちません。

したがって、私は個別に質問することにしました。

これは私のプロジェクト設定です-

  1. Apache CXFを使用したRESTベースのWebサービス
  2. Hibernate 3.0(遅延読み込みや調整用のカスタムHQLなどの関連する最適化を使用)
  3. Tomcat 6.0
  4. MySql 5.5

Javaベースのアプリケーションをスケーラブルにするために遵守するベストプラクティスは何ですか?

15
Kshitiz Sharma

私は過去に問題に対処しましたが、それでも現場で学ぶべきことがたくさんあると感じています。これは、今日のソフトウェア開発で最も興味深い分野の1つであると思います。これについての考えをいくつか次に示します。
MySQLはfair十分なデータベースであり、大量のデータを処理している場合を除きます。この場合、NoSQLデータベースを検討します。ただし、yourのニーズに最適なNoSQLデータベースを慎重に検討する必要があります。

システムでキャッシングを実装する必要があります-可能な限り多くの読み取り専用データをキャッシュするか、いくつかのキャッシング戦略を定義してください-たとえば、ユーザーが見るのに有効なシナリオがありました最近の更新が過去1時間に行われた限り、「古いデータ」。
私は、JBoss Cache、または多分 Infinispan (これは分散データ構造のようなもの)または他の一般的なキャッシュフレームワークを検討します。
さらに、Tomcatについて説明したように、私はあなたがいくつかの要求/応答モジュールで作業していることを前提としています。特定のリクエストのスコープに存在するキャッシュを使用することを検討してください。これは、 スレッドローカルストレージ に関連付けられている単純なHashMapでもかまいません。
ここでの私の考えは、 休止状態の1次キャッシュ によく似ています。

ファイル、トランザクション、その他のリソースは、開いたままにしておくという点でコストがかかることに注意してください。できるだけ早くファイルとトランザクションを閉じてください。そうしないと、大規模なセットアップで再現されるバグが発生します。

さらに、2000人の同時ユーザーについて理解する必要があります。これは、2000人のユーザーが一度にサーバーにアクセスしているのですか、それともシステムを使用しているのですか? 2000人のユーザーがサーバーへのソケットを開こうとするケースと、500人だけが現在1500人がクライアント側で入力を埋める結果を見ているケースを区別します。

クラスタリングの使用を検討する必要があります- ロードバランシング 、スティッキーセッションのような問題に対処する必要があります(つまり、ロードバランサーは同じセッションの同じサーバーにリクエストをリダイレクトします)もっと。

同期コードが必要な場合-同期戦略を慎重に選択してください。単純なロックが使用されているシステムをいくつか見ましたが、 ReaderWriterLock は、ほとんどのアクセスが読み取り専用であるため、改善される可能性があります。

可能な場合はクライアント側のキャッシュと検証を検討し、サーバーへの呼び出しを保存して、同じパラメーターを持つ要求に対するほとんどの応答が変更されない場合に備えて、データの違いのみを送信するようにしてください。
たとえば、 oVirt オープンソースプロジェクトでは、特定の仮想マシンの統計情報を取得するように要求します。 VMのデータの一部はめったに変更されないため、そのMD5のみを送信します。データが変更された場合、MD5値も変更された場合は、完全なデータを取得するリクエストを実行します。 MD5だけではありません。

前にhibernateについて説明しました-使用を慎重に検討することをお勧めします-多くの書き込みを実行し、読み取りを少なくする必要がある場合、Hibernateは理想的ではない可能性があります。 Spring-JDBC JDBCのラッパーとして。

データベースを適切にインデックス化し、正しいデータベーススキームを使用します。プリコンパイルおよび最適化されているため、ストアドプロシージャのレイヤーの使用を検討してください。

過去に、jboss 4.2.1を使用してmysql(主に読み取り専用アクセス)でシステム(単一ノード)を処理し、2000人の同時ユーザーに到達するようにしたことを述べたいと思います
(サーバーに対して2000ソケットを開くという点で一度にアクセスするのではありません)が、システムの使用/閲覧、JBoss Cacheの使用、キャッシュへのプリロード、最もアクセスされたデータの一部、またはデータの認識「人気があり人気がある」が私たちのソリューションは私たちのアーキテクチャとフローに適していました、
このように私が言うように-
ヒントやコツは他にもありますが、それは実際にはアーキテクチャと、システムに必要なフローに依存します。幸運を!

8
zaske

良い質問。どちらが最善のアプローチであるかはおそらく難しいですが、私の経験から試してみます。

JavaベースのWebアプリケーションをスケーリングする最良の方法は、可能な限りステートレスで記述することです(可能な場合)。これにより、アプリケーションを水平方向にスケーリングでき、Tomcatサーバーを追加できますより多くの同時ユーザーです。

ただし、ご指摘のとおり、データベース接続に問題がある可能性があります。しかし、私が持っている質問は、どのようにデータを取得しているのですか?ユーザー生成ですか、それともサードパーティからデータを取得しますか?サードパーティのアプリケーション(FB、Twitterなど)から集約されたデータを使用してユーザーにサービスを提供している場合、フォローできるのは、マスターデータベースに書き込み、スレーブデータベースにデータを複製するためです。各Tomcatインスタンスに割り当てられます。次に、各Tomcatサーバーは独自のスレーブデータベースから取得できます。

 Are there faster alternatives to Mysql?

インメモリデータストアを持つMySQLクラスターに行くことができます。ただし、アプリケーションに変更が必要な場合があることに注意してください。 sql joinsは、MySQLクラスターでは十分にサポートされていませんが、最新バージョンでは同じ機能が改善されています。コストが要因ではない場合は、Oracleを試すことができます。

キャッシングソリューションは間違いなくパフォーマンスを向上させます。しかし、それはすべてアプリケーション全体のアーキテクチャに依存します。いつデータをキャッシュにプッシュするか、いつダーティにするか(キャッシュから削除するか)を十分に理解しておく必要があります。

マルチサーバー環境での負荷分散については、Apacheを使用してロードバランシングを行うよりも、ロードバランサーを使用することをお勧めします。

3
Chandra

私は現在(プロレベルで)同様のシステムをセットアップしており、これが私が選択したデザインです。

  • 2つのNginxロードバランサー(両方がアクティブで、どちらもフェイルオーバーされており、DNSラウンドロビンでバランスが取れている)
  • マスターマスターレプリケーションモードの2つのMySQLデータベース
  • Tomcatクラスターとしての2つのTomcatインスタンス
  • Tomcatクラスターのキャッシングとセッション状態共有の両方のための2つのMemcachedインスタンス

これにより、冗長性のある高可用性でスケーラブルなソリューションが実現します。

(まともなハードウェア上の)ロードバランサーは、飽和した1 Gbpsのラインをそれぞれ簡単にロードバランスします。これは、SSLオフロードにも最適な場所です。

セッション情報はmemcachedに保存できます。 Tomcatインスタンスが失敗した場合、別のTomcatインスタンスが関連するセッション情報を取得できるため、クライアントは何も気づきません。これをスティッキーセッションと組み合わせることも忘れないでください。 (ネットワークトラフィックを抑えるため)

Tomcatクラスタリングには、memcachedを使用せずに、クラスター間でリアルタイムにセッション情報を共有するオプションもあります。パフォーマンスは良いと思いますが、Memcachedを使用する方が良いでしょう。

これらのアプリケーションでさらにパワーが必要な場合:

  • Nginx:ロードバランサーを追加しますが、これがすぐにボトルネックになるとは思いません。
  • Tomcat:Tomcatクラスターのサイズを簡単に増やしたり、クラスターを追加したりできます
  • Mysql:読み取り専用スレーブを追加するか、クラスターサイズを増やします(アプリケーションによって異なりますが、RESTベースのアプリケーションを作成したため、これは問題にはなりません)
  • Memcached:ノードを追加すると、Memcachedはかなりうまくスケーリングすると思います。

私はあなたのアプリケーションがどのように構築されているか、そして大きなリソースが何であるかを知りませんが、(負荷テスト中に!)データベースの負荷が高い場合は、アプリケーションとデータベースの間にキャッシュを追加するとパフォーマンスが大幅に向上します。ただし、すべてがキャッシュ可能であるとは限らないことを忘れないでください。クエリが常に異なる場合、キャッシュは役に立ちません(多くの場合)

私のアドバイスは、VMware Workbench(またはsimilair仮想化ソフトウェア)をダウンロードして、簡単なセットアップを作成することです。ロードバランシングやクラスタリングは必要ありません。基本とそこから機能します。 1つずつ追加の機能(バランシング、キャッシング、クラスタリングなど)を追加し、必ず各トピックについていくつかの調査を行って、正しい選択をしたことを確認してください。

このプロセス中に同じパフォーマンステストを実行し続ける場合は、[〜#〜] x [〜#〜]の使用が[〜#〜]の使用よりも優れているかどうかをご自身で確認できますy [〜#〜]設定、またはキャッシングによる影響など.

結局のところ、このような設定はアプリケーションとそのクライアントの要件に大きく依存し、すべてがさまざまな方法で実行でき、それぞれに独自の長所と短所があります。

他に質問は?

幸運を!

ウェズリー

2
Wesley