30台のサーバーから2台に切り替えた方法:Go

30台のサーバーから2台に切り替えた方法:Go



約3年前にIronWorkerの最初のバージョンをリリースしたとき、Rubyで記述され、APIはRailsで記述されていました。 しばらくすると、負荷が急速に増大し始め、Rubyアプリケーションの限界にすぐに達しました。 つまり、Goに切り替えました。 そして、詳細を知りたい場合は、続きを読んでください...



最初のバージョン


最初に、少し歴史があります。最初はSimpleWorkerと呼ばれるIronWorkerの最初のバージョンを作成しました(悪い名前ではありませんか?) 私たちは他の会社のためにアプリケーションを作成するコンサルティング会社でしたが、当時はアマゾンウェブサービスとRuby On Railsの2つの人気がありました。 そのため、Ruby on RailsとAWSを使用してアプリケーションを作成し、新しい顧客を獲得しました。 IronWorkerを作成した理由は、「かゆみをひっかく」ためです。 24時間年中無休でデータを送信するデバイスを使用するクライアントが複数あり、このデータを受信して​​有用なものに変換する必要がありました。 この問題は、1時間ごと、毎日など、データを処理するスケジュールで重いプロセスを開始することで解決しました。 私たちは、データを処理するために顧客ごとに個別のインフラストラクチャを絶えず調達および維持する必要なく、すべての顧客に使用できるものを作成することにしました。 したがって、「サービスとしてのハンドラ」を作成しました。これを最初にタスクに使用し、その後、おそらく他の誰かが同様のサービスを必要とすることを決定し、それを公開しました。 それでIronWorkerが生まれました。



サーバーへのプロセッサの常時負荷は約50〜60%でした。 負荷が増加したとき、プロセッサの負荷を約50%に保つためにサーバーを追加しました。 これは、非常に多くのサーバーに支払った価格に満足している間、私たちに適していました。 より大きな問題は、負荷サージへの対処方法でした。 負荷(トラフィック)の次のジャンプは、クラスタ全体を無効にする可能性のあるドミノ効果を作成しました。 通常の負荷よりも50%だけ高い負荷のこのようなジャンプ中、Railsサーバーはプロセッサを100%使用し始め、応答しなくなりました。 これにより、ロードバランサーはこのサーバーがクラッシュしたと判断し、他のサーバー間で負荷を再分配しました。 また、クラッシュしたサーバーのリクエストの処理に加えて、残りのサーバーはピーク負荷を処理する必要があったため、通常、次のサーバーがクラッシュするまで少し時間がかかり、バランサープールから再び除外されました。 すぐに、すべてのサーバーがダウンしました。この現象は、巨大なclusterf ** k( + Blake Mizerany )としても知られています。







当時のアプリケーションでこれを回避する唯一の方法は、サーバーの負荷を減らしてピーク負荷に備えるために、膨大な数の追加容量を使用することです。 しかし、それは莫大なお金を使うことを意味しました。 何かを変更する必要がありました。



書き直しました


APIを書き直すことにしました。 正直なところ、Ruby on Railsで書かれたAPIはスケーラブルではありませんでした。 Ruby on Railsよりもはるかに少ないリソースで多くのワークロードを処理できるJavaで同様のことを開発してきた長年の経験に基づいて、私はそれをはるかに改善できることを知っていました。 そのため、ソリューションはどの言語を使用するかによって決まりました。



言語選択


最後にやりたいことはJavaに戻ることだったので、私は新しいアイデアを受け入れました。 Javaは(そうでしたか?)パフォーマンスなど、多くの利点がある素晴らしい言語ですが、Rubyコードを数年間書いた後、どれだけ生産的にコードを書くことができるかを喜んでいます。 Rubyは、便利で理解しやすい、シンプルな言語です。



PythonやJavaScript / Node.jsなど、Rubyよりもパフォーマンスが優れた他のスクリプト言語(簡単でした)を調べました。 また、JVMベースのScalaとClojure、およびErlang(AWSを使用)やGo(golang)などの他の言語にも注目しました。 勝ちました 。 競争力が言語の基本的な部分であったことは素晴らしいことでした。 標準カーネルライブラリには、APIの構築に必要なほぼすべてが含まれていました。 容量が大きいです。 すぐにコンパイルされます。 Goでのプログラミングは素晴らしく、Rubyの場合と同様、最終的には数字は嘘をつきません。 プロトタイプを構築し、パフォーマンスをテストした後、Goで大きな負荷を問題なく処理できることに気付きました。 そして、チームとのいくつかの議論の後(「すべては順調です、Googleはそれをサポートします」)、Golangを使用することにしました。



最初にGoを試してみることにしたとき、それは危険な決断でした。 大規模なコミュニティはありませんでしたし、オープンソースプロジェクトの数も多くありませんでした。実稼働環境でGoを使用した成功例もありませんでした。 また、Goを選択した場合、優秀なプログラマを採用できるかどうかもわかりませんでした。 しかし、すぐにGoを選んだからこそ 、最高のプログラマを雇うことができることに気付きました。 Goは本番環境でのGoの使用を公表した最初の企業の1つであり、golangメーリングリストに空席の発表を投稿した最初の企業です。 その後、最高の開発者が仕事のためにGoを使用できるため、私たちのために働きたいと考えました。



行った後


Goでバージョンを起動した後、サーバーの数を2台に減らしました(2台目は信頼性のためにさらに必要です)。 サーバーの負荷は、リソースを使用していないかのように最小限になりました。 プロセッサの負荷は5%未満であり、アプリケーションは(起動時に)数百KBのメモリを使用し、Railsアプリケーションは約50 MB(起動時)を消費しました。 これをJVMと比較してください! 多くの時間が経ちました。 そしてそれ以来、巨大なclusterf ** kを再び持つことはありませんでした。



それ以来、私たちは大きく成長しました。 これでトラフィックが増え、追加サービス(IronMQとIronCache)を開始し、何百ものサーバーを使用して顧客のニーズに対応しました。 そして、バックエンド全体がGoに実装されています。 振り返ってみると、Goを選択することは大きな決断でした。なぜなら、成長と規模拡大のために優れた製品を構築し、才能ある人々を引き付けることができたからです。 そして、私が行った選択は、近い将来に私たちが成長するのを助け続けると思います。



PS翻訳はTravisの許可を得て作成されました。質問がある場合は、彼と他のIron.ioチームメンバーが喜んで回答します。



All Articles