ポルノは 大きな産業 。最大のプレーヤーのトラフィックに匹敵するインターネット上のサイトは多くありません。
そして、この膨大なトラフィックをジャグリングするのは難しいです。さらに難しいことに、ポルノサイトから提供されるコンテンツの多くは、単純な静的ビデオコンテンツではなく、低遅延のライブビデオストリームで構成されています。しかし、関連するすべての課題について、私が読んだことはめったにありません Python開発者 それらを引き受ける人。そこで、自分の仕事の経験について書くことにしました。
数年前、私は ワーキング ポルノ業界だけでなく、世界で26番目(当時)に最も訪問されたWebサイト。
当時、このサイトはリアルタイムメッセージングプロトコル(RTMP)を使用してポルノビデオストリーミングリクエストを処理していました。具体的には、Adobeが構築したFlash Media Server(FMS)ソリューションを使用して、ユーザーにライブストリームを提供しました。基本的なプロセスは次のとおりです。
いくつかの理由から、FMSは、両方の購入を含むコストから始めて、私たちにとって良い選択ではありませんでした。
これらの料金はすべて上昇し始めました。コストはさておき、FMSは、特にその機能において欠けていた製品でした(これについては後で詳しく説明します)。そこで、FMSを廃棄して、独自のPythonRTMPパーサーを最初から作成することにしました。
mysqlはutf8に変換します
結局、私は私たちのサービスをおよそ20倍効率的にすることに成功しました。
関係する2つの主要な問題がありました。1つは、RTMPおよびその他のAdobeプロトコルとフォーマットが公開されておらず(つまり、公開されていない)、操作が困難でした。何も知らない形式のファイルをどのように反転または解析できますか?幸いなことに、私たちの仕事の基礎となった公共圏(Adobeによって作成されたのではなく、OS Flashと呼ばれるグループによって作成された)で利用可能ないくつかの逆転の取り組みがありました。
注:Adobeは後で「 仕様 」には、アドビが作成していない反転ウィキおよびドキュメントですでに開示されている情報よりも多くの情報が含まれていませんでした。彼らの(Adobeの)仕様はとてつもなく低品質であり、それを作りました ライブラリを実際に使用することはほぼ不可能です 。さらに、プロトコル自体が意図的に誤解を招くように見えることがありました。例えば:
そして第二に、RTMPは非常にセッション指向であるため、着信ストリームをマルチキャストすることは事実上不可能でした。理想的には、複数のユーザーが同じライブストリームを視聴したい場合は、そのストリームが放送されている単一のセッションへのポインターをユーザーに戻すことができます(これはマルチキャストビデオストリーミングになります)。しかし、RTMPでは、アクセスを必要とするすべてのユーザーに対して、まったく新しいストリームのインスタンスを作成する必要がありました。これは完全な無駄でした。
javascriptは、次のどの状況では使用できません
それを念頭に置いて、私は典型的な応答ストリームを再パッケージ化/解析することにしました FLVの「タグ」 (「タグ」は、ビデオ、オーディオ、またはメタデータの一部です)。これらのFLVタグは、ほとんど問題なくRTMP内を移動できます。
このようなアプローチの利点:
私は当時最もよく知っていた言語で開発を始めました。C。時間が経つにつれて、この選択は面倒になりました。そこで、Cコードを移植しながらPythonの基礎を学び始めました。開発プロセスはスピードアップしましたが、いくつかのデモの後、私はすぐにに遭遇しました 資源枯渇の問題 。 Pythonのソケット処理は、これらのタイプの状況を処理することを目的としていませんでした。具体的には、Pythonでは、アクションごとに複数のシステムコールとコンテキストスイッチを実行し、膨大なオーバーヘッドを追加していることがわかりました。
コードをプロファイリングした後、パフォーマンスが重要な関数を完全にCで記述されたPythonモジュールに移動することを選択しました。これはかなり低レベルのものでした。具体的には、カーネルを利用しました。 epoll 対数的な成長順序を提供するメカニズム。
非同期ソケットプログラミングには、特定のソケットが読み取り可能/書き込み可能/エラーで埋められているかどうかの情報を提供できる機能があります。これまで、開発者はselect()システムコールを使用してこの情報を取得していましたが、これは拡張性が低くなっています。 Poll()はselectの優れたバージョンですが、呼び出しのたびに一連のソケット記述子を渡す必要があるため、それほど優れていません。
あなたがしなければならないのはソケットを登録することだけであり、システムはその別個のソケットを記憶し、すべてのザラザラした詳細を内部で処理するので、Epollは素晴らしいです。したがって、呼び出しごとに引数を渡すオーバーヘッドはありません。また、スケーリングがはるかに優れており、関心のあるソケットのみを返します。これは、100kソケット記述子のリストを実行して、ビットマスクを含むイベントがあるかどうかを確認するよりもはるかに優れています。これは、他のソリューションを使用する場合に行う必要があります。
しかし、パフォーマンスの向上のために、私たちは代償を払いました。このアプローチは、以前とはまったく異なるデザインパターンに従いました。このサイトの以前のアプローチは、(私が正しく思い出せば)受信と送信をブロックする1つのモノリシックプロセスでした。私はイベント駆動型ソリューションを開発していたので、この新しいモデルに合うように残りのコードもリファクタリングする必要がありました。
具体的には、新しいアプローチでは、次のように受信と送信を処理するメインループがありました。
プライベートエクイティファンドの調達
これはデータのローリングウィンドウであり、クライアントが遅すぎて受信できない場合にフレームをドロップするためのヒューリスティックが含まれていました。物事はかなりうまくいった。
しかし、別の問題が発生しました。カーネルの コンテキストスイッチ 負担になっていた。その結果、瞬時ではなく、100ミリ秒ごとにのみ書き込むことを選択しました。これにより、小さいパケットが集約され、コンテキストスイッチのバーストが防止されました。
おそらく、サーバーアーキテクチャの領域には、より大きな問題があります。負荷分散とフェイルオーバーに対応したクラスターが必要でした。サーバーの誤動作が原因でユーザーを失うのは楽しいことではありません。最初は、指定された「ディレクター」が需要を予測することによって放送局のフィードを作成および破棄しようとする、別のディレクターのアプローチを採用しました。これは見事に失敗しました。実際、私たちが試したすべてはかなり実質的に失敗しました。最終的に、クラスターのノード間でブロードキャスターをランダムに共有し、トラフィックを均等化するという比較的強引なアプローチを選択しました。
これは機能しましたが、1つの欠点がありました。一般的なケースはかなりうまく処理されましたが、サイトの全員(または不均衡な数のユーザー)が1つの放送局を視聴したときにひどいパフォーマンスが見られました。良いニュース:これはマーケティングキャンペーンの外では決して起こりません。このシナリオを処理するために別のクラスターを実装しましたが、実際には、マーケティング活動のために有料ユーザーのエクスペリエンスを危険にさらすことは無意味であると推論しました。実際、これは実際には本物のシナリオではありませんでした(考えられるすべてのシナリオを処理するのは良かったのですが)場合)。
最終結果からのいくつかの統計:クラスターの1日のトラフィックは、ピーク時(60%の負荷)で約10万人のユーザーであり、平均で約5万人でした。私は2つのクラスター(HUNとUS)を管理しました。それぞれが約40台のマシンを処理して負荷を共有しました。クラスターの合計帯域幅は約50Gbpsであり、ピーク負荷時に約10Gbpsを使用していました。結局、私は10 Gbps /マシンを簡単に押し出すことができました。理論的には1、この数は1マシンあたり30 Gbpsに達する可能性があります。これは、1台のサーバーから同時にストリームを視聴している約30万人のユーザーに相当します。
既存のFMSクラスターには200台を超えるマシンが含まれていましたが、これを15台に置き換えることができました。実際の作業を行うのはそのうちの10台だけでした。これにより、約200/10 = 20倍の改善が得られました。
おそらく、Pythonビデオストリーミングプロジェクトからの私の最大のポイントは、新しいスキルセットを学ぶ必要があるという見通しにとらわれてはいけないということでした。特に、Python、トランスコーディング、およびオブジェクト指向プログラミングはすべて、このマルチキャストビデオプロジェクトに着手する前に私が非常に専門的でない経験をした概念でした。
それと、独自のソリューションをローリングすることで大きな利益が得られます。
1その後、コードを本番環境に移行したときに、PCI帯域幅が狭いために10ギガビットイーサネットカードを処理できない古いsr2500 Intelサーバーを使用していたため、ハードウェアの問題が発生しました。代わりに、1〜4x1ギガビットイーサネットボンドでそれらを使用しました(複数のネットワークインターフェイスカードのパフォーマンスを仮想カードに集約します)。最終的に、パフォーマンスの問題なしに10Gbpsの光ファイバを提供する新しいsr2600i7Intelをいくつか入手しました。予測されるすべての計算は、このハードウェアを参照しています。