レポート-CppCometサーバーの機能とアーキテクチャの概要

これはレポートのテキストとrumeetup.ruカンファレンスでの私のスピーチのビデオで、読みやすい形式で表示されます。 また、C ++でゼロからオープンソースコメットサーバーの開発を開始するようになった理由について読者に時間を無駄にしないように、導入部分も削除しました。



ビデオスピーチ





技術的に重要な詳細を含まない紹介

スライド1-ご挨拶







スライド2-プロジェクトについて少し



5年前に、私は彗星サーバーを作成するというアイデアを得たhighload ++ 2012カンファレンスに参加しました。 これを行う客観的な理由はありませんでした。 私はこのアイデアが気に入りました。 さらに、私は過去のプロジェクトから適用できる経験がありました。



それ以来、私はこのプロジェクトにほぼ2000時間を費やしました。 APIに互換性があるようにSaaSコメットサービスとそのオープンソースの対応物を作成したため、コードを変更せずにSaaSバージョンとオープンソースバージョンを切り替えることができます。



この間、ロシア語と英語で詳細なドキュメントを書くことができました。



私は本番環境でCppCometをほぼ4年間使用してきましたが、まだ積極的に開発し、新しい機能を徐々に追加しています。 たとえば、先週はクラスタリング機能を追加しました。



4年間、私はプロジェクトユーザーの技術サポートに携わってきました。 そして、各質問に基づいて、APIとドキュメントを改善して、次のユーザーが簡単になるようにしました。









スライド3-アナログ



私のプロジェクトは、他のツールを使用して実装できない革新的なことを行いません。 したがって、このスライドでは、競合するプロジェクトのリストをまとめました。



図書館





サース





スライド4-はじめに



おそらく、各開発者の前に、遅かれ早かれ、自分のチャットを作成したり、リアルタイムの通知を実装したりするタスクが発生します。



また、プロジェクトが新しく、設計段階であっても、どこでどのデータをリアルタイムで更新する必要があるかを考慮することができれば便利です。



しかし、これは常に起こるとは限りません。 既存のプロジェクトにリアルタイムのデータ更新を追加する必要がある場合があります。



ページのリロード後ではなく、サイト上の記事のコメントをユーザーがすぐに更新したいとします。



最初の最も簡単なソリューションは、ajaxサーバーから1秒ごとに新しいajaxサーバーにデータを要求することです。



解決策はシンプルで非常に効果的ですが、いくつかはそうです。 たとえば、管理者エリアでは、最大1〜2人が座っています。







スライド5



しかし、複数の訪問者がいる場合、比較的少ないトラフィックでもサイトにddoを配置したい場合、このコードは素晴らしいです。







スライド6



クライアントからサーバーに大量のリクエストを送信する代わりに、サーバーに表示された新しいデータをクライアントに送信する方が合理的です。



このスキームでは、JavaScriptクライアントはWebソケットを介して彗星サーバーに接続し、そこからのバックエンドからの通知を待ちます。



また、Webサーバーはイベント通知を彗星サーバーに送信し、これらの通知がフロントエンドに配信されることを期待しています。



私自身の経験から、このデータがサイトデータベースに記録された直後にデータをコメットサーバーに送信すると便利だと思います。







スライド7



サーバーコメットには2つのAPIがあり、1つはブラウザーからWebSocket経由で接続するためのものです。 バックエンドからリクエストを送信するための2番目のインターフェース。



JavaScript APIのプロトコルには特に選択はありません。 私たちはウェブソケットに取り組んでいます。

ただし、バックエンドにアクセスするためのAPIはさまざまな方法で実装できます。







スライド8-API



最初は、プロトコル用のシンプルなAPIとそれに対応するPHPクライアントを書くことをためらいませんでした。 しかし、出来上がった自転車は開発が容易で、メンテナンスが不便でした。

その結果、複数のプラットフォームでAPIのすべてのバージョンで後方互換性を維持することは、時間のかかるタスクであることが証明されています。



そのプロトコルの背景に対して、よく知られているすべてのREST APIでの作業は非常に魅力的に見えます。 しかし実際には、各リクエストのhttpプロトコルで作業する場合、ネットワーク接続を確立し、リクエストを実行し、ネットワーク接続を閉じる必要があります。 これは、すべての要求が同じネットワーク接続内で実行されるtcpで作業するオプションよりも長くなります。



そして最後に、SphinxSearchで実装されたパスに従うことを決め、mysqlプロトコルのサーバー部分を実装し、多かれ少なかれ人気のある言語ごとに存在するmysqlクライアントを使用して彗星サーバーで動作することが可能になりました。







スライド9-CometQL API



コメットサーバーは、mysqlサーバーのふりをし始めました。 また、APIはデータベースを呼び出すようになりました。



クライアントにデータを送信するために挿入し、サーバーの彗星から情報を受信することを選択します。

テーブルの名前は、操作が実行されるオブジェクトを示します。

データベースの名前は、作業中のAPIのバージョンを象徴しています。 バージョン1の場合。2年以上前からの互換性は壊れていません。







スライド10-JavaScript API



