Skip to content

Instantly share code, notes, and snippets.

@voluntas
Last active January 28, 2024 13:58
Show Gist options
  • Save voluntas/8d1f2100537db4f43bf412f9e2f24970 to your computer and use it in GitHub Desktop.
Save voluntas/8d1f2100537db4f43bf412f9e2f24970 to your computer and use it in GitHub Desktop.
Erlang/OTP で WebRTC と QUIC

Erlang/OTP で WebRTC と QUIC

日時

2019-06-01

voluntas

バージョン

19.06.2

URL

https://voluntas.github.io/

depth

3

2019 年 6 月 1 日に行われる Erlang & Elixir Fest 2019 の発表者用の資料です。

今回の資料はすでに http://bit.ly/erlang-webrtc-quic に公開されています

注意

この発表は、写真撮影、録音、録画はすべて禁止でお願いします。SNS への投稿は問題ありません。

自己紹介

Twitter ID は voluntas です。時雨堂の方から来ました。

概要

今日は WebRTC という仕組みを使ったパッケージ製品を Erlang/OTP で開発しているという話をします。 Erlang/OTP を利用することで実現できている会社の仕組みや、どんなプロトコルを利用した製品なのか、そして Erlang/OTP で作られた製品が多くのお客様のもとで安定的に可動するためにどうしているのかなど、現実的なつまらない話をしていこうと思います。

WebRTC に QUIC が組み込まれ始めたので QUIC も開発しているので、その話もおまけ程度にします。 こちらは期待はしないでください。

Erlang/OTP の話というよりかは Erlang/OTP を使って零細企業でがんばってるよという話なので、眠い人は寝てて大丈夫です。

パッケージ製品とは

お客様の環境で動作させるパッケージという提供方法です。

つまり自分の手を離れた瞬間からアップデート版の提供以外は何もできなくなります。

バグがあったりしたらすぐに直してデプロイなどは一切できません。 またインターネットから隔離された閉じたネットワークで利用される可能性だってあります。

自分のコントロール下にない中で、使われる製品。それがパッケージ製品です。

何を話すのか

実際に Erlang/OTP で書かれた自社のパッケージ製品だけで会社が回る所まで来ています。

Erlang/OTP でパッケージ製品を開発、販売し、売れ始めて、 会社としてどんな状況になって、どうしていっているのかを話していきます。

また、開発体制の話も触れられればと思います。

WebRTC とは

WebRTC という名前を知っている方はいらっしゃるかもしれませんが、実際どんなものか?というのを見たことがある人は少ないかもしれませんので、簡単に説明していきます。

WebRTC はブラウザ同士でリアルタイムな映像や音声、データをやり取りする仕組みです。ポイントはブラウザ同士というところです。

ブラウザはウェブサーバとやり取りするイメージだと思いますが、 WebRTC はウェブサーバを経由せず、ブラウザ同士で直接やり取りする技術です。

プロトコルは TCP ではなく UDP を利用します。

そのため、 WebRTC では再送制御や輻輳制御などをすべて自前で実装しています。簡単にいえばとても複雑なプロトコルと思っていただいて良いです。

どれだけ複雑なのかは WebRTC を実装するために必要な RFC 一覧をまとめた資料を御覧ください。

WebRTC 資料まとめ

ちなみに WebRTC は Chrome のリリースごとにアップデートします、つまり 6 週間ごとに更新されていく仕組みです。

どのくらリアルタイム?

WebRTC の RTC はリアルタイムコミニュケーションの略なんですが、 どのくらいリアルタイムかというと 200-300 ミリくらいの遅延です。

どのくらい複雑?

大変複雑です。少し古い資料ですが興味あれば是非読んでみてください。

詳解 WebRTC

WebRTC SFU とは

ブラウザ同士が直接やりとりする WebRTC の仕組みを無理やりサーバ経由にした仕組みが WebRTC SFU という仕組みです。

なぜせっかくブラウザ同士でやりとりできるのに、なぜサーバ経由?って思った人は多いと思います。

