どのように強力なバックエンドサービス?


  各プログラマのために、失敗は彼の頭の上にダモクレスの剣をぶら下げている、希望の問題を解決するための探求にすべてのプログラマの失敗を回避する方法を、敬遠されています。この問題のために、我々は、分析から建築設計、コード、テストの各視点、コードレビューの準備を要求することができ、オンライン、このような操作やメンテナンスなどのオンラインサービスは、自分の答えを与えています。私は多くが言っ願って、欠点、特定の視点から問題の理解について話を、2年間の限定されたインターネット体験、独自のバックエンドの作業と組み合わせます。
  当社のサービスのほとんどは、このような使用に消費者を与えるよう構成されており、他の人が提供するサードパーティのサービスに依存して、障害の各部分の内側かもしれなど、ビジネス・ロジック、アルゴリズム、データ、各種の、間に散在していますソース。失敗を避けるためにどのように?私は「ダウト第三者、準備の消費者は、自分自身を行います。」、一つの文章にまとめ

1つの疑わしいサードパーティ

  「すべてのサードパーティのサービスは信頼できない、」誇大広告は、サードパーティをお約束するものどんなに:信念に従います。この信念に基づいて、我々は次のアクションを持っている必要があります。

1.1良いビジネスプランのダウングレードを作る、すべての詳細が明らかに

  サードパーティのサービスがハングアップした場合どのようにしますか?当社の事業はまた、ハングアップに続きますか?この結果は、我々はダウングレードに良い計画を開発することができるかどうかを確認したいのか明確ではない、それは非常にサービスの信頼性を向上します。より良い理解につながるいくつかの例。
  たとえば、私たちが推薦サービスをパーソナライズんが、ユーザーは、ユーザーのパーソナライズされたデータの中心から取得する必要があり、ためにするために、スコアリングモデルに代入していますが、サービスセンターをハングアップならば、我々は、データを取得することはできませんので、お勧めしませんか?もちろん、我々はすべての詳細を明らかにするために、キャッシュ内のホット商品を置くことができません。
  別の例は、ニーズが第三者からとMySQLへの最新の更新データを取得することをデータ同期サービスを行うことですちょうど第三者は、2つの方法を提供します:1)一つは、メッセージ通知サービスは、変更後のデータのみを送信しています。 2)一つは、HTTPサービスで、我々は、データを取得するために、独自のイニシアチブを呼び出す必要があります。私たちは、高いリアルタイムので、同期のファッションニュースを選択し始めませんが、遅延の後にメッセージに遭遇したに送られたが、問題なく、珍しいもの、と私たちは日が経過したので、問題はすでに障害にアップグレードされます。合理的な方法は、メッセージが問題であったとしても、すべての詳細を明らかにすることなく、更新後のアクティブシンク時間を通じて確保するために、2つの同期方式、メッセージリアルタイムの更新のための方法は、httpイニシアチブ同期タイミングトリガー(例えば、1時間)を使用する必要があります。
  時々、サードパーティのサービス一見、通常のが、返されたデータが汚染され、その後、右のすべての詳細を明らかにする方法はありますか?一部の人々は、この時、データのサードパーティの通知、迅速な回復に加えて、基本的なだけ待つことができると言います。例えば、我々は転置インデックスを構築するためにデータを取得するために、サードパーティのインターフェースを呼び出す必要があるモバイル検索サービス側を、行う、サードパーティのデータエラーならば、私たちのインデックスが間違っていることになり、その後、偽のコンテンツからGoogleの検索サービス画面をリードしています。最速の半分の時間にサードパーティのデータ復旧サービスを、我々はまた、半分の時間のためのインデックスを構築する必要があり、時間の一時間以上の検索サービスが正常にそこに機能しないことができること、これは容認できません。それのすべての詳細を明らかにするには?我々のアプローチは、そのデータの汚染問題のサードパーティのデータソースが発生したら、我々初回停止スイッチインデックス構築、およびインデックスファイルの正常な初期のスナップショットに素早くロールバック、たとえデータ、インデックスファイルのスナップショット時からの全体量を保存することですない非常に新しい(おそらく1時間前)が、少なくとも、我々は、検索結果を確認する必要があり、かつ取引上特に大きな影響を与えることはありません。

