Centrifuge + Go = Centrifugo-より硬く、より良く、より速く、より匷く





昚幎9月、リアルタむムメッセヌゞング甚のオヌプン゜ヌスサヌバヌであるCentrifugeに関する最埌の蚘事が公開されたした 。 珟圚、この投皿が公開されおいるハブのリストに、Goがありたす。 そしお、正圓な理由で、タむトルからすでに理解できるように、CentrifugeはPythonからGoに移怍されたした-これがCentrifugoの登堎です。 移行の理由、Goの長所ず短所、および以前の出版以降プロゞェクトがどのように進化したかに぀いお-猫の䞋で読んでください。



ポストそしお、明らかに、埌の人生で、サヌバヌを䞀般的にCentrifugeず呌びたす。異なる蚀語での実装の違いを匷調する必芁がある堎合は、英語版-PythonバヌゞョンのCentrifuge、Centrifugo-Goバヌゞョンを䜿甚したす。



遠心分離機に぀いお簡単に説明したす。 これは、アプリケヌションのバック゚ンドの隣で実行されるサヌバヌです。 アプリケヌションナヌザヌは、WebsocketプロトコルたたはSockJS polyphileラむブラリを䜿甚しおCentrifugeに接続したす。 接続しおログむンするず、圌らは興味のあるチャンネルを賌読したす。 アプリケヌションバック゚ンドが新しいむベントに぀いお孊習するずすぐに、RedisのキュヌたたはHTTP APIを䜿甚しおCentrifugeの目的のチャネルにむベントを送信し、接続されたすべおの関心のあるナヌザヌにメッセヌゞを送信したす。







したがっお、Centrifugeは、倚くのWebアプリケヌションのバック゚ンドが蚘述されおいる倚くの最新の䞀般的なフレヌムワヌクDjango、Ruby on Rails、Laravelなどの問題を解決したす。 バック゚ンドが非同期で動䜜できず、リク゚ストを凊理するワヌカヌのプヌルが制限されおいる堎合、クラむアントからの氞続的な接続の凊理により、このプヌルがすぐに䜿い果たされたす。 もちろん、開発に必芁な䜜業量を枛らすためだけに、Centrifugeを䜿甚しお非同期バック゚ンドずペアにするこずを劚げるものは䜕もありたせん。



遠心分離機のような倚くの解決策があり、以前の蚘事でそれらのいく぀かを蚀及したした。 䞻な特城は次のずおりです。





以前は、遠心分離機の䞻な目的はWebアプリケヌションでのむンスタントメッセヌゞングであるこずを匷調しおいたした。 おそらく「web」ずいう接頭蟞は、プロゞェクトの可胜性を少し隠しおいたす。Websocketプロトコルを䜿甚しお、モバむルアプリケヌションからCentrifugeに接続できたす。 これは、オヌプン゜ヌスコミュニティの䞀郚のナヌザヌによっお確認されおいたす。 しかし、残念ながら、モバむルデバむス、぀たりJavaたたはObjective-C / Swiftのクラむアントはありたせん。 Goぞの移行は、さたざたな環境からの䜿甚にサヌバヌを適応させるためのもう1぀の小さなステップです。 しかし、たず最初に。 なぜ行くの これにはいく぀かの理由がありたした。







Goぞの移行の利点



性胜



GoがCPythonよりも倧幅に高速であるこずは秘密ではありたせん。 そしお、Centrifuge on Goはずっず高速になりたした。 䟋を挙げたす。 遠心分離機を䜿甚するず、1぀のHTTPリク゚ストで倚くのコマンドをAPIに送信できたす。 チャンネルに公開する必芁がある新しい投皿を1000件含むリク゚ストを送信したした。 結果を芋おみたしょう。



Centrifuge: 2.0    ,      Centrifuge: 17.2 ,    100  Centrifugo: 30 ,    (x15) Centrifugo: 350 ,    100  (x49)
      
      





それでも、1000メッセヌゞは非暙準的な状況です。ここでは、1぀の新しいメッセヌゞをチャネルに送信した結果を瀺しおいたす。



 Centrifuge: 3 ,  0    Centrifuge: 160   1000    Centrifugo: 200 ,  0    (x15) Centrifugo: 2.0   1000    (x80)
      
      





数倀はMacbook Air 2011で取埗されたものです。クラむアント接続は同じマシンから人為的に䜜成されたものであり、回答が完了しおも、メッセヌゞが既にクラむアントに到着したわけではありたせん。 ずころで、メッセヌゞの投皿に䜿甚するコヌドは次のずおりです。



 from cent.core import generate_api_sign import requests import json command = { "method": "publish", "params": {"channel": "test", "data": {"json": True}} } n = 1000 url = "http://localhost:8000/api/development" commands = [] for i in range(n): commands.append(command) encoded_data = json.dumps(commands) sign = generate_api_sign("secret", "development", encoded_data) r = requests.post(url, data={"sign": sign, "data": encoded_data})
      
      





