LoginSignup
55
24

More than 1 year has passed since last update.

[翻訳] Real time communication at scale with Elixir at Discord

Last updated at Posted at 2020-10-10

Elixir Digitalization Implementors/fukuoka.ex/kokura.ex の piacere です
ご覧いただいて、ありがとうございます :bow:

創業からElixirを採用し、毎年のように前人未到の高性能を達成している「Discord」が、2020年10月8日、秒間2,600万を超えるWebSocketイベントを、1,200万ユーザに同時配信していることをレポートした「Real time communication at scale with Elixir at Discord」を発表したので、翻訳してみました

Real time communication at scale with Elixir at Discord
https://elixir-lang.org/blog/2020/10/08/real-time-communication-at-scale-with-elixir-at-discord/

内容が、面白かったり、役に立ったら、「LGTM」よろしくお願いします :wink:

:ocean::ocean::ocean: Advent Calendar、fukuoka.ex1位、Elixir2位達成ヽ(=´▽`=)ノ :ocean::ocean::ocean:

fukuoka.ex Advent Calendar、Webテクノロジーカテゴリで堂々1位 … 各コラムぜひお読みください
https://qiita.com/advent-calendar/2020/fukuokaex
image.png

そして、プログラミング言語カテゴリは、1位がRust、2位がElixir、3位がGoとモダン言語揃い踏みでのトップ3、熱いネー:laughing:
https://qiita.com/advent-calendar/2020/elixir
image.png

DiscordのElixirによる大規模リアルタイム通信(Real time communication at scale with Elixir at Discord)

Founded in 2015 by Jason Citron and Stan Vishnevskiy, Discord is a permanent, invite-only space for your communities and friends, where people can hop between voice, video, and text, depending on how they want to talk, letting them have conversations in a very natural or authentic way.

Today, the service has over 100 million monthly active users from across the globe.

Every day people spend 4 billion minutes in conversation on Discord servers, across 6.7 million active servers / communities.

From day one, Discord has used Elixir as the backbone of its chat infrastructure.

When Discord first adopted the language, they were still working on building a viable business, with many questions and challenges in front of them.

Elixir played a crucial role in giving them the desired technological flexibility to grow the company and also became the building block that would allow their systems to run on a massive scale.

Discordは、2015年にジェイソン・シトロンとスタン・ヴィシュネフスキーによって設立された、コミュニティと友人達のための招待制限定スペースで、話し方に応じて、音声とビデオ、テキストを行き来できる、ナチュラルまたは正真正銘の会話を提供します

現在このサービスは、世界中に1億人を超える月間アクティブユーザーがいます

人々は毎日、670万のアクティブなサーバー/コミュニティに渡り、Discordサーバ上で40億分の会話を行っています

Discordは初日から、チャットインフラのバックボーンとしてElixirを使用してきました

Discordが、最初にこの言語を採用したとき、まだ実行可能なビジネスの構築に取り組んでおり、多くの疑問と課題が目の前にありました

Elixirは、会社を成長させるために必要な技術的柔軟性の提供の上で重要な役割を果たし、システムを大規模スケールできるようにするためのビルディングブロックにもなりました

image.png

立上げ時のテクノロジー(Starting technologies)

Back in 2015, Discord chose two main languages to build their infrastructure: Elixir and Python.

Elixir was initially picked to power the WebSocket gateway, responsible for relaying messages and real-time replication, while Python powered their API.

Nowadays, the Python API is a monolith while the Elixir stack contains 20 or so different services.

These architectural choices do not represent a dichotomy between the languages but rather a pragmatic decision.

Mark Smith, from the Discord team, explains it succinctly:

“given the Elixir services would handle much bigger traffic, we designed them in a way where we could scale each service individually.”

Discord has also explored other technologies along the way, Go and Rust being two examples, with distinct outcomes.

While Discord completely phased out Go after a short foray, Rust has proven to be an excellent addition to their toolbox, boosted by its ability to play well with Elixir and Python.

2015年、Discordはインフラ構築にElixirとPythonの2つのメイン言語を選択しました

Elixirは当初、メッセージのリレーとリアルタイムレプリケーションを担うWebSocketゲートウェイを提供するために選ばれ、PythonはAPIを提供しました

現在、Python APIはモノリシック(一枚岩)ですが、Elixirスタックには20個ほどの異なるサービスが含まれています

これらのアーキテクチャ上の選択は、言語間の二者択一ではなく、むしろ実用的な決定です

Discordチームのマーク・スミスは、簡潔に説明します

「Elixirサービスがより大きなトラフィックを処理することを考え、私達は、各サービスを個別にスケールできるやり方で設計しました」

Discordは、その過程で他のテクノロジーも調査しましたが、GoとRustはその2つの例で、明確な結果が得られています

Discordは、短期間の攻略の後、Goを完全に廃止しましたが、Rustは、ElixirやPythonとうまく連携できることで後押しされ、ツールボックスへの優れた追加機能だと実証されました

大規模なコミュニケーション(Communication at scale)

Effective communication plays an essential role when handling millions of connected users concurrently.

To put things into perspective, some of Discord’s most popular servers, such as those dedicated to Fortnite and Minecraft, are nearing six hundred thousand users.

At a given moment, it is not unlikely to encounter more than two hundred thousand active users in those servers.

If someone changes their username, Discord has to broadcast this change to all connected users.

Overall, Discord’s communication runs at impressive numbers.

They have crossed more than 12 million concurrent users across all servers, with more than 26 million WebSocket events to clients per second, and Elixir is powering all of this.

何百万もの同時接続ユーザーを処理する場合、効果的なコミュニケーションは重要な役割を果たします

状況を俯瞰すると、フォートナイトや、マインクラフトなど、Discordで最も人気のあるサーバーのいくつかは60万人のユーザーに近付いています

ある瞬間に、これらのサーバーで20万人を超えるアクティブユーザーに遭遇する可能性はほとんどありません

もし誰かがユーザー名を変更した場合、Discordは接続されているすべてのユーザーに、この変更をブロードキャストする必要があります

全体として、Discordのコミュニケーションは、見事な数字を捌いています

1200万人を超える同時ユーザーが全てのサーバーに点在し、そのクライアントには1秒あたり2600万件以上のWebSocketイベントが送信され、そしてElixirはこの全てを提供します

リアルタイム通信の観点から、ErlangVMはこの仕事に最適なツールです(In terms of real time communication, the Erlang VM is the best tool for the job)

— Jake Heinz、リードソフトウェアエンジニア

When we asked their team “Why Elixir?”, Jake Heinz gave a straight-forward answer:

“In terms of real time communication, the Erlang VM is the best tool for the job. It is a very versatile runtime with excellent tooling and reasoning for building distributed systems”.

Technologically speaking, the language was a natural fit.

However, Elixir was still a bet back in 2015:

“Elixir v1.0 had just come out, so we were unsure in which direction the language would go. Luckily for us, we have been pleased with how the language has evolved and how the community shaped up.”

私達のチームに「なぜElixir?」と尋ねたところ、ジェイク・ハインツは単純明快な回答をしました

「リアルタイムコミュニケーションの観点から、Erlang VM(≒Elixirのコアとなっている仮想マシン)はこれを果たすのに最適なツールです。分散システムを構築するための優れたツールと根拠を備えた多彩なランタイムです」

技術的に言えば、言語はナチュラルにフィットしました

しかし、2015年におけるElixirは、まだ賭けでした

「Elixirバージョン1.0がリリースされたばかりだったため、言語がどの方向に進むかは分かかりませんでした。幸運なことに、言語が進化度合いと、コミュニティの形成度合いには満足しています」

チャットインフラチーム(The chat infrastructure team)

To power their chat messaging systems, Discord runs a cluster with 400-500 Elixir machines.

Perhaps, the most impressive feat is that Discord’s chat infrastructure team comprises five engineers.

That’s right: five engineers are responsible for 20+ Elixir services capable of handling millions of concurrent users and pushing dozens of millions of messages per second.

Discord also uses Elixir as the control plane of their audio and video services, also known as signaling, which establishes communication between users.

C++ is then responsible for media streaming, a combination that altogether runs on 1000+ nodes.

チャットメッセージングシステムを提供するために、Discordは400~500台のElixirマシンでクラスターを実現しています

恐らく最も印象的な偉業は、Discordのチャットインフラチームが、5人のエンジニアで構成されていることです

そうです、5人のエンジニアが、数百万の同時ユーザーを処理し、1秒間に数千万のメッセージをプッシュできる20個以上のElixirサービスを担当しています

Discordは、ユーザー間の通信を確立する「シグナリング」と呼ばれる音声/動画サービスのコントロールプレーンとしてもElixirを使っています

C++は、メディアストリーミングを担い、これは、合計で1000個以上のノードで走っている組み合わせです

The Elixir services communicate between them using Distributed Erlang, the communication protocol that ships as part of the Erlang Virtual Machine.

By default, Distributed Erlang builds a fully meshed network, but you can also ask the Erlang VM to leave the job of outlining the topology up to you, by setting the aptly named -connect_all false flag.

The Discord team sets this option to assemble a partially meshed network with etcd being responsible for service discovery and hosting shared configuration.

The chat infrastructure developers are not the only ones touching the Elixir codebases.

According to Mark Smith, this is an important part of Discord’s culture:

“We don’t work in silos. So a Python developer may have to work on the Elixir services when building a new feature. We will spec out the feature together, figure out the scalability requirements, and then they will work on a pull request, which we will review and help them iterate on it.”

Elixirサービスは、Erlang VMの一部としてバンドルされている通信プロトコルである分散Erlangでコミュニケートしています

デフォルトで分散Erlangは、完全にメッシュ化されたネットワークを構築しますが、「-connect_all」フラグをfalseに設定することで、Erlang VMにこのトポロジーの停止をさせることもできます

Discordチームは、このオプションを設定して、部分的にメッシュ化されたネットワークを構築し、etcdがサービス検出と共有構成のホスティングを担います

Elixirのコードベースに触れているのは、チャットインフラ開発者だけではありません

マーク・スミスによると、これはDiscordの文化の重要な部分です

「私たちはサイロで作業しません。そのため、Python開発者は、新機能を作るときにElixirサービスに取り組む必要が出てきます。機能を一緒に特定し、スケーラビリティ要件を把握してから、プルリクエストをレビューし、(開発の)イテレートを支援し、処理します」

コミュニティと課題(Community and challenges)

To run at this scale, Discord learned how to leverage the Erlang VM’s power, its community, and when to recognize challenges that require them to reach for their own solutions.

For example, Discord uses Cowboy for handling WebSocket connections and TCP servers.

To manage data bursts and provide load regulation, such as back-pressure and load-shedding, they use GenStage, which they have discussed in detail in the past.

Other times, the efforts of the company and the community go hand in hand.

That was the case when Discord used the Rustler project, which provides a safe bridge between Elixir and Rust, to scale to 11 million concurrent users.

この規模で実行するために、Discordは、Erlang VMのパワーとそのコミュニティにレバレッジをかける方法と、独自のソリューションに到達すべき課題をいつ認識するかを学びました

たとえばDiscordは、WebSocket接続とTCPサーバーのハンドリングにCowboy(≒Erlangの高速HTTPサーバ)を使用します

データバースト(≒短期的な大量データ)を管理し、バックプレッシャー(≒送信制御)および負荷遮断としてロードレギュレーション(≒通信負荷を安定化させる統制)を提供するためには、以前にもコラムで詳細に説明したGenStage(≒多段ステージでバックプレッシャーベースのPubSubを制御するElixirライブラリ)を使います

また、企業とコミュニティで手を取り合う努力もしています

Discordが、ElixirとRustの間に安全なブリッジを提供するRustlerプロジェクトを使用して、1,100万人の同時ユーザー拡張をしたケースが、これに当てはまります

They used the Rustler to hook a custom data structure built in Rust directly into their Elixir services.

However, the team has made abundantly clear that the powerhouse is the Erlang platform.

Every time they had to push their stack forward, they never felt cornered by the technology.

Quite the opposite, their engineers could always build efficient solutions that run at Discord’s scale, often in a few hundred lines of code.

Discord frequently gives these projects back to the community, as seen in Manifold and ZenMonitor.

The Discord team also adapted quickly when things went wrong.

For instance, they attempted twice to use Mnesia in production —a database that ships as part of Erlang’s standard library.

They tried Mnesia in persistent and in-memory modes, and the database nodes would often fall behind in failure scenarios, sometimes being unable to ever catch up.

Eventually they ditched Mnesia altogether and built the desired functionality with Erlang’s builtin constructs, such as GenServer and ETS.

Nowadays, they resolve these same failure scenarios within 2-3 seconds.

彼らはRustlerを使って、Rustに組み込まれているカスタムデータ構造をElixirサービスに直接フックしました

しかしチームは、その原動力がErlangプラットフォームであることを充分に明らかなものとしました

彼らは、(Elixirの)スタックを前進させる必要があるたび、テクノロジーに追い詰められたと感じることはありませんでした

正反対に、エンジニアは常にDiscordの規模で、数百行のコードで実行される効率的なソリューションを構築できました

Discordは、Manifold(≒プロセス間通信をバッファリングして負荷減少させるElixirライブラリ)ZenMonitor(≒リモートプロセスを効率良く監視できるElixirライブラリ)に見られるように、これらのプロジェクトをコミュニティに頻繁にバックしています

Discordチームは、問題が発生したときにも迅速に対応しました

たとえば、Erlang標準ライブラリの一部としてバンドルされているDBであるMnesia(≒分散インメモリDB)を本番環境で2回、使おうとしました

彼らは、永続モード(≒ディスクにDBデータを保存するモード)とインメモリモードでMnesiaを試しましたが、DBノードは障害シナリオで遅れることが多く、追いつけない場合がありました

最終的に、彼らはMnesiaを完全に捨て、GenServer(≒Elixir/Erlangの軽量サーバプロセステンプレート)ETS(≒標準バンドルの非分散インメモリDB)などのErlangの組み込み構造を使用して、目的の機能を構築しました

現在、同様の障害シナリオは2~3秒で解決されます

エリクサーをマスターする(Mastering Elixir)

None of the chat infrastructure engineers had experience with Elixir before joining the company.

They all learned it on the job.

Team members Matt Nowack and Daisy Zhou report initially struggling to understand how all of their services communicate.

Matt adds:

“In the beginning, it was hard to accept all of the guarantees that Erlang VM provides. I’d worry about data races and concurrency issues that were impossible to happen”.

Eventually, they took these guarantees to heart and found themselves more productive and more capable of relying on the platform and its tools.

Matt continues:

“The introspection tools the Erlang VM provides is the best in class. We can look at any VM process in the cluster and see its message queue. We can use the remote shell to connect to any node and debug a live system. All of this has helped us countless times.”

チャットインフラエンジニアは、入社前にElixirの経験がありませんでした

彼らはみな、仕事の中でそれを学びました

チームメンバーのマット・ノワックとデイジー・チョウは、最初はすべてのサービスがどのように通信するかを理解するのに苦労した、と報告しています

Mattは次のように付け加えています

「当初、Erlang VMが提供するすべての保証を受け入れることは困難でした。(Erlang VMでは)起こり得ないデータの競合や同時実行の問題について心配していました」

最終的に、彼らはこれらの保証を心に刻み、プラットフォームとそのツールに依存することで、より生産的になれることに気付きました

マットは続けます

「Erlang VMが提供するイントロスペクションツールは最高級です。クラスター内の任意のVMプロセスを調べて、そのメッセージキューを確認できます。リモートシェルを使用して、任意のノードに接続し、動いているシステムをデバッグできます。これら全てが、私達を数え切れないほど助けてくれました」

Running at Discord’s scale adds its own dimension to mastering the language, as they need to familiarize with the abstractions for providing concurrency, distribution, and fault-tolerance.

Nowadays, frameworks such as Nerves and Phoenix handle these concerns for developers, but the underlying building blocks are always available for engineers assembling their own stack, such as the Discord team.

In the end, Jake summarized how crucial Elixir and the Erlang VM have been at Discord and how it affected him personally:

“What we do in Discord would not be possible without Elixir. It wouldn’t be possible in Node or Python. We would not be able to build this with five engineers if it was a C++ codebase. Learning Elixir fundamentally changed the way I think and reason about software. It gave me new insights and new ways of tackling problems.”

Discordの規模での実行には、並行性、分散、および耐障害性を提供するための抽象化に精通する必要があるため、独自の言語習得が追加されます

現在、Nerves(≒ElixirのIoTフレームワーク)Phoenix(≒Elixirの軽量Webフレームワーク)などのフレームワークは、開発者のこれら懸念に対処していますが、Discordチームのような、独自のスタックを組み立てるエンジニアは、より基礎的なビルディングブロックを利用します

最後にジェイクは、ElixirとErlang VMが、Discordでどれほど重要で、それが彼のパーソナリティにどのように影響したかをサマリーしました

「Discordで行うことはElixir無しでは不可能です。Node.jsやPythonでは不可能です。また、C++コードベースでは、5人のエンジニアでこれを構築することはできません。Elixirを学ぶことで、ソフトウェアについての私の考え方や根拠が根本的に変わりました。それは私に新しい洞察と問題に取り組む方法を与えてくれました」

終わり

Discordという全世界にスケールする有名サービスにおいて、Elixirがどのように活用され、貢献しているかの様子が見えたでしょうか?

5年前の2015年、Discordがサービス開始した当初は、まだまだElixirは未成熟で、そこからの数年で、言語/コミュニティの両方が、順調に成長し、Discordを支え続け、Discordもコミュニティに貢献していった…

そういった「企業とコミュニティが手を取り合うエコシステム」によって、1200万人同時ユーザー/秒間2600万件以上のWebSocketイベントを処理できる巨大なプラットフォームに成長していった訳です

そして、入社当時はElixirを知らなかったエンジニア達が、やはり数年でキャッチアップし、Elixirが、Node.jsやPythonでは不可能な様々を提供し、一方で、性能面で上を行くC++では叶わない驚異的な生産性をも実現している様子が伝われば幸いです

なおDiscordは、他にもこの数年、Elixirを活用した実績をブログで説明していますので、ご興味あればご覧ください

2017年のDiscord発表

How Discord handles push request bursts of over a million per minute with Elixir’s GenStage
https://blog.discord.com/how-discord-handles-push-request-bursts-of-over-a-million-per-minute-with-elixirs-genstage-8f899f0221b4

2018年のDiscord発表

How Discord Scaled Elixir to 5,000,000 Concurrent Users
https://blog.discord.com/scaling-elixir-f9b8e1e7c29b

2019年のDiscord発表

Using Rust to Scale Elixir for 11 Million Concurrent Users
https://blog.discord.com/using-rust-to-scale-elixir-for-11-million-concurrent-users-c6f19fc029d3


EDI/fukuoka.ex/kokura.ex のイベントでは、このような全世界のElixir情報や実装例、それらを試したライブデモを披露することもあるので、ご興味あれば、下記URLでメンバー登録してください

:sunny::sunny::sunny: 本コラム、Qiitaトップランキング4位獲得、ありがとございますヽ(=´▽`=)ノ :sunny::sunny::sunny:
image.png

p.s.このコラムが、面白かったり、役に立ったら…

image.pngimage.png にて、どうぞ応援よろしくお願いします:bow:

55
24
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
55
24