|
Tarsは、テンセントがオープンソース化したマイクロサービスフレームワークです。昨年4月にオープンソース化され、今年6月にLinux Foundationに寄贈されました。Tarsは、開発から運用までをカバーする包括的なソリューションをユーザーに提供し、製品やサービスの迅速な開発、リリース、展開、立ち上げ、保守を支援します。スケーラブルなプロトコルエンコード/デコード、高性能RPC通信フレームワーク、名前ルーティングと検出、リリース監視、ログ統計、構成管理を統合し、マイクロサービスを活用した安定性と信頼性に優れた分散アプリケーションを迅速に構築し、完全かつ効果的なサービスガバナンスを実現します。1年以上の開発期間を経て、Tarsは現在、China Literature Group、Huya Live、iFlytek、Youpin Wealth、Longtu Games、Jintaiyang Educationなど、多くの企業で利用されています。 9月15日、テンセントはTarsのGolang版であるTars-Goを正式にオープンソース化することを発表しました。Tarsのオープンソース化発表では、Tarsと現在市場に出回っている他のマイクロサービスフレームワークとの違い、技術アーキテクチャ、パフォーマンスデータ、そして関連する技術的な詳細が明らかになりました。本記事では、今回リリースされたGolang版Tarsについて詳しく紹介します。 プロジェクトアドレス: https://github.com/TarsCloud/TarsGo サービス ガバナンスと複数の言語をサポートします。この機能を提供するのは Tars だけです。マイクロサービスアーキテクチャはここ2年間で爆発的な人気を博し、最も主流のアーキテクチャパターンとなりました。マイクロサービスフレームワークについて議論する際には、Dubbo、gRPC、Spring Cloudといった著名なプロジェクトを当然ながら挙げることができます。これらのマイクロサービスフレームワークは、サービスガバナンスと多言語サポートの有無に基づいて、以下の4つのカテゴリに分類できます。
上記の分析から、Tarsはサービスガバナンスをサポートしながら多言語サポートも提供するマイクロサービスフレームワークであることがわかります。これがTarsのユニークな特徴であり、その強みです。 Tarsは物理マシン、仮想マシン、コンテナ上で実行できます。メインプロトコルはIDLベースのTarsプロトコルです。これはpbに似たバイナリ解析プロトコルです。Tarsは他のプロトコルやユーザー定義プロトコルもサポートしています。 主な呼び出し方法はRPCで、同期、非同期、一方向呼び出しをサポートしています。サービスガバナンスに関しては、サービス登録やディスカバリといった業界標準の機能に加え、Setモデル、自動リージョン認識、オーバーロード保護といった大規模トラフィック処理のためのガバナンス機能も提供しています。言語に関しては、新たにサポートされたGolangに加え、現在C++、Java、NodeJS、PHPをサポートしています。さらに、フレームワーク全体はDevOpsとの連携も容易です。 Tars は、レジストリ、サービス ノード、基本サービス クラスターの 3 つの部分に分かれています。 レジストリ レジストリは、マイクロサービス クラスターの管理および制御ノードであり、サービス登録や検出などの機能を提供します。 サービスノード サービスノードは、Tarsにおける最小単位です。コンテナ、仮想マシン、または物理マシンのいずれかです。ビジネスサービスは、複数のサービスノードを展開することで、キャパシティとフォールトトレランスの問題に対処します。サービスノードには、ノード管理サービスと1つ以上のビジネスサービスが含まれます。ノードサービスは、ノード上のサービスの統合管理を提供し、サービスノードの起動、停止、監視などの機能を提供します。また、ビジネスサービスノードから報告されるハートビートを受信し、サービス検出のデータソースとしてレジストリに報告します。 基本サービスクラスター 基本サービスクラスターは、マイクロサービスのガバナンス問題を解決するために設計された一連のサービスです。サービスノードの数は可変であり、フォールトトレランスと災害復旧のために、通常は複数のサーバーに展開する必要があります。具体的なノード数はビジネスの規模によって異なります。例えば、ビジネス規模が大きく、より多くのログ記録が必要な場合は、より多くのログサービスノードを展開する必要があります。基本サービスには、主に監視と統計、構成センター、ログ集約、認証と承認、分散コールチェーンが含まれます。Tarsは非常に包括的なサービスガバナンス機能を備えています。 Tarsはレジストリ、サービスノード、そして基盤となるサービスクラスタと連携し、サービス検出/登録、負荷分散、認証、分散トレースといったサービスガバナンスタスクを透過的に実行します。例えば、フレームワークはレジストリを介してxxxsvrを登録し、クライアントはレジストリにアクセスしてサービスアドレス情報のリストを取得します。その後、クライアントは必要に応じて適切な負荷分散方式を選択し、サービスを呼び出します。負荷分散は、ラウンドロビン、ハッシュ、重み付けなど、複数の方式をサポートしています。 障害ノードをより迅速に保護するために、クライアントは、呼び出されたサービスの呼び出し時に発生した異常に基づいて障害の有無を判断し、より迅速な障害保護を実現します。具体的には、クライアントからサーバーへの呼び出しで、設定されたしきい値を超えるタイムアウトが連続して発生した場合、またはタイムアウト率が特定のパーセンテージしきい値を超えた場合、クライアントはそのサーバーノードをブロックし、トラフィックを正常なノードにリダイレクトします。ブロックされたサーバーノードでは、定期的に再接続が試行され、成功すると通常のトラフィック分散が再開されます。 ビジネスの成長に伴い、サービス展開は必然的にデータセンターやリージョンをまたぐものになります。従来の負荷分散手法では、サービスがリージョンやデータセンターをまたいで展開される場合、ネットワークの問題によりレイテンシが増加する可能性があります。サービス間のアクセスを高速化し、リージョン間およびデータセンター間の展開に伴うネットワークリソースの消費を削減し、ネットワーク障害の影響を軽減するために、Tarsはリージョンを考慮した自動サービスガバナンス機能を提供します。 レジストリと開発フレームワークを使用して自動領域認識を実現する利点は次のとおりです。
さらに、Tars はSetモデルも提供します。 セットモデルは、ビジネス機能の特性に基づいてユニットをセットで展開することで、展開を標準化・標準化します。セットモデルの利点は次のとおりです。
トラフィック制御において、サービスリリースとデプロイメントにおいて直面する主な課題は、「業務に影響を与えずにサービス変更を行う方法」と「カナリアリリースの検証をいかに実施するか」です。Tarsでは、レジストリと開発フレームワークを通じてオンデマンドでトラフィック制御を実施し、ロスレスリリースとカナリアリリースの目標を達成できます。 言語サポートに関しては、これまでサポートされていた PHP、C++、NodeJS、Java に加えて、Golang サポートが追加されました。 さらに、Tars は、操作を可視化し、Web ベースで実行できるようにする OSS プラットフォームを提供します。 主に以下の特徴が含まれます。
ターズゴー、ターズゴー!多言語サポートはTarsの大きな強みです。TarsはこれまでにC++、Java、PHP、NodeJS版をリリースしています。Goのコルーチン並行処理メカニズムは、大規模で高並列なバックエンドサーバーアプリケーションの開発に非常に適しています。さらに、Docker、Kubernetes、Etcdといったコンテナ化技術の急速な発展に伴い、Goはますます人気が高まり、クラウドネイティブ環境で推奨される言語となっています。こうしてTarsのGo版が開発され、Tars-Goのリリースは、今日のクラウドネイティブ化が進む環境において特に重要な意味を持ちます。 新しくリリースされた Go バージョン Tars-Go の全体的なアーキテクチャは、次の図に示すように、3 つの主要な部分に分けられます。
編集者は、TarsオープンソースチームがTars-Goの開発中に、様々な側面でパフォーマンスチューニングと修正を行ったことを知りました。Tars-Goの初期バージョンは機能開発と改善に重点が置かれており、体系的な負荷テストとパフォーマンス分析が不足していました。ビジネスでの使用期間を経て、パフォーマンス最適化が優先事項となりました。Tarsオープンソースチームはまず、tars2goツールを最適化し、構文木生成プロセス中に型情報を生成することで、型チェックにリフレクションを使用しないようにすることで、エンコードとデコードの効率を2倍向上させました。その後、サービス全体に対して複数回の負荷テストを実施し、CPUプロファイリングによるパフォーマンス分析を実施しました。 以下に、パフォーマンスの改善と最適化の例をいくつか示します。 タイマーのパフォーマンスの問題 Tars-Goは、受信リクエストごとに処理用のgoroutineを作成します。呼び出しタイムアウトを処理するためにタイマーが作成され、リクエストが終了すると削除されます。同時実行性が高まると、タイマーの作成と削除が頻繁に行われ、サービスのCPU時間を大量に消費します。 開発チームは、マルチCPUシナリオにおいて多数のタイマーが存在するとパフォーマンスが著しく低下するという問題を発見しました。最適化のアプローチとして、各CPU (p) に独自のタイマーを割り当てることが挙げられます。これにより、全体的な同時実行パフォーマンスが大幅に向上する可能性があります。そのため、Tars-Goはコンパイル環境をバージョン1.10.3にアップグレードしました。プロファイルでは大幅なパフォーマンス向上が見られ、チームはタイムポーリングアルゴリズムに基づく独自のタイマーを実装することで、精度とパフォーマンス、そして効率性を両立させました。 ネットパッケージのSetDeadline呼び出しのパフォーマンスの問題 Tars-Goは、ネットワーク接続の読み取り/書き込みタイムアウトを設定するために、`net`パッケージの`SetReadDeadline`および`SetWriteDeadline`呼び出しを使用します。しかし、プロファイリングの結果、これらの呼び出しは高並列処理環境ではCPU時間を大量に消費することが判明しました。これらの呼び出しを回避するために、Sysfdを使用してソケットの読み取り/書き込みタイムアウトを設定します。 バイトバッファによるパフォーマンスの問題 下の図に示すように、時間の大部分はスライス関連の操作に費やされています。これは、パケットのエンコードおよびデコード処理中に、bytes.Bufferが一時記憶領域として使用されていることを示しています。基盤となるbytes.Bufferが使用するバイトスライスのサイズが不足すると、一定量のメモリ空間が割り当てられます。頻繁な割り当ては非効率であり、大きなパケットを処理する際にパフォーマンスが大幅に低下します。 Tars-Goは、RedisのメモリモデルとLinuxのスラブメカニズムに着想を得て、頻繁に作成・破棄されるオブジェクトに対して事前作成と再利用のアプローチを採用しています。Go言語自体は、一時オブジェクトを再利用してガベージコレクション(GC)を削減するための「sync.Pool」メカニズムを提供しています。これを基に、Tars-GoはLinuxのスラブメカニズムに類似したバッファ管理スキームを実装し、大幅なパフォーマンス向上を実現しています。 その他の最適化 上記のパフォーマンス最適化の後、 Tars-Go は小さなパケットの同時実行パフォーマンスを5 倍向上させました。
Tars-Goプログラミング例Tarsプロトコルは、言語に依存しないIDLで記述されたバイナリプロトコルです。ツールはサーバーとクライアントのコードを自動生成します。以下はTarsプロトコルの例です。 プログラミングを行うときは、まず次に示すように Tars ファイルを定義する必要があります。インターフェイス Mult を定義します。ここで、a と b は入力パラメータ、c は出力パラメータで、どちらも整数です。 次に、インターフェースコードを生成します。`tars2go JesseTest.tars` を使用すると、`Pragma JesseTest` フレームワークの `servant` メソッドと `Mult` メソッドのフレームワーク実装が自動的に生成されます。ビジネスロジックは実装の詳細を気にする必要はありません。 最後に、インターフェース コードを実装し、入力パラメータ a と b を乗算した結果を c に格納し、クライアントに返します。 その後、`go build` を使用してコンパイルできます。 クライアントは、入力パラメータと出力パラメータに焦点を合わせ、Tars ファイルから変換されたパッケージをインポートして RPC 呼び出しを完了するだけで済みます。 今後、Linux FoundationはTarsプロジェクトのコミュニティ運営メカニズムを強化し、Tarsの影響力を中国から国際舞台へと拡大していきます。
|