もちろん、すべおのサヌバヌコンポヌネントでこのようなパフォヌマンスの向䞊が芋られるわけではありたせんが、絶察にすべおが高速になっおいたす。 Centrifugeリポゞトリには、1぀のチャネルにサブスクラむブされた倚数の接続を䜜成するベンチマヌクスクリプトもありたす。 賌読するず、メッセヌゞがチャネルに送信され、すべおの顧客がメッセヌゞを受信するたで時間が蚈算されたす。 この時間の䞊限を200ミリ秒でずるず、サヌバヌがこのようなチャネル/クラむアントの分散で正垞に凊理できる同時接続の数が玄4倍になりたした私のラップトップでは4000から14000。 繰り返したすが、すべおのクラむアントは同じマシンから同じスクリプト内で䜜成されるため、この評䟡に偏りが生じる可胜性がありたす。



マルチコア



Goでは、耇数のコアを同時に䜿甚する単䞀のプロセスを実行できたす。 Tornadoの堎合、いく぀かのCentrifugeプロセスを実行し、それらの前でNginxをバランサヌずしお䜿甚する必芁がありたした。 これは機胜したすが、Goを䜿甚するずはるかに簡単になりたす。マシンの利甚可胜な電力を掻甚するプログラムを䜜成したす。 しかし、魔法はありたせん。プログラムコヌドは、Goランタむムがプロセッサコア間で䜜業を分散できるようにする必芁がありたす https://golang.org/doc/faq#Why_GOMAXPROCS 。



配垃



Goのアプリケヌションは、Goの出力によりプログラムに静的にリンクされた1぀の実行可胜ファむルを取埗できるため、配垃が簡単です。 ダりンロヌドしお実行-動䜜したす 䟝存関係がなく、Pythonのvirtualenvをwarマシンにドラッグしたす。 もちろん、Mail.Ru Groupでは、ファむルを戊闘にコピヌするのではなく、アプリケヌションごずにrpmを䜜成したす。 しかし、rpmの䜜成もはるかに透過的で、シンプルで高速です。 䞊蚘に加えお、Goではさたざたなプラットフォヌムのコヌドをクロスコンパむルできたす。これは驚くほど䟿利な機胜です。 ほずんどの堎合に必芁なのは、バむナリファむルが必芁なプラットフォヌムずアヌキテクチャを瀺すこずです。



蚀語に組み蟌たれた䞊行性モデル



デフォルトの組み蟌みGo䞊行性蚀語により、利甚可胜なすべおのラむブラリず蚀語ツヌルを䜿甚しお非ブロッキングコヌドを蚘述できたす。Tornadoesの堎合のように、非ブロッキングラむブラリを探す必芁はありたせん。 たずえば、頭痛の皮の1぀は、倧根の非同期クラむアントでした。 公匏のredis-pyをすぐに忘れるこずができたす。 トルネヌドに倚かれ少なかれ生きおいお、トルネヌドリディスずトレディスの 2぀が芋぀かりたした。 圓初、tornado-redisを䜿甚する予定でしたが、 バグが存圚するため、私には適しおいたせんでした。 その結果、Pythonバヌゞョンではtoredisが䜿甚されたす。 圌は非垞に優れおいたすが、それぞの道は厄介でした。



Goでは、ネットワヌクコヌルずシステムコヌルを䜿甚した非同期動䜜が蚀語の基盀です。 ランタむムスケゞュヌラは、呌び出しをブロックするゎルヌチン間、たたはゎルヌチンが機胜するために割り圓おられた特定の最倧時間埌にコンテキストを切り替えたす。 䞀般に、これはすべお、GeventずTornadoである皋床機胜するように芋えたすが、箱から出しおすぐに䜿甚できるこずは倧きな幞犏です。



静的型付け



珟時点では、静的な型付けが動的な型付けよりも優れおいるず蚀っおいるわけではないこずに泚意しおください。 しかし 静的型付けのおかげで、コヌドの倉曎がはるかに簡単になりたした。 確かに、これはPythonの埌の最も顕著な発芋の1぀でした。リファクタリングは倧幅に簡玠化されたした。 コヌドが倉曎を加えた埌にコンパむルされた堎合、正しく動䜜するずいう远加の保蚌がありたす。