ブラウザ同士 1:1 ならいいんですが、やりとり先が 10 クライアントいた場合どうでしょうか。 1 クライアントが 10 クライアントの送ります。例えばこれがフル HD で 5Mbps の映像だとしたら、 50Mbps をクライアントが配信する必要があります。なかなか厄介です。

つまり配信を代理してくれるサーバが欲しくなります。それが WebRTC SFU です。

興味ある人は WebRTC SFU コトハジメ をどうぞ。

WebRTC SFU Sora とは

この WebRTC SFU を自社で実装したのが WebRTC SFU Sora です。

導入事例

多くの企業で導入していただいています。

WebRTC SFU Sora - 導入事例

Erlang/OTP

もちろん Erlang/OTP でできています。

フルスクラッチ

オープンソースをベースにしたとかではなく、1 からフルスクラッチで開発しています。 また WebRTC 関連のライブラリはすべて自社開発しています。

  • RTP / RTCP
    • リアルタイムなメディアパケットをやり取りするプロトコル
    • RTCP はそれのコントローラプロトコル
  • SDP
    • セッション確立用のプロトコル
  • STUN
    • NAT 超えのための補助プロトコル
  • TURN-UDP / TURN-TCP / TURN-IPv6
    • NAT 超えのためのリレープロトコル
    • UDP と TCP と IPv6 で挙動が異なる
  • DTLS
    • データグラム向け TLS
  • SRTP / SRTCP
    • RTP や RTCP を暗号化するプロトコル
  • EBML
    • WebM に利用されている仕組み
  • SCTP
    • UDP と TCP のいいところどりプロトコル
    • over UDP でユーザランドで実装

利用しているライブラリ

基本的なライブラリ以外は使用していません

できるだけ外部ライブラリに依存しないという方針をとっています。 すべて最新版を利用しており、何かあれば積極的に貢献していく方針です。

落ちない?

製品を販売してから 4 年経ちますが、一度も落ちたという報告を頂いていません。

開発体制

  • 最初は自分 1 人で開発してましたが、一昨年から新しく社員が入ってそれからは 2 人で開発しています
  • パッケージ製品自体は 2 名で開発しています
  • 2 人とも Erlang/OTP を利用した製品開発は 10 年以上あります
  • 自分が基本的な機能、もう 1 人が応用的な機能
    • つまり自分はプロトコルよりです

Erlang/OTP ルール

  • develop ブランチへのマージは Compile と Xref と Dialyzer は必ず通す
    • 通しさえすればマージして良い
  • コーディング規約はなんとなく守る
    • あってないのを見つけたら修正したければしても良い
  • 1 プロセスに働かせすぎない
  • できるだけ細かくプロセスの役割を分ける
  • メッセージパッシング数は減らす
  • 速度を Erlang VM に期待しない
  • gproc は使う
  • NIF は使わない
  • HiPE は使わない
  • 常に最新の Erlang VM を利用する
  • 常に最新の rebar3 を利用する
  • テストは EUnit を利用する
    • ct は利用しない

開発方針

  • ロードマップを引く
  • マネージメントはしない
  • コミニュケーションはできるだけ取らない
  • マージは積極的にする
  • 単体テストはあまり頑張らない
  • 新機能追加はできるだけしない
  • 内部実装は積極的に変える
  • 変更履歴は必須
  • ドキュメントは後回しにしない
  • 自動化を無理にしない
  • コードレビューは最低限
  • WebRTC ライブラリはできるだけ内製化する
  • 好み問題は開発している方が選択権あり
  • コミットログは適当でいい
  • コメントはしっかり書く
  • コードがドキュメント
  • 設計思想や方針は書きたければ書く
  • 顧客向けドキュメントはしっかり書く

継続開発

  • 大きめのリリースは年 2 回
    • 4 月と 10 月
    • バグ修正があれば、適時リリース
  • 積極的なリファクタリング
  • 抽象化しない
  • 減らせるコードはできるだけ減らす
  • 利用してるライブラリには常に最新版を利用する
    • バグがあった場合はフィードバックをできるだけする
  • とにかくコメント重視
  • CI は回す