1.2高速な失敗の原則に従って、タイムアウトを設定してください

  サービスコールの通常の応答時間にサードパーティのインターフェースは50ミリ秒、1日のサードパーティインターフェイスの問題で、要求応答時間の約15%がサービス負荷が10以上に舞い上がるない長い前に、2Sを超えると、応答時間が非常に遅いです当社のサービスにサードパーティのサービスは崩壊を引き起こしたこと。
  なぜそれがダウン着用していましたか?設定されていないタイムアウト!我々は、すべてのスレッドがビジーである場合、過剰の要求はキューに置かれ、スレッドプール、スレッド50のスレッドプールの最大数を使用して、同期呼び出しを使用します。サードパーティのインターフェースの応答時間が50ミリ秒程度であれば、スレッドはすぐにライブに自分の手で行うことができ、その後、次の要求を処理するが、残念ながら場合は、最後の2S、第三者インターフェースの応答時間の一定割合この50件のスレッドは、キューが大幅に全体的なサービス容量の減少で、その結果、要求の多くを蓄積する、突き止めることでしょう。
  正しいアプローチは、彼らは私たちが大きな影響を果たすサービスに問題はありませんので、にもかかわらず、議論や、200msのなどのサードパーティ短いタイムアウト時間を決定することです。

第三者、慎重に選ばれた再試行メカニズムを保護するために適切な1.3

  私たちは、再試行のメカニズムを使用するかどうかを慎重に検討するために彼らのビジネスと例外を結合する必要があります。たとえば、サードパーティのサービスを呼び出すために、例外を報告し、一部の学生は、あなたが再テスト結果がどのように、例えば、いくつかのビジネスは、ビジネスロジックが間違っを異常表す返され、これは間違っている、無責任直接再試行になりました異常;何らかの異常がインターフェイスのタイムアウト例外処理の効果によって配合されている場合や、ビジネスの組み合わせを決定する必要上、この時間は、時々再試行リアサービスを開始するためのより大きな圧力になる与える傾向があります。

2消費者への準備

  ここで再び、我々は信念を主張:「すべての消費者が飛んでいない」という関係なく、どのようなパーティの誇大広告を確保します。この信念に基づいて、我々は次のアクションを持っている必要があります。

2.1デザインの良いAPI(RPC、RESTfulな)、誤用を避けるために、

  過去2年間で貧困層インターフェースの原因から、直接または間接的に、失敗をたくさん見てきました。あなたのインターフェースは、多くの人が誤って使用している場合、単純なに見えたが、それは真剣に、独自のインターフェイスデザイン、インターフェースデザインを考慮しなければならないが、非常に深い知識は、私はあなたが良いAPI&なぜを設計する方法をジョシュア・ブロックのスピーチ」を見てお勧めしますそれは事項(どのように良いのAPIを設計すると、これは重要である理由)、「および」 JavaのAPIの設計チェックリスト 。 "
  以下は、私の経験についての簡単な話です。
A)インターフェース最小限の露出の原則に従ってください
  我々は多くを提供することができますどのくらいを消費者インタフェース、より多くのインタフェースは、現象の無差別使用しやすい提供するので、緩い唇は船の事を沈めます。さらに、インタフェースが公開には、より高いコストは、自分を維持します。
b)は、インターフェイスが何ができるかを消費者がそうさせてはいけません
  あなたは完全な操作を実行するために、私たち消費者インタフェースを複数回呼び出す必要がある場合は、インターフェイスのデザインは、問題がある可能性があります。唯一のgetData(int型のID)を提供する場合、データ・アクイジション・インターフェースなど、あなたは20時間のデータを取得する場合は、インターフェイスは、その後、サイドを使用し、それは、消費者のパフォーマンスの低下が、また、増加する理由だけではなく、私たちを呼び出すためのインターフェース20を介してループする必要があります当社のサービスへの圧力は、その後、getDataList(一覧<整数> idList)を提供し、インターフェースは明らかに必要です。