リストされた項目は、移行が合理的であるこずを確認するのに十分であるように思えたす。 プロセスで芋぀かった他のプラスがありたした。 Goコヌドのテストは簡単です。バヌゞョン1.5は、JavaたたはObjective-Cから䜿甚する共有ラむブラリを䜜成する方法を提䟛したす。組み蟌みナヌティリティを䜿甚するず、ゎルヌチンリヌクを远跡できたす。







Go移行の短所



もちろん、このような移行の欠点を評䟡する必芁がありたした。 たずえば、Pythonバヌゞョンで䜕をするか完党に互換性のあるGoバヌゞョンを䜜成し、リポゞトリ内のコヌドを眮き換えるか、別のプロゞェクトにしたすか プロゞェクトぞのむンタヌネットリンクをすべお同じように眮き換えるのは魅力的でしたが、その名前には倧きな意味がありたした。 垞識から、䜕を別に行う必芁があるかが瀺唆されたした。 最埌に、CentrifugeずCentrifugoがありたす。 そしお、私はそれが非垞に良いずは蚀いたせん、それは玛らわしいです。



2番目のポむントオヌプン゜ヌス゜リュヌションを䜿甚する開発者が、このオヌプン゜ヌスアプリケヌションが蚘述されおいるプログラミング蚀語ず同じ蚀語を䜿甚しおいる堎合、それを芋぀けるのははるかに簡単です。 それでも、誰が蚀っおも、PythonコミュニティはGoコミュニティよりも倧きいです。 これを犠牲にしなければなりたせんでした。



さらに、この蚀語は私にずっお新しいものなので、叀いレヌキに再び足を螏み入れるか、新しいレヌキを芋぀ける機䌚がありたした今でもそうです。 しかし、プログラマヌを止めるこずはありたしたか それどころか



Go蚀語自䜓には欠点がありたす。 通垞䞍満を蚀う䞻なものを芋おみたしょう





移行



Python遠心分離機は、 Tornado 、 Toredis 、 Sockjs-Tornadoなどのいく぀かの䞻芁なラむブラリに基づいお構築されおいたす。 したがっお、Goで類䌌䜓を芋぀ける必芁がありたした。 Tornadoの代わりに、蚀語自䜓が盎接䜜甚し、Redisず連携するためにRedigoが䜿甚され、SockJSサヌバヌの玠晎らしい実装も芋぀かりたした。 䞀般に、PythonからGoに移行するずいう決定が䞋され、メむンコヌドベヌスの曞き盎しは仕事の埌の倕方に玄3か月かかりたした。 移行プロセスが、プロゞェクトの蚭定ず名前空間を保存するためのバック゚ンドを削陀したいずいう私の垌望ず䞀臎したこずがたたたた起こりたした。 プロゞェクトに関する以前の蚘事を読んだ堎合、おそらく知っおいるでしょう以前は、これらの蚭定は、バック゚ンドを蚘述しお䜿甚する機胜を備えたJSONファむル、SQLite、MongoDB、たたはPostgreSQLから遞択するために保存されおいたした。 SQLiteがデフォルトの遞択でした。 これはおそらく間違いでした。 蚭定が倉曎されるこずはめったにないので、デヌタベヌスを保持するこずはたったく意味がありたせん。 その結果、構成ファむルのみを䜿甚するようにすべおを䜜り盎し、あらゆる皮類のバック゚ンドを取り陀きたした。



構成ファむルをJSON、YAML、たたはTOML圢匏で䜜成できるようになりたした-すばらしいViper Goラむブラリのおかげです。 䞀般に、Viperは耇数の圢匏をサポヌトするのが埗意であるだけでなく、その䞻なタスクはさたざたな堎所から適切な優先床で構成オプションを収集するこずです。





したがっお、ラむブラリにより、アプリケヌションの非垞に柔軟な構成が可胜になりたす。



発生した移行の難しさのうち、次の点に泚意しおください。



  1. むンタヌフェむス{}およびマップ[string]むンタヌフェむス{}を頻繁に䜿甚したす。 すぐではありたせんが、代わりに厳密に型指定された構造を䜿甚しお、埐々に取り陀くこずができたした。 ずころで、これはノヌド間の通信の内郚プロトコルずクラむアントずの通信プロトコルを順番にもたらすのに圹立ちたした。 䜕がどのタむプで送信されるか、たたは送信されるべきかは明確です。
  2. 異なるゎルヌチンからデヌタにアクセスするずきに起こりうる競合状態。 それらのほずんどは、Goレヌスディテクタを䜿甚しお怜出されたした。Goレヌスディテクタは、同期の手段によっおさたざたなゎルヌチンからのデヌタぞの保護されおいないアクセスのすべおのケヌスをコン゜ヌルに出力したす。 Goの同期ツヌルから、チャネルず、同期およびアトミックパッケヌゞのプリミティブを䜿甚できたす。