JavaScript APIは、エラー処理、クラスタリング機能、およびさまざまな最適化のための多くのコードを隠します。 たとえば、1つのサイトのタブをいくつ開いても、コメットサーバーとのネットワーク接続は1つだけ確立され、残りのタブはすべてに共通の接続を介してコメットサーバーと通信します。







スライド11-メッセージ配信チャンネル



JavaScriptのイベントに関する情報を取得するには、このイベントをサブスクライブする必要があります。



たとえば、ブラウザで開いたページに関する新しいコメントを受け取りたい場合は、サーバーが何かを通知するチャンネルを購読します。



購読した後、サーバーから購読したチャンネルにデータを送信できます。



チャンネル名は何でもかまいませんが、主なことは、サーバーがJSからサブスクライブしたチャンネルにメッセージを送信することです







スライド12-プライベートメッセージを受信する



前の例では、購読するチャネルを知っている人はだれでもメッセージを受信できます。 しかし、これは必ずしも便利ではありません。



たとえば、チャットを作成していて、他のユーザーがこのメッセージを受信できないように特定の人にメッセージを配信したい場合は、チャンネルの代わりにプライベートメッセージメカニズムを使用する方が便利です。



これを行うには、「msg」という名前の特別なチャンネルにサブスクライブします。 個人宛てのメッセージのみを受信します。

この機能は、コメットサーバーでのユーザー認証後に使用できます。







スライド13-パフォーマンス



パフォーマンスと平均でtsungで使用するメモリ消費量の測定、 64,000ユーザーの場合、 5 GB未満のRAM 同時に、cometサーバーはマルチスレッドモードで実行されているため、利用可能なすべてのカーネルをほぼ均等に使用することができます。



テストはもちろん総合的なものであり、私の制作における実際の負荷ははるかに少ないです。 これまでのところ、最大1,500人がオンラインです。 そして最終的に、サーバーはその機能の数パーセントに過ぎません。







スライド14



その結果、最初のスライドで引用したのとほぼ同じ量のコードに戻りましたが、すべて正しく実行しました。 そして今では、64,000のオンラインあたり約5 GBのRAMの負荷に耐えることができます。 さらに、クラスタリング、スケーリング、フォールトトレランスの機会があります。







スライド15-スケーリング



スケーラビリティを事前に計画することは常に役立ちます。



彗星サーバーでは、クラスター内の各サーバーが要求を受信し、イベントについて通知する必要があるクラスターサーバーに転送できるクラスタリング可能性を提供しました。



データの挿入(挿入および設定)操作は非同期で実行されます。つまり、クラスター内のすべてのサーバーに要求が送信されるまで待機しません。



データサンプリング操作(選択および表示)は同期して機能します。







スライド16-フォールトトレランス



何かが壊れてコメットサーバーが利用できなくなった場合、最良の場合、メッセージはユーザーに届きません。



クラスターがない場合、サーバーの問題ですべてがすぐに壊れる可能性があります。

コメットサーバーのクラスタの場合、リクエストを送信しようとしているのがこのノードを経由している場合、1つのノードの障害も苦痛になります。







スライド17



現実の世界では、時々間違いが起こります。 そして、エラー処理のためにそのようなコードを書くことは楽しい経験ではありません。 そして最も重要なのは、一部のサーバーが利用できない場合、最初の試行で接続しないことです。

したがって、クラスターのスキームにhaproxyを含めて、クラスターの稼働中のノード間で要求のバランスを取ることができます。







スライド18



haproxyには、mysqlサーバーと動作しないサーバーのリストから例外をポーリングするメカニズムがあります。 また、クラスターのノード間の負荷分散の割合を設定する機会もあります。

javascript apiには、ノードの1つが利用できない場合にクラスター内の別のノードに接続する機能もあります。 その結果、サーバーの彗星のクラスターのノードをオフにしても、システムに少なくとも1つの作業ノードがある限り、操作性は維持されます。



さらに、Webブラウザーからのクライアントは、ページを更新する必要さえありません。 すべてがJavaScript API内に隠されます。







スライド19-プロジェクト開発計画

スライド19-計画



1つ目は、クラスターの改善です。 この秋にのみクラスタリングメカニズムを実装したため、ユーザーエクスペリエンスを蓄積する必要があります。 2つ目は、 ビデオチャットとビデオ会議機能の追加です。



ビデオチャットのデモは既にあります。 しかし、APIはまだ最後まで落ち着いていません。 そして、ビデオチャットはすでに使用できますが。 次のリリースがビデオチャットに対して完全な下位互換性を持つことは事実ではありません。



また、 GitHubで予定されている機能を公開しています









スライド20-既に使用されているいくつかの例

スライド20-すでに使用されている場所



実際、私の彗星サーバーは数十のサイトで使用されています。 ここに私が知っているプロジェクトの一部のみを示します。 最初の3つには、すべての参加者のための簡単な共通チャットが組み込まれています。



2行目には、ソーシャルネットワークのチャットと出会い系サイトのチャットが含まれています。











スライド21-ご清聴ありがとうございました

スライド21-ご清聴ありがとうございました。








All Articles