C)は避けてください長時間実行インターフェイス
  またはデータメソッドを取得するには、例えば:getDataList(一覧<整数> idList)は、ユーザIDのパス1ワットヶ月が来るようにと、私たちのサービスは、結果を出すために数秒を推定していなかったと仮定し、多くの場合、タイムアウトの結果、ユーザがどのようにコールします結果はタイムアウト例外で、どのように?そのような長さの制限の長さを制限することは、あなたがリストのidが長く、彼らが異常報告100以上で合格した場合、実行に時間を避けることができるように、それぞれが唯一、100のIDを渡すことができていること、100です。
  プラス、このような制限は、あなたは、消費者が明確にこのメソッドは、この制限を持っていることを知らせなければなりません。前誤用、ユーザー100以上の商品を購入するために、すべての商品のオーダーの下で情報を得るために、中央のインターフェースを呼び出すための商品注文サービスの必要性の例に遭遇したが、呼び出しが失敗したか、そこに異常は何も再生できませんでした情報の値、およびは、後の調査の前に長い時間が完了商品センターインターフェース長限界であることを学びました。
  どのように我々は制限を増やすことができ、それは、ユーザーがそれを誤用することはできませんでしたか?
  二つのアイデア:1)、ユーザIDとして呼び出し分割操作は、通過1Wするためにユーザ・インターフェースを助けるために、内部インタフェース100のIDリスト(長さ100毎)に分割し、そのように消費者内部シールド機構こと、サイクルを呼び出しています;消費者の透明性2)ユーザーが独自の分裂を行うことができ、我々のアプローチは限られていることをユーザーノウハウを聞かせする必要があるので、具体的な方法があり、サイクル呼び出しに書いた:1)などgetDataListWithLimitLength(一覧として、メソッド名を変更し、<整数> idList) ;; 2)メモを追加; 3)の長さが100以上、明らかに例外は、語られることは簡単で、スローされている場合。
d)の使用の原則へのパラメータ
  避けパラメータの長さが3よりも後に使用することが一般的に、長すぎるより困難である、それは私の議論はあまり、どのように行うことですと言われたのですか?まあクラスで書きます!
  また、連続パラメータの同じタイプのを避けるため、または誤用には非常に簡単。
  intなどの他の種類の誤用を回避するための方法であるようにString型を、使用しないようにしてくださいすることができます。
e)の例外
  インタフェースは、実装の中で最も現実的な問題を反映している必要がありますが、巧妙なコードを使用して、いくつかの特別な処理を行うことはできません。一部の学生は、多くの場合、例外の内側にスローされているものに関係なくは、撮影後に空のセットを返し、トライキャッチでインターフェースコードを参照してください。

1
2
3
4
5
6
7
公衆リスト<整数>試験(){
{試します
...
}キャッチ(例外e){
リターンCollections.emptyList();
}
}

  これは非常に多くの場合、自分の問題は、パラメータ、またはサービス側の内部的な問題を渡す知っているが、未知のかもしれないの誤用いったんはありません、消費者は非常に無力になります。

2.2フロー制御、回避乱用へのサービスによってトラフィックの分布、

  私は多くの学生が高いの同時サービスが同様の事件が発生したたことを信じている:君主の前日、突然そのインターフェイスはほとんど使用不可能ではありませんずっと後に、彼らの要求の10倍の量が突然インタフェースに上昇した、システム全体の崩壊につながる連鎖反応を引き起こします。
  なぜ10回上昇するだろう、それはインターフェースが部外者が攻撃されて、私の経験では、一般的に可能性が高い「犯罪を犯して」内部の人々を参照してくださいています。一部の学生は、毎分のMapReduceジョブオンラインサービス、サービスGaosiを呼び出す前に見てきました。
  このような状況に対処するには?人生は私たちに答えを与える:例えば、古いゲートは、誰かが超高電力デバイスを使用すると、ヒューズが様々な電流が焼損する強力ではありません保護するために爆破する、ヒューズをインストールされています。同様に私たちのインターフェースはまた、麻痺によって引き起こされる過度の圧力にシステムのための予想外の要求からシステムを防止するために、「ヒューズ」にインストールする必要があり、ときトラフィックの量は、あなたが取るか、または排水メカニズムを拒否することができます。具体的なアルゴリズムを制限する「を参照してください 練習を制限するインターフェイス 、」テキストを。

自分を行うには3

  自分で行うことは要求分析、アーキテクチャ設計、コーディング、テスト、コードレビューから、オンライン、オンラインサービスの運用および保守のフェーズは、コードが上書かれた、フレームワークの設計の下で、単純な共有の際に、拡大に焦点を当てている、非常に大きな話題です親指のいくつかのルール。