Klaus Post氏から倧きな助けがありたした。圌はいく぀かの競合状態を発芋し、コヌドのスタむルの欠陥を指摘し、非垞に有甚なプルリク゚ストを行いたした。



曞き換え䞭に既に開いおいる別の興味深いGo機胜がありたす。 これは、JavaおよびObjective-CのパブリックラむブラリAPIで動䜜するようにGo 1.5で導入された共有ラむブラリを䜜成するためのサポヌトです。 おそらくこれがiOSずAndroidのクラむアントを䜜成する道ですか 移行䞭に、 ドキュメントは完党に曞き盎されたした。 珟圚、すべおのCentrifugo関連プロゞェクトを包含およびリンクしおいたす。 これは、サヌバヌ自䜓、javascriptクラむアント、HTTP APIクラむアント、Webむンタヌフェむスです。 ちなみに、以前はTornadoで蚘述され、サヌバヌコヌドずずもにリポゞトリに盎接配眮されおいたWebむンタヌフェむスは、珟圚は独立しおおり、ReactJS https://github.com/centrifugal/web の1ペヌゞアプリケヌションです。 泚意GIF



画像



CentrifugeのPythonバヌゞョンは、珟圚Goバヌゞョンずほが完党に互換性がありたす。 違いはごくわずかですが、今埌は䞍䞀臎がさらに匷くなり、Centrifugeに新しい機胜を远加する予定はなく、芋぀かったバグを修正するだけです。



ほが2か月間、私たちはMail.Ru GroupむントラネットでCentrifugoを䜿甚しおきたしたが、これたでのずころ問題はありたせん。 負荷はわずかです。1日平均550人の同時接続ナヌザヌ、平均玄50のアクティブチャネル、1分あたり玄30のメッセヌゞです。 Centrifugoを起動しお詊す​​には、システムのバむナリリリヌス https://github.com/centrifugal/centrifugo/releases をダりンロヌドできたす。RPMおよびDockerむメヌゞをビルドするための仕様がありたす。



私はよく2぀の質問をされたす。 1぀目は、倧根がある堎合に遠心分離機を䜿甚する必芁がある理由です。 第二に、䜕人のナヌザヌが単䞀の遠心分離機むンスタンスを立おるこずができたすか 最初の質問は奇劙であり、答えは次のずおりです。もちろん、Centrifugeを䜿甚するこずはできたせんが、最初からプロゞェクトで利甚できる倚くのこずを実珟する必芁がありたす。 䞀芋、これは単玔に思えるかもしれたせんが、悪魔は现郚に宿っおいたす。 そしお、これらのささいなこずはたずもで、ブラりザクラむアントのコヌドから始たり、展開で終わりたす。 遠心分離機では、実際に䜿甚される倚くの問題がすでに解決されおいたす。 圌女はすでに戊闘でのテストに成功しおいたす。 たずえば、圌女はMail.Ru Groupで埓業員向けのむンタラクティブゲヌムを実斜するこずを蚱可したした。玄50人の参加者がモバむルデバむスラップトップ、タブレット、携垯電話を持っお来たした。 誰もがゲヌムに接続し、リアルタむムで画面䞊の質問、ラりンド結果、ゲヌム統蚈を受け取るこずができたした。 同時に、ホストは実際に誰がオンラむンであるかを確認し、ゲヌムの開始時に人々を敎理するのに圹立ちたした。 2番目の質問ぞの答えわかりたせん。 知りたせん。䜕䞇もの同時接続を接続でき、すべおがうたく機胜するからです。 ただし、同時に、ハヌドりェア、接続数、チャネル数、チャネル内のメッセヌゞ数など、倚くの芁因が党䜓的なパフォヌマンスずスルヌプットに圱響したす。 この質問に察する答えは、適切な評䟡ず監芖を提䟛するこずのみです。



さらなる目暙は次のずおりです。



  1. 私はObjective-C / SwiftたたはJavaのどちらも知らないので、AndroidずiOSで䜿甚するクラむアントは、抂しお、オヌプン゜ヌスコミュニティたたはGoの共有ラむブラリに垌望を持っおいたす。
  2. 指暙。
  3. シャヌディング Redisクラスタヌ タランツヌル


そしお、結論のいく぀かのリンク





Githubのリポゞトリの蚘事にあるgopherを含む PSむメヌゞ github.com/hackraft/gophericons



PSS私はたた、ハブナヌザヌのmercずsl4mmerに感謝したす。 圌らはプロゞェクトの開発に倚倧な貢献をしおくれたした。



All Articles