日時: | 2019-06-01 |
---|---|
作: | voluntas |
バージョン: | 19.06.2 |
URL: | https://voluntas.github.io/ |
Contents
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 はウェブサーバを経由せず、ブラウザ同士で直接やり取りする技術です。
プロトコルは TCP ではなく UDP を利用します。
そのため、 WebRTC では再送制御や輻輳制御などをすべて自前で実装しています。簡単にいえばとても複雑なプロトコルと思っていただいて良いです。
どれだけ複雑なのかは WebRTC を実装するために必要な RFC 一覧をまとめた資料を御覧ください。
ちなみに WebRTC は Chrome のリリースごとにアップデートします、つまり 6 週間ごとに更新されていく仕組みです。
WebRTC の RTC はリアルタイムコミニュケーションの略なんですが、 どのくらいリアルタイムかというと 200-300 ミリくらいの遅延です。
大変複雑です。少し古い資料ですが興味あれば是非読んでみてください。
ブラウザ同士が直接やりとりする WebRTC の仕組みを無理やりサーバ経由にした仕組みが WebRTC SFU という仕組みです。
なぜせっかくブラウザ同士でやりとりできるのに、なぜサーバ経由?って思った人は多いと思います。
ブラウザ同士 1:1 ならいいんですが、やりとり先が 10 クライアントいた場合どうでしょうか。 1 クライアントが 10 クライアントの送ります。例えばこれがフル HD で 5Mbps の映像だとしたら、 50Mbps をクライアントが配信する必要があります。なかなか厄介です。
つまり配信を代理してくれるサーバが欲しくなります。それが WebRTC SFU です。
興味ある人は WebRTC SFU コトハジメ をどうぞ。
この WebRTC SFU を自社で実装したのが WebRTC SFU Sora です。
多くの企業で導入していただいています。
もちろん 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 でユーザランドで実装
基本的なライブラリ以外は使用していません
できるだけ外部ライブラリに依存しないという方針をとっています。 すべて最新版を利用しており、何かあれば積極的に貢献していく方針です。
- rebar3
- https://github.com/erlang/rebar3
- ビルドライブラリ
- lager
- https://github.com/erlang-lager/lager
- ログ出力ライブラリ
- gproc
- https://github.com/uwiger/gproc
- プロセス名前付けライブラリ
- ranch
- https://github.com/ninenines/cowlib
- TCP ライブラリ
- cowboy
- https://github.com/ninenines/cowboy
- HTTP サーバ
- uuid
- https://github.com/okeuday/uuid
- UUID ライブラリ
- jsone
- https://github.com/sile/jsone
- JSON ライブラリ
- hackney
- https://github.com/benoitc/hackney
- HTTP クライアント
- reacon
- https://github.com/ferd/recon
- デバッグライブラリ
製品を販売してから 4 年経ちますが、一度も落ちたという報告を頂いていません。
- 最初は自分 1 人で開発してましたが、一昨年から新しく社員が入ってそれからは 2 人で開発しています
- パッケージ製品自体は 2 名で開発しています
- 2 人とも Erlang/OTP を利用した製品開発は 10 年以上あります
- 自分が基本的な機能、もう 1 人が応用的な機能
- つまり自分はプロトコルよりです
- develop ブランチへのマージは Compile と Xref と Dialyzer は必ず通す
- 通しさえすればマージして良い
- コーディング規約はなんとなく守る
- あってないのを見つけたら修正したければしても良い
- 1 プロセスに働かせすぎない
- できるだけ細かくプロセスの役割を分ける
- メッセージパッシング数は減らす
- 速度を Erlang VM に期待しない
- gproc は使う
- NIF は使わない
- HiPE は使わない
- 常に最新の Erlang VM を利用する
- 常に最新の rebar3 を利用する
- テストは EUnit を利用する
- ct は利用しない
- ロードマップを引く
- マネージメントはしない
- コミニュケーションはできるだけ取らない
- マージは積極的にする
- 単体テストはあまり頑張らない
- 新機能追加はできるだけしない
- 内部実装は積極的に変える
- 変更履歴は必須
- ドキュメントは後回しにしない
- 自動化を無理にしない
- コードレビューは最低限
- WebRTC ライブラリはできるだけ内製化する
- 好み問題は開発している方が選択権あり
- コミットログは適当でいい
- コメントはしっかり書く
- コードがドキュメント
- 設計思想や方針は書きたければ書く
- 顧客向けドキュメントはしっかり書く
- Sphinx は素晴らしい
- 大きめのリリースは年 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 が利用しているプロトコルはモダンなプロトコルではないため、 RTP/RTCP や SCTP を QUIC に置き換えていくという流れがきています。
QUIC API for Peer-to-peer Connections
そのため、自社でも 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 自体は追いかけています。
どうなるかわかりませんが、 Erlang VM の JIT 対応にかなり期待してます。
OTP-22.0 で入って OTP-23.0 (2020 年) では gen_* 系が socket モジュールに切り替わるそうです。
gen_tcp を socket モジュールを書き換えて簡単にベンチマークを取得 CPU 使用率が 40% 減ったそうで、かなり期待してます。
ssl モジュールが logger を利用したカスタムモジュールを提供したりと、標準 logger がかなり力をつけてきています。
今までは lager を使っていましたが lager は 4.0 から logger のラッパーになるようです。
- Andrew Thompson - Erlang logging for the 21st OTP | Code BEAM SF 19 - YouTube
- TLS logging improvements in OTP 22 – A Blog from the Erlang/OTP team – The Erlang/OTP team at Ericsson, the implementors and maintainers of Erlang/OTP.
FGO を支える負荷試験ツール – shiguredo – Medium
Lifetime Supporting Membership x 2 です。
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>
ag shinohara:
THANKS 49:Shunichi Shinohara