Javaで高度にスケーラブルなWebサービスを設計する方法は?


15

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

/programming/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ベースのアプリケーションをスケーラブルにするために従うべきベストプラクティスは何ですか?


RESTサービスを公開している場合、Varnishのようなリバースプロキシを使用すると非常に役立ちます。データはどれくらい新しい必要がありますか?リレーショナルデータベースが必要ですか?データを分割できますか?説明しているテクノロジースタックを使用して、実際にエンドポイントにヒットするリクエストをできるだけ少なくすることに重点を置きます。Hazel cast / Gigaspacesなどのソリューションを使用して、このインメモリを検討しましたか?
ebaxt

@ebaxtの提案に感謝します。Gigaspacesはオープンソースのようです。しかし、ヘイゼルキャストは面白そうです。
Kshitizシャルマ

1
@ebaxt「リレーショナルデータベースが必要ですか?」nosqlを採用すると、アプリケーションアーキテクチャが大幅に変わります。複雑さを最小限に抑えようとしています。しかし、コストは私たちにとっての要因ではありません。したがって、リレーショナルアプローチに固執します。
Kshitizシャルマ

1
Postgres、MySQL、その他何でも使用できます。インフラストラクチャはどうですか?ディスクアレイを使用できますか?サーバーは同じ場所でホストされていますか?クラスターをハートビートなどで接続できますか?それらを同じサブネットに配置できますか?
エド

1
私もプログラマーです。しかし、リレーショナルデータベースがボトルネックである場合、この質問に終わる傾向があります。市場には、状況によっては他のデータベースよりもパフォーマンスの良いデータベースがあります。しかし、彼らは別のデフォルトのトランザクション分離レベルとペシミスティック並行など対楽観的同時実行を使用している
edzeを

回答:


8

私は過去にこの問題に対処しましたが、それでもこの分野で学ぶべきことがたくさんあると感じています。:私はここに、今日ではソフトウェア開発であり、これについていくつかの考えがあるの最も興味深い分野の一つであることがこれを見つける
MySQLがある公正あなたがデータの大規模な膨大な量で作業している場合を除き、十分なデータベース、およびこのような場合には、あなたはのNoSQLを検討するかもしれませんただしニーズに最適なNoSQLデータベースを慎重に検討する必要があります。

システムにキャッシングを実装する必要があります-できるだけ多くの読み取り専用データをキャッシュするか、いくつかのキャッシング戦略を定義してください-たとえば、ユーザーが「古いデータ」を次のように表示できるシナリオがありました最近の更新が最後の1時間に行われた限り。
私は、JBoss Cache、またはInfinispan(分散データ構造に近い)またはその他の一般的なキャッシュフレームワークを検討します。
さらに、Tomcatについて述べたように、リクエストレスポンモジュールで作業することを想定しています。特定のリクエストのスコープ内に存在するキャッシュの使用を検討してください。これは、スレッドローカルストレージに関連付けられた単純なHashMapでさえあります
ここでの私の考えは、Hibernateの1次キャッシュに非常に似ています

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

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

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

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

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

多分での作業あなたは書き込みの多くを実行する必要がある場合には、あまり読み、Hibernateはあなたのための理想的ではないかもしれない、とあなたが考慮しなければならない-私は慎重にそれを使用することを検討することができreocmmendだろう-私は前に休止状態に述べた春JDBCラッパーを超えるとJDBC。

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

過去に、jboss 4.2.1でmysql(ほとんどの読み取り専用アクセス)上のシステム(単一ノード)を扱い、2000ユーザー
(サーバーに対して2000ソケットを開くという点では一度にアクセスしません)、しかし、システムを使用/閲覧し、JBoss Cacheを使用し、最もアクセスされたデータの一部をキャッシュにプリロードします。 「しかし、私たちのソリューションはアーキテクチャとフローに適していた
ので、これらのケースで述べたように
、さらにヒントとコツがありますが、それは本当にアーキテクチャとシステムに必要なフローに依存します。幸運を!


ストアドプロシージャを除き、ストアドプロシージャを使用しないことに同意します。また、並行ハッシュマップとアトミック値を使用して、スレッドセーフにすることができます
-NimChimpsky

3

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

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

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

 Are there faster alternatives to Mysql?

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

キャッシングソリューションは間違いなくパフォーマンスを改善します。ただし、それはすべて、アプリケーション全体のアーキテクチャに依存します。キャッシュにデータをプッシュするタイミング、ダーティにする(キャッシュから削除する)タイミングを十分に認識する必要があります。

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


「ロードバランシングにApacheを使用するよりもロードバランサを使用することをお勧めします」Apacheではない場合、どのアプローチ/ソフトウェアをお勧めしますか?
Kshitizシャルマ

基本的に、ネットワーク管理者が構成できるロードバランサーハードウェアを推奨していました。このコースには、プロジェクトに追加費用がかかります。このロードバランサーには独自のIP(仮想IPとも呼ばれます)があり、基本的にはこのIPをドメインに割り当てます。要求が来ると、これは接続されているすべてのサーバーにラウンドロビン(他のアルゴリズムも利用可能)方式でルーティングします。ハードウェアがオプションではない場合、この目的のためにapacheを使用できますが、この目的のためだけにapacheを調整する必要がないので、ハードウェアをお勧めします。

同じことを行うために、httpdを備えた専用サーバーを使用しています。ハードウェアは問題ではありません。
Kshitizシャルマ

正しく覚えていれば、httpdとmod_clusterを使用できます。httpdとmod_clusterをチェックする前に、ハードウェアLBの「過剰」ソリューションに進む前に慎重に検討します

@zaske-おそらく、ハードウェアロードバランサーは多すぎると思います。ただし、スケールアップが必要な場合は、サーバーを追加することで簡単に行えます。

2

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

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

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

(まともなハードウェア上の)ロードバランサーは、飽和した1ギガビットの回線をそれぞれ簡単に負荷分散します。これは、SSLオフロードにも最適な場所です。

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

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

これらのアプリケーションのいずれかでより多くの電力が必要な場合:

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

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

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

このプロセス中に同じパフォーマンステストを実行し続けると、セットアップでXを使用する方がYを使用するよりも優れているかどうか、キャッシュにどのような影響があるかなどを確認できます。

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

他に質問は?

幸運を!

ウェズリー


ハシバミ?hazelcast.com
NimChimpsky

キャッシングレイヤーにフレームワークを使用しますか、それとも単にSQLクエリで多数の手動ハッシュを使用しますか?
-djechlin
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.