テスト

  • 取り扱ってるのが音声や映像ということもあり、自動化は短期的にはあきらめる
    • 中長期的に 1-2 年かがりでシステムを作っていってる
    • ミドルウェアでかつ音声と映像、さらにネットワークよりとなるとかなり複雑になるためそう簡単にはできない
  • 自動化は長期的な視点で考える
  • 人間は高機能なので、テストは人海戦術でいく

自社製品

複雑な機能の実現

WebRTC SFU Sora にはスポットライト機能という機能があります。

この機能は 1 ルームに 200 人はいっても、 直近で話をした 5 人の映像と音声だけを配信するという仕組みです。

これを中央集権管理ではなく、実装しています。遅延が 200 ミリという中で、リアルタイムに音声が会った場合の切り替え機能を実現しています。

また 5 人以外の音声や映像はパケットを破棄したりしています。

実際の動きをみてください。

https://www.youtube.com/watch?v=rz9NJfeX1Js

設計半年、実装半年、この機能を実現している製品は世界で WebRTC SFU Sora だけです。

数字の話

数値は実際に確認したわけではなく当時の状況を思い出しながら試算した値です

あまり数字の話は好きではないのですが、少しだけ。

WebRTC は UDP のため約 1200 バイト単位で分割する必要があります。

1.5Mbps の映像を 300 人に配信することを考えると、まず回線が 450Mbps 必要になります。 そして 1 人に対して 1250/秒 パケットが必要になります。

300 人に対してだと 1 サーバで 375,000/秒 パケットになります。

検証ではありますが 800kbps を 500 人に対して 8 ルームというのを 1 サーバで検証したことがあります。

リクエスト 約 666/秒 * 500 人 * 8 ルーム = 約 2,664,000/秒 パケットを処理していることになります。 CPU 使用率は 9000% (96 コアのサーバでした) でした。

WebRTC と QUIC

WebRTC が利用しているプロトコルはモダンなプロトコルではないため、 RTP/RTCP や SCTP を QUIC に置き換えていくという流れがきています。

QUIC API for Peer-to-peer Connections

そのため、自社でも QUIC の実装を進めています。

QUIC 実装

QUIC には TLS 1.3 の実装が必要なのですが、 TLS 1.3 を一部省略した TLS のため QUIC TLS としてフルスクラッチで実装しています。

https://github.com/quicwg/base-drafts/wiki/Implementations#sora_quic

実装はサーバとライブラリのみで、クライアントは実装せず ngtcp2 や quiche などで動作を確認しています。

最低限の実装は終わっており、実際に WebRTC に QUIC になったタイミングで自社製品にも載せていく予定です。

実装した話などはすべて公開していますので、興味があればみてみてください。 最近は WebRTC を優先していることもあり、実装はしていません。ただ QUIC や TLS 1.3 自体は追いかけています。

時雨堂 QUIC 開発ログ

おまけ

BEAMJIT

どうなるかわかりませんが、 Erlang VM の JIT 対応にかなり期待してます。

socket モジュール

OTP-22.0 で入って OTP-23.0 (2020 年) では gen* 系が socket モジュールに切り替わるそうです。

gen_tcp を socket モジュールを書き換えて簡単にベンチマークを取得 CPU 使用率が 40% 減ったそうで、かなり期待してます。

logger モジュール

ssl モジュールが logger を利用したカスタムモジュールを提供したりと、標準 logger がかなり力をつけてきています。

今までは lager を使っていましたが lager は 4.0 から logger のラッパーになるようです。

Erlang/OTP を利用しています

FGO を支える負荷試験ツール – shiguredo – Medium

Erlang Ecosystem Foundation

Lifetime Supporting Membership x 2 です。

貢献

OTP

ag voluntas:

lib/eldap/AUTHORS
7:     voluntas

ag shinohara:

erts/doc/src/notes.xml
11374:      Thanks to Tuncer Ayaz and Shunichi Shinohara for

lib/tools/doc/src/notes.xml
1326:       Shinohara)</p>

lib/stdlib/doc/src/notes.xml
4390:       Shunichi Shinohara)</p>

rebar3

ag shinohara:

THANKS
49:Shunichi Shinohara
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment