はじめに
Ibco は、WeChat バックエンドで大規(guī)模に使用されている c/c++ コルーチン ライブラリで、2013 年以來、WeChat バックエンドの數萬臺のマシンで安定して実行されています。 Libco は、Tencent の 6 つの主要なオープンソース プロジェクトの 1 つとして、2013 年に初めてオープンソース化されました。最近、メジャー アップデートが行われ、https://github.com/tencent/libco で同期されています。 libco は、システムの高い同時実行機能を提供しながら、バックエンドのアジャイル同期スタイルのプログラミング モデルをサポートします。
libco によってサポートされる機能
ビジネス ロジックに侵入する必要がなく、マルチプロセスおよびマルチスレッド サービスをコルーチン サービスに変換し、同時実行機能が 100 倍向上します
CGI フレームワークをサポートし、Web サービスを簡単に構築します (新規(guī)) ;
gethostbyname 、mysqlclient、ssl およびその他の一般的に使用される 3 番目のライブラリをサポート (新機能)
オプションの共有スタック モードにより、1 臺のマシンで數千萬の接続に簡単にアクセスできます
完全で簡潔なコルーチン プログラミング インターフェイス
– pthread のようなインターフェイス設計。コルーチンの作成と復元は、co_create や co_resume などのシンプルで明確なインターフェイスを通じて完了できます。 – コルーチン間の通信用のクラス __thread、コルーチン セマフォ co_signal (新規(guī))。言語レベルのラムダ実裝、コルーチンと組み合わせて、バックグラウンドの非同期タスクを適切に記述して実行します (新規(guī)) – epoll/kqueue に基づく小型で軽量のネットワーク フレームワーク、時間ルーレットに基づく高性能タイマー
バックグラウンド。
初期の WeChat 複雑で変化するビジネス要件と、バックエンドでの製品の迅速な反復のため、ほとんどのモジュールは半同期および半非同期モデルを採用しています。アクセス層は非同期モデルであり、ビジネス ロジック層は同期マルチプロセスまたはマルチスレッド モデルです。ビジネス ロジックの同時実行能力はわずか數十から數百です。 WeChatのビジネスが成長するにつれて、システムの規(guī)模はますます大きくなり、各モジュールはバックエンドサービス/ネットワークジッターの影響を受けやすくなります。
非同期変換の選択
WeChatバックエンドの同時実行機能を向上させるための一般的なアプローチは、既存のネットワーク上のすべてのサービスを非同期モデルに変更することです。このアプローチでは、フレームワークからビジネス ロジック コードに至るまでの膨大な作業(yè)が必要となり、完全な変換が必要となり、時間と労力がかかり、リスクが伴います。そこで私たちはコルーチンの使用を検討し始めました。
しかし、コルーチンを使用すると、次のような課題に直面します:
業(yè)界のコルーチンには、C/C++ 環(huán)境での大規(guī)模なアプリケーションの経験がありません;
コルーチンのスケジューリングを制御する方法;
次のような同期スタイルの 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 は各コルーチンが獨自の実行スタックを持つことを許可します。コルーチンの作成時に、固定サイズのメモリがコルーチンの実行スタックとしてヒープ メモリから割り當てられます。フロントエンドでアクセス接続を処理するためにコルーチンを使用する場合、大規(guī)模なアクセス サービスの場合、サービスの同時実行制限はメモリによって簡単に制限されてしまいます。この目的のために、libco はスタックレス コルーチン共有スタック モードも提供します。これにより、複數のコルーチンが同じ実行スタックを共有するように設定できるようになります。同じ共有スタック內のコルーチン間を切り替える場合、現在実行中のスタックの內容をコルーチンのプライベート メモリにコピーする必要があります。このようなメモリ コピーの數を減らすために、共有スタックのメモリ コピーは、異なるコルーチン間で切り替えるときにのみ発生します。共有スタックの占有者が変更されていない場合、実行中のスタックをコピーする必要はありません。
libco コルーチンの共有コルーチン スタック モードを使用すると、十分なコルーチンを作成するだけで、単一のマシンで數千萬の接続に簡単にアクセスできます。 libco 共有スタック モードを通じて 1,000 萬個のコルーチン (E5-2670 v3 @ 2.30GHz * 2、128G メモリ) を作成すると、各 100,000 個のコルーチンが 128k メモリを使用し、安定したエコー サービス全體の合計メモリ消費量は約 66G になります。
コルーチンのプライベート変數
マルチプロセス プログラムがマルチスレッド プログラムに変換されるとき、__thread を使用してグローバル変數をすばやく変更できます。コルーチン環(huán)境では、コルーチン変數 ROUTINE_VAR を作成しました。これにより、コルーチンのワークロードが大幅に簡素化されます。コルーチン変換。
コルーチンは基本的にスレッド內でシリアルに実行されるため、スレッドのプライベート変數を定義すると、再入性の問題が発生する可能性があります。たとえば、__thread というスレッド プライベート変數を定義する場合、當初は各実行ロジックがこの変數に排他的にアクセスできるようにしたいと考えていました。しかし、実行環(huán)境をコルーチンに移行すると、同じスレッドのプライベート変數が複數のコルーチンで操作される可能性があり、変數侵入の問題が発生します。このため、libco の非同期変換を実行するときに、ほとんどのスレッド プライベート変數をコルーチン レベルのプライベート変數に変更しました。コルーチンのプライベート変數には次の特性があります。コードがマルチスレッドの非コルーチン環(huán)境で実行されている場合、変數はスレッド プライベートです。コードがコルーチン環(huán)境で実行されている場合、この変數はコルーチン プライベートです?;Aとなるコルーチンのプライベート変數は、実行環(huán)境を自動的に決定し、必要な値を正しく返します。
コルーチンのプライベート変數は、既存の環(huán)境を同期から非同期に変える上で決定的な役割を果たします。同時に、たった 1 行の宣言コードで済む非常にシンプルで便利なコルーチンのプライベート変數の定義メソッドを定義しました。 。
gethostbynameのフックメソッド
既存のネットワークサービスの場合、システムのgethostbyname APIインターフェイスを通じて実際のアドレスを取得するためにDNSにクエリを実行する必要がある場合があります。コルーチンの変換中に、フックのソケット ファミリ関數が gethostbyname に適用できないことがわかりました。コルーチンが gethostbyname を呼び出すと、結果が同期的に待機されるため、同じスレッド內の他のコルーチンの実行が遅延します。 glibc の gethostbyname ソース コードを調べたところ、フックが有効にならないことがわかりました。これは主に、glibc が一般的な poll メソッドではなく、內部でイベントを待機する __poll メソッドを定義しているためであり、同時に glibc はスレッド プライベート変數も定義しているためです。異なるコルーチンで使用される可能性があるため、切り替えにより再入が発生し、データが不正確になる可能性があります。最後に、gethostbyname コルーチンの非同期化は、Hook __poll メソッドとコルーチンのプライベート変數の定義によって解決されます。
Gethostbyname は、glibc によって提供される同期クエリ DNS インターフェイスです。業(yè)界には gethostbyname の優(yōu)れた非同期ソリューションが多數ありますが、これらの実裝にはサードパーティ ライブラリの導入が必要であり、非同期コールバック通知メカニズムを提供するために基礎となる層が必要です。 libco はフックメソッドにより、glibc ソースコードを変更することなく gethostbyname の非同期化を実現します。
コルーチンセマフォ
マルチスレッド環(huán)境では、スレッド間の同期要件が発生します。たとえば、あるスレッドの実行は別のスレッドのシグナルを待つ必要がありますが、この要件を解決するには通常 pthread_signal を使用します。 。 libco では、コルーチン間の同時実行要件を処理するために、コルーチン セマフォ co_signal を定義します。コルーチンは、待機中のコルーチンに通知するか、co_cond_signal および co_cond_broadcast を通じて待機中のすべてのコルーチンを起動するかを決定できます。
概要
Libco は、完全なコルーチン プログラミング インターフェイス、一般的に使用されるソケット ファミリ関數フックなどを提供する効率的な c/c++ コルーチン ライブラリであり、企業(yè)が同期プログラミング モデルを使用して迅速な反復開発を行えるようにします。過去數年間の安定した運用により、libco は WeChat のバックエンド フレームワークの基礎として極めて重要な役割を果たしてきました。

ホットAIツール

Undress AI Tool
脫衣畫像を無料で

Undresser.AI Undress
リアルなヌード寫真を作成する AI 搭載アプリ

AI Clothes Remover
寫真から衣服を削除するオンライン AI ツール。

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中國語版
中國語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統(tǒng)合開発環(huán)境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック









