ibco は、WeChat バックエンドで大規模に使用されている C/C++ コルーチン ライブラリで、2013 年以来、WeChat バックエンドの数万台のマシンで安定して実行されています。 Libco は、Tencent の 6 つの主要なオープンソース プロジェクトの 1 つとして 2013 年に初めてオープンソース化されました。最近、メジャー アップデートが行われ、github.com/tencent/libco で同期されています。 libco は、システムの高い同時実行機能を提供しながら、バックエンドのアジャイル同期スタイルのプログラミング モデルをサポートします。
libco によってサポートされる機能
ビジネス ロジックに侵入する必要がなく、マルチプロセスおよびマルチスレッド サービスをコルーチン サービスに変換し、同時実行機能が 100 倍向上します
CGI フレームワーク をサポートし、Web サービスを簡単に構築できます。 New);
gethostbyname、mysqlclient、ssl などの一般的に使用される 3 番目のライブラリをサポート (新)
オプションの共有スタック モードにより、単一マシンで数千万の接続に簡単にアクセスできます
完全で簡潔なコルーチン プログラミング インターフェイス
– クラス pthread インターフェイスの設計、コルーチンの作成と復元は、co_create や co_resume などのシンプルで明確なインターフェイスを通じて完了できます – スレッドのようなコルーチンのプライベート変数変数、相互用のコルーチン セマフォ co_signal (New)コルーチン通信; – コルーチンと組み合わせた非言語レベルのラムダ実装。バックグラウンドの非同期タスクをその場で記述および実行します (新規) - epoll/kqueue に基づく小型で軽量のネットワーク フレームワーク、タイム ルーレットに基づく高性能タイマー;
libco 背景
WeChat バックエンドの初期には、複雑で変化するビジネス ニーズと迅速な製品反復要件のため、ほとんどのモジュールは半同期および半非同期
モデル を採用していました。アクセス層は非同期モデルであり、ビジネス ロジック層は同期マルチプロセスまたはマルチスレッド モデルです。ビジネス ロジックの同時実行能力はわずか数十から数百です。 WeChatのビジネスが成長するにつれて、システムの規模はますます大きくなり、各モジュールはバックエンドサービス/ネットワークジッターの影響を受けやすくなります。
非同期変換の選択
WeChatバックエンドの同時実行機能を向上させるための一般的なアプローチは、既存のネットワーク上のすべてのサービスを非同期モデルに変更することです。このアプローチでは、フレームワークからビジネス ロジック コードに至るまでの膨大な作業が必要となり、完全な変換が必要となり、時間と労力がかかり、リスクも伴います。そこで私たちはコルーチンの使用を検討し始めました。
しかし、コルーチンを使用すると次のような課題に直面します:
業界のコルーチンには C/C++ 環境での大規模なアプリケーションの経験がない;
コルーチンのスケジューリングを制御する方法;
同期スタイルの
API 呼び出しを処理する方法ソケット、mysqlclient など;
既存のグローバル変数とスレッドのプライベート変数の使用に対処する方法
最終的に、libco を通じて上記の問題をすべて解決し、ビジネスの非侵襲的な変換を達成しました。論理。 libco を使用して、数百の WeChat バックエンド モジュールをコルーチンと非同期変換に変換しました。変換プロセス中、ビジネス ロジック コードは基本的に変更されませんでした。これまでのところ、WeChat バックエンドのサービスのほとんどはマルチプロセスまたはマルチスレッドのコルーチン モデルであり、以前と比べて同時実行機能が質的に向上しており、libco は WeChat バックエンド フレームワークの基礎となっています。
libcoフレームワーク
libcoはフレームワーク内でインターフェース層、システム
関数フック層、イベントドライバー層の3つの層に分かれています。
同期スタイル API の処理
同期スタイル API、主に同期ネットワーク呼び出しの場合、libco の主なタスクは、これらの待機によるリソースの占有を排除し、システムの同時実行パフォーマンスを向上させることです。通常のネットワーク バックグラウンド サービスの場合、完全なネットワーク インタラクションを完了するために、接続、書き込み、読み取りなどの手順を実行することがあります。これらの API を同期的に呼び出すと、スレッド全体がネットワーク対話を待ってハングします。
同期プログラミングスタイルの同時実行パフォーマンスは良くありませんが、コードロジックが明確で記述が簡単であるという利点があり、迅速なビジネスの反復とアジャイル開発をサポートできます。既存のビジネス ロジック コードをオンラインで変更することなく同期プログラミングの利点を維持し続けるために、libco は革新的にネットワーク呼び出しインターフェイス (フック) を引き継ぎ、コルーチンの放棄と回復をコールバックを使用した非同期ネットワーク IO のイベントとして登録しました。 。ビジネス処理が同期ネットワーク要求に遭遇すると、libco 層はネットワーク要求を非同期イベントとして登録し、このコルーチンは CPU 占有を放棄し、CPU は実行のために他のコルーチンに渡されます。 Libco は、ネットワーク イベントが発生するかタイムアウトになると、コルーチンの実行を自動的に再開します。 同期スタイル API のほとんどを Hook メソッドを通じて引き継ぎ、libco は適切な時間に実行を再開するようにコルーチンをスケジュールします。
数千万のコルーチンのサポート
デフォルトでは、libco はコルーチンごとに実行スタックを持ち、コルーチンが作成されると、コルーチンの実行スタックとして固定サイズのメモリがヒープ メモリから割り当てられます。フロントエンドでアクセス接続を処理するためにコルーチンを使用する場合、大規模なアクセス サービスの場合、サービスの同時実行制限はメモリによって簡単に制限されてしまいます。この目的のために、libco はスタックレス コルーチン共有スタック モードも提供します。これにより、複数のコルーチンが同じ実行スタックを共有するように設定できるようになります。同じ共有スタック内のコルーチン間を切り替える場合、現在実行中のスタックの内容をコルーチンのプライベート メモリにコピーする必要があります。このようなメモリ コピーの数を減らすために、共有スタックのメモリ コピーは、異なるコルーチン間の切り替え時にのみ発生します。共有スタックの占有者が変更されていない場合、実行中のスタックをコピーする必要はありません。
libco コルーチンの共有コルーチン スタック モードを使用すると、十分なコルーチンを作成するだけで、単一のマシンで数千万の接続に簡単にアクセスできます。 libco 共有スタック モードを通じて 1,000 万個のコルーチン (E5-2670 v3 @ 2.30GHz * 2、128G メモリ) を作成すると、各 100,000 個のコルーチンが 128k メモリを使用し、サービス中の安定した echo の総メモリ消費量は約 66G になります。
コルーチンのプライベート変数
マルチプロセス プログラムがマルチスレッド プログラムに変換されるとき、コルーチン環境では、スレッドを使用してグローバル変数を迅速に変更できます。これにより、コルーチンのワークロードが大幅に簡素化されます。 。
コルーチンは基本的にスレッド内でシリアルに実行されるため、スレッドのプライベート変数を定義すると、再入性の問題が発生する可能性があります。たとえば、スレッドのスレッド プライベート変数を定義する場合、当初は各実行ロジックがこの変数を排他的に使用できるようにしたいと考えていました。しかし、実行環境をコルーチンに移行すると、同じスレッドのプライベート変数が複数のコルーチンで操作される可能性があり、変数侵入の問題が発生します。このため、libco の非同期変換を実行するときに、ほとんどのスレッド プライベート変数をコルーチン レベルのプライベート変数に変更しました。コルーチンのプライベート変数には次の特性があります。コードがマルチスレッドの非コルーチン環境で実行されている場合、変数はスレッド プライベートです。コードがコルーチン環境で実行されている場合、この変数はコルーチン プライベートです。基礎となるコルーチンのプライベート変数は、実行環境の判断を自動的に完了し、必要な値を正しく返します。 コルーチンのプライベート変数は、既存の環境を同期から非同期に変える上で決定的な役割を果たします。同時に、たった 1 行の宣言コードで済む非常にシンプルで便利なコルーチンのプライベート変数の定義方法を定義しました。 gethostbyname のフックメソッド
既存のネットワークサービスの場合、システムの gethostbyname API インターフェースを通じて実際のアドレスを取得するために、
DNS にクエリ
する必要がある場合があります。コルーチンの変換中に、フックのソケット ファミリ関数が gethostbyname に適用できないことがわかりました。コルーチンが gethostbyname を呼び出すと、結果が同期的に待機されるため、同じスレッド内の他のコルーチンの実行が遅延します。 glibc の gethostbyname ソース コードを調べたところ、フックが有効にならないことがわかりました。これは主に、glibc が一般的なポーリング メソッドではなくイベントを待機するポーリング メソッドを定義しており、同時に glibc の間で切り替えるためのスレッド プライベート変数も定義しているためです。異なるコルーチンを再入すると不正確なデータが生成される可能性があります。 gethostbyname コルーチンの最終的な非同期は、フック ポーリング メソッドとコルーチンのプライベート変数の定義によって解決されます。 Gethostbyname は、glibc によって提供される同期クエリ DNS インターフェイスです。業界には gethostbyname の優れた非同期ソリューションが多数ありますが、これらの実装にはサードパーティ ライブラリの導入が必要であり、基礎となる層が非同期コールバック通知メカニズムを提供する必要があります。 libco はフックメソッドにより、glibc ソースコードを変更することなく gethostbyname の非同期化を実現します。 コルーチンセマフォ
マルチスレッド環境では、スレッド間の同期要件が発生します。たとえば、あるスレッドの実行は別のスレッドからのシグナルを待つ必要がありますが、この要件を解決するには通常 pthread_signal を使用します。 libco では、コルーチン間の同時実行要件を処理するために、コルーチン セマフォ co_signal を定義します。コルーチンは、待機中のコルーチンに通知するか、co_cond_signal および co_cond_broadcast を通じて待機中のすべてのコルーチンを起動するかを決定できます。
概要
Libco は、完全なコルーチン プログラミング インターフェイス、一般的に使用されるソケット ファミリ関数フックなどを提供する効率的な c/c++ コルーチン ライブラリであり、企業が同期プログラミング モデルを使用して迅速な反復開発を行えるようにします。過去数年間の安定した運用により、libco は WeChat のバックエンド フレームワークの基礎として極めて重要な役割を果たしてきました。
【関連推奨事項】
1.
WeChatパブリックアカウントプラットフォームのソースコードのダウンロードAlizi注文システムのソースコードの無料ダウンロード以上がlibco が大量のデータ情報をどのようにサポートしているかを説明しますの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。