3.1単一責任の原則

  反映後ろに二年以上働いて、学生のために、設計モデルは、優れた外観を持つ必要があり、私は特定のデザインパターンの様々な重要ではないと思いますが、重要な原則です。例えば、単一責任の原則の様々な段階では、私たちの要求分析、アーキテクチャ設計では、など、コーディングすることは非常に有益です。
  要求分析段階では、単一責任の原則は、サービスが明確に定義されていない境界場合は、すべての合理的かつ不当な要求が接続されている場合、サービスはunmaintainable、非スケーラブルに現れるリードする、当社のサービスの境界を定義常に悲しい結末を障害します。
  アーキテクチャが懸念されるために、単一の責任も非常に重要です。、このような順序でサービス、検索、推奨インタフェースが含まれている;例えば、読み書きモジュールがサービス揺れが非常に強力な読みにつながる、一緒に入れている、もし別の読み取りと、それは非常に読みサービス(個別の読み取りと書き込み)の安定性を向上させます書きます私達の写真のサービスの別の例を、推奨は、注文の機能に影響を与え、この時間は別々のサービスに異なるインターフェースであり、かつ独立して展開することができる、そのような問題は、他のサービス(リソース隔離)に影響を与えないということがあり問題である場合別々のドメインを使用して、その他のサービス(静的および動的な分離)とは無関係に、CDN上に置きました。
  あなたのクラスは、より多くの事をした場合、ビューのコードポイントからは、クラスが一つだけ、私たちは離れて彼を考慮する必要があります。これの利点は、他のコードへの影響は非常に小さい、後で変更することは非常に簡単で、非常に明確です。そして、きめの細かい表情のクラスメソッド、メソッドが2つのだけのことをやっている場合にのみ機能である事を、行うもある改正が別の関数に機能に影響を与える可能性があるため、あなたは、それを離れて取ることができます。

3.2リソースの使用を制御

  我々はマシンのリソースが限られていることを認識した文字列のピンと張ったが、気にする書き込みコードにしてください。マシンのリソースは何?CPU、メモリ、ネットワーク、ディスク、などあなたが保護と制御の仕事をしない場合は、フル稼働でリソースたら、簡単にオンラインの問題につながることができます。

3.2.1 CPUリソースを制限するには?

a)の計算アルゴリズム
  サービスは、そのような注文サービスを推薦するように、コンピューティングの多くを必要とので、そのようなアルゴリズムの著者として、あなたのコンピューティングのアルゴリズムを最適化するようにしてください地理空間距離を頻繁に使用を計算するために使用される場合には、最適化、および良い結果を達成してきた、見ます「 最適な地理空間距離を計算し 、テキストを」。
b)のロック
  多くのサービスのために、それほどのリソースを消費するアルゴリズムを計算していないが、CPU利用率がロックの使用を見て、この時間が必要、高もあり、私の提案は、必要でない場合は、明示的なロックを使用しないでくださいされています。
C)習慣の問題を
  例えば、書き込みサイクル時間、時には誤って、一定の条件の下で、無限ループになって、あなたが適切に取り出すことが可能かどうかを確認してください、非常に有名な場合は「 マルチスレッドの無限ループの問題のHashMap 。」例えば、トラバーサル、文字列のパフォーマンスの低下のコレクションを横断+より合計文字列よりがある場合StringBuffer.appendかどうか、チェックするとき?
スレッドプールのd)のメイク使用
  スレッドプールによってスレッドの数を制限するには、あまりにも多くのスレッドがスレッドコンテキスト切り替えによるオーバーヘッドを回避します。
e)は、JVMのチューニングパラメータ
  JVMパラメータは、次のような、CPUの使用に影響を与えるだろう「 あなたがオンライン公開またはサービスを再起動して問題のジッタソリューション 。」

3.2.2リミットどのメモリリソース?

a)は、JVMパラメータ
  比較によるJVMパラメータを設定し、JVMパラメータチューニングの経験によって制限メモリ使用量に、私はテキストを書くために良い友人を持っている「を参照してください LinuxとJVMのメモリとの間の関係を分析します 。」
b)は、Javaクラスサイズのセットを初期化します
  初期サイズ、長いサービス接続リソースは、メモリのコストは、このサービスを最適化することが非常に重要であるとき、できるだけ多くを使用してJavaコレクション。
C)メモリ・プール/プールを使用して
D)スレッドプールを使用しては提供されなければならないときに、キューの最大長
  見ての前に障害の多くは、メモリ・オーバーフローにつながるキューの最大長さに制限を果たしていないことになっています。
e)のローカルキャッシュは、大規模なデータを使用しないようにする場合
  大量のデータは、あなたが彼らのサービスを回すことができるなどのRedis、TAIR、またはGCとして分散キャッシュを配置することを検討することができた場合は立ち往生。
f)はデータキャッシュを圧縮
  関連サービスの前に、お勧め行うときたとえば、あなたがユーザ嗜好データが直接6Gに短いテキスト圧縮アルゴリズムと直接12G場合は保存され、後にすることができる保存する必要があるが、その後我々は良いの圧縮および伸張アルゴリズムのCPU使用率、効率性を考慮しなければなりませんバランスの圧縮率、圧縮率が高いが、アルゴリズムのパフォーマンスの低下の一部、オンラインリアルタイムのコールには適していません。
  いくつかの連載を保存するために直接使用するprobuf後の時間、そのためには、メモリ空間を節約することができます。
g)を、サードパーティ製のソフトウェアの実装の詳細をクリア、微調整
  サードパーティ製のソフトウェアを使用して、そのような私たちのオリジナルのインデックスファイルの発見以前のように、私は完全に実用的な仕事に理解メモリを節約する方法の明確な詳細は、Luceneのソースコードを読んだ後に圧縮することができた後にのみ、そのときマニュアルに「を特に参照して、見つけることができない のLuceneインデックスファイルサイズの最適化の概要 」の記事。

3.2.3制限する方法ネットワークリソース?

a)のコール数を減らします
  コール数を減らしますか?しばしば紹介サービスにデータを取得するために行くための複数の場所で遭遇した場合、一般的な使用をして、多くの場合、そこにネットワークのオーバーヘッドを実現した場合、その後、彼らはループ内でバッチ処理を使用する必要があり、取得のRedis / TAIRで生徒を見ますこの時点でのデータ、CPUコストリソース、ネットワークリソースの消費量、多くの場合、実際に使用される方法は、大量のデータをオフライン最初の店にあるだけで、この時、オンラインサービスをフェッチするマルチスレッド並列はすべて、その要求限りすることができデータ収集。
b)は、データ送信の量を減少させます
  私たちは、データのすべての情報を対応するIDを返す場合は、1つの方法は、そのような頻繁に遭遇したのgetData(int型のID)として、必要とされている転送があり、送信を圧縮され、1人は必要ありません、そして第二に、データ伝送の量があまりにもあります大きな、この時間は、消費者のニーズに対応するフィールドに、サーバーが返すのみフィールドの上、送信側を使用して、のgetData(int型のID、リスト<文字列>フィールド)を変更することができます。

3.2.4リミットどのディスクリソース?

ログは、ボリューム、および定期的なクリーニングを制御するために戦います。1)プリントキーのみ例外ログ2)ログアラーム監視のサイズ。サードパーティのサービスに走ったがハングアップしたら、私は、その後、私はここに印刷し、サードパーティのサービスログの例外を呼び出していきます、私のサービスは、サードパーティのサービスは自動的に他のサービスを使用してハングアップする場合は、ダウングレードのシナリオに持っていたが、急にしています4)これまでのログを印刷等のログをクリーンアップするために、数日ごとのcrontabを使用して、定期的にログをクリーンアップするために)3;私がハングアップし、マシンを知るために見に乗ったことをアラームサービスを受信するための十分なディスクが原因とクラッシュではありませんより重要なログの一部の終了は、リモートログHDFSファイルシステムに直接印刷することができます。

3.3つの点を避けます

  1つのかごにあなたの卵を入れないでください!大部屋からリモートライブサービスの展開、という点で、よりレベルとすることができます。独自のデザインの観点から、サービスが展開のレベルを達成することができるはずです。
  多くのステートレスサービスの場合、nginxのことで、飼育係は、簡単に水平に拡張することができます。
  サービスジョブの種類によっては、どのように「を参照することができ、すべての後、唯一のノードで実行することができ、それの単一のポイントを避けるために、 クラスター分析の原則のクォーツアプリケーション 記事」。
  データサービスの場合は、単一のポイントは、どのようにそれを避けるために?要するに、断片化層状等によって達成することができ、後ボーエンの要約が存在するであろう。

4まとめ

  失敗を避けるためにどのように?私の経験では、一つの文に凝縮:「疑い第三者、準備の消費者を、自分で行う」、我々はまた、考えて、自分の経験を要約し、共有することができます。


おすすめ

転載: juejin.im/post/5df35fa2f265da33f63f5150