メインコンテンツへスキップ

Elixirで新しいBitTorrentトラッカー作ってみた!

·3 分
2025/06 Elixir BitTorrent P2P ネットワーク プログラミング

Elixirで新しいBitTorrentトラッカー作ってみた!

引用元:https://news.ycombinator.com/item?id=44323253

dahrkael 2025/06/19 22:49:49

ElixirとGoの勉強でBitTorrentトラッカーを3ヶ月で作ってみたよ!DHTとかPEXが普通だけど、パブリックトラッカーにはまだ意味あると思う。みんなopentrackerとか使う中、これはクラッシュしないのが売りさ(aquaticとtorrustは別ね)。今後も開発続けるよ。swarm_printout.ex以外は手書きさ。dockerイメージもあるから試してみて!

nesarkvechnep 2025/06/20 09:33:56

OTPファーストな設計を見たかったな。残念ながら、コードはほぼ手続き的で、ETSとかApplicationをほぼ全ての操作で使ってるね。ElixirやBEAM言語でOTP設計を学びたいなら、James Edward GrayとBruce Tateの”Designing Elixir Systems with OTP”と、Lance Halvorsenの”Functional Web Development with Elixir, OTP, and Phoenix”って本を読んでみるといいよ。

dahrkael 2025/06/20 10:08:52

最初にもっとOTPっぽく書いたんだけど、この機能の特定フローにはスケーリングが合わなかったんだよね。結局トラッカーって特殊なデータベースみたいなもんで、データを最速で処理するのが一番の目標だからさ。まあ、教えてもらった本は読んでみるよ。

salviati 2025/06/20 12:08:19

もし俺みたいにこの文脈でOTPって何?って人がいたら、これだよ。OTPはOpen Telecom Platformの略だけど、もう通信だけって感じじゃないね(通信アプリケーションみたいな性質のソフトウェアってことだけど)。Erlangの偉大さの半分がConcurrencyとDistributionにあるとして、もう半分がError Handling能力にあるなら、OTPフレームワークはその”第三の半分”さ。詳しくはこっち見て!
https://learnyousomeerlang.com/what-is-otp

andyleclair 2025/06/21 03:12:47

BitTorrentトラッカーをGenServersで作るなんて全然意味ないよ。単一サーバー構成ならETSが100パーセント正しい選択だね。明らかに水平スケールはしないけど、垂直には月に届くくらい伸びるし、大抵の場合YAGNI(You Ain’t Gonna Need It)なんだってば。

lawik 2025/06/21 14:46:45

ElixirとErlangのすごいところの多くは、すごく分かりやすいコードなのにパフォーマンスが良いってとこだよね。追加のGenServersとかgen_statemsがクールなケースもあるけど、ElixirとPhoenixを使う多くの場面で変に凝ったアーキテクチャを選ぶ必要はないんだ。だってランタイムがもう十分クールにしてくれてるからね。

Zarathu 2025/06/20 17:40:04

ちょっと知りたいんだけど、「OTPファースト」な設計ってどんなの?ETSはOTPに組み込まれてるのに、どうしてETSを使うのが「OTPファーストじゃない」の?ETS使うのって何が悪いの?コード見たけど、手続き的ってほど全然近くないと思ったな。

b0a04gl 2025/06/20 17:10:52

面接のためにElixirを1週間だけ勉強したんだけど、落ちたんだ。でも、あの1週間でコードの書き方がマジで変わったよ。state isolationとか、shared dataなしとか、失敗してきれいに再起動とかね。今回のコード見て、派手なGenServersじゃなくて、速いプロセスとか生のETS、シンプルな流れだけどちゃんと障害考慮してる。同じ考え方だなって思ったよ。きれいだね。

voicedYoda 2025/06/20 02:57:34

よくやったね。いくつか簡単なアドバイスなんだけど、IO.putsじゃなくてLoggerに切り替えること。あとOTelを追加することも検討してみて。

solid_fuel 2025/06/20 04:01:03

Logger[0]とTelemetry[1]で十分だと思うな。OpenTelemetryとかもTelemetryのフックで後から追加できるから大丈夫だよ。
[0] https://hexdocs.pm/logger/1.18.4/Logger.html
[1] https://hexdocs.pm/telemetry/readme.html

dahrkael 2025/06/20 08:42:46

Loggerはテーブルのきれいな表示以外で全部使ってるよ。
TelemetryはPrometheusとかHTML形式でもオプションで使えるみたいね: https://github.com/Dahrkael/ExTracker/tree/master/lib/ex_tra

ai-christianson 2025/06/20 03:06:39

一番好きなOpenTelemetryのシンクって何?

s-mon 2025/06/20 02:10:49

Elixir超好き!今これでイケてる通知エンジン作ってるとこ。マジ最高。

mikehostetler 2025/06/20 02:30:08

それってOSS?それともプライベートなの?Elixirにはマジでもっと良い通知エンジンが必要とされてるよ。

rhgraysonii 2025/06/20 05:27:27

通知エンジンが必要って具体的にどういうこと?PhoenixのPubSub使えばすごく簡単だし実績もあるよ。俺は何回か大規模で実装したし。どんな問題にぶつかってて、今のツールじゃダメだと感じるの?

rhgraysonii 2025/06/20 05:28:53

自分で作らずに買うなら、Knock.appってのを見てみて。これもElixirでできてるよ: https://knock.app

abrookewood 2025/06/20 01:26:52

リリースおめでとう!opentrackerと比べてどう?パフォーマンスとか詳細をぜひ教えてほしいな。

dahrkael 2025/06/20 08:40:35

小さいトラッカーならopentrackerの方が多分速くてメモリも少し少ないかもね。
extrakerはCPUのコア数が2桁とかになった時に真価を発揮するはずだよ。
まだちゃんとしたベンチマークはできてないんだけどね。

quechimba 2025/06/20 03:03:06

いいね!いつかチェックしてみるよ。
俺も何年か前にElixirで簡単なトラッカー書いたことあるんだよね。コードはここにあるよ: https://github.com/aalin/mr_torrent

dahrkael 2025/06/20 08:44:36

面白いね!なんで特にprivate trackerにしようと思ったの?

arch-choot 2025/06/20 07:27:32

面白い!俺もBTをもっと知るためにTypescriptで似たようなことして、Rustを学ぶためにRustでやり直したよ(https://github.com/ckcr4lyf/kiryuu)。DBにはredisを使うことにしたんだ。君のは全部memory上のDBみたいだね?何か面白いdesignの決定とか、それで直面したproblemsとかあった?(俺のredis solutionは、その後のannounceでpeersをrandomiseしないみたいで、あんまり良くないんだ)

dahrkael 2025/06/20 08:17:48

俺の場合は、in-memoryなETSを使うのが最高のdecisionだったよ。各processでconcurrentにpeerのデータをread&writeできるから、contentionとlatencyがminimalで済むんだ。唯一sequentialなpartは新しいswarmがinitially createdされる時だけだけど、それはあんまりhappeningしないからfine。
there’s sadly no native support for taking random rows directly from the tables, so for now i grab the whole swarm and then take a random subset(https://github.com/Dahrkael/ExTracker/blob/master/lib/ex_tra…)

toast0 2025/06/20 18:36:10

ETS tableがいくつのslotsを持ってるか見るwayがあったかrememberしてないけど、imperfectなdistributionでもokなら、maybe randomにslotを選んで、ets:slot\2を使ってそのslotの全てのitemsを取得し、then selectするのはどうかな。maybe you can get the slot count from eta:table_info(Table, stats), although that’s not intended for production use, so the format may change without notice.

yesco 2025/06/20 13:17:10

・https://en.m.wikipedia.org/wiki/Mainline_DHT
・https://en.m.wikipedia.org/wiki/Peer_exchange

atmosx 2025/06/20 14:47:35

DHT(Distributed Hash Table)とPEX(Peer Exchange)は、torrent clientsがcentralised trackersなしでpeersを見つけられるようにするものだよ。だから、もうcentralなplace \ public trackerは必要ないんだ。

Thaxll 2025/06/20 14:52:02

You still need a central server though…

perching_aix 2025/06/20 15:54:56

そうだよ、individualなtorrentsをtrackするだけじゃなくなるんだ。初期のpeer discovery stage(bootstrapping)の間だけroleを果たすんだよ。peersは自分でtorrent swarmsを見つけるから、bootstrap serversはそこからexcludedされるんだ。

LtdJorge 2025/06/20 15:56:44

If you are connected to the DHT network, you don’t. Unless you mean for DNS and such.

perching_aix 2025/06/20 15:58:37

いや、ああいうネットワークに繋がるには、まず特定の集権的なノードに接続する必要があるってことだよ。

LtdJorge 2025/06/20 16:12:39

ブートストラップノードのことだね。でもあれらは、歴史的にある程度そうだったとしても、絶対に集権化されてる必要はないんだ。何百万ってあってもいいんだし。

もっとコメントを表示(1)
perching_aix 2025/06/21 03:49:42

それでも、その一部のリストは必要でしょ?そして「同じネットワーク」に繋いでくれるって、そもそもその意味が通じるかどうか分からないけど、信頼するしかないんじゃない?

immibis 2025/06/20 16:18:52

もしブートストラップノードが何百万もあったら、どうやって見つけるの?

toast0 2025/06/20 17:52:14

もしよく知られたポートで待機してて、何百万ってあるなら、「ランダムな」IPv4アドレスに数千個プローブを送れば、たぶん一つは見つかるよ。
見つけたらブートストラップノードのリストを手に入れて保持すれば、全てのルーティング可能なIPv4アドレスから選ぶ代わりに、ブートストラップアドレスの中からランダムに選べるようになるね。

immibis 2025/06/20 20:28:22

IPv6についてはどう考えてる?

toast0 2025/06/20 20:59:45

IPv6のプロービングは結構難しいよ。/48のうち/64だけ使うとか::0や::1を仮定しても、現実的じゃないほどプローブが必要になるだろうね。NAT64経由でv4空間をプローブしてv6アドレスを交換するか、有効なv6アドレスリストをクライアントに入れる方法もあるけど、それはまた集権的になっちゃう。どうやって配布するの?たぶんスーパーノードを動かしてリストをクライアントソースにダンプする感じかな。最初はリストにそのノードだけとか。

LtdJorge 2025/06/20 20:30:56

ブートストラップノードは、トラッカーみたいにtorrentに埋め込めるよ。トラッカーは全部の状態を持つけど、ブートストラップノードはDHTネットワークのノードに繋ぐだけ。その後は完全に分散化されるんだ。
SRV DNSレコードに埋め込むとか、DNSサーバー取得と同じ問題。ISPからDHCP経由でノードアドレスをもらえるかもね(笑)。

dahrkael 2025/06/20 08:51:39

うん、Elixirは選択肢の一つだよ。C++より絶対楽しめる自信あるな。

vivzkestrel 2025/06/20 03:50:44


- どうやって始めたの?
- 他のプロジェクト参考にした?
- どれくらい時間かかった?
- qbittorrentとかと比べて、どれくらい機能すると思う?

dahrkael 2025/06/20 09:05:12

別のプロジェクトでトラッカーが必要だったのがきっかけだけど、作るのが楽しくなっちゃってさ。
他のトラッカーのコードもちらっと見たけど、複雑すぎたりシンプルすぎてあんま役に立たなかったんだよね。
今のところ3ヶ月、寝る時間を削って頑張ってるよ。
qbittorrentみたいなクライアントじゃないけど、将来seedbox向けのクライアントも作りたいなって考えてる。

lionkor 2025/06/20 05:44:12

これはトラッカーであって、トレントクライアントじゃないよ。

NooneAtAll3 2025/06/20 06:56:07

トラッカーってどういう意味?

devoutsalsa 2025/06/20 07:01:30

トレントトラッカーってのは、ファイル持ってる人は知ってるけど自分では何も保存しない、世界一付き合い悪いマッチングサービスみたいなもんかな。パーティの場所は知ってるけど絶対自分ではやらない友達みたいな。
あなたのBitTorrent clientが「Linux ISO持ってる人いるー?」って聞くと、トラッカーはスタートアップが資金調達失敗して方向転換するより早くIPアドレスのリストをくれる。
その後、clientはその人たち(seedersとかleechers)に繋がってデータ交換始めるんだけど、トラッカーは何食わぬ顔。ファイル共有版Tinderみたいな感じだけど、みんな匿名で、たぶん深夜3時に怪しいものダウンロードしてる。

vjerancrnjak 2025/06/20 07:36:46

全然匿名じゃないよ。トラッカーとのやり取りはHTTPSでもできるけど、peer同士の通信は全部暗号化されてないから。

immibis 2025/06/20 10:24:32

オプションの暗号化拡張もあるよ。BitTorrent社(BEP発行してるところ)が暗号化に思想的に反対してるからBEPはないけどね。

KomoD 2025/06/20 04:44:14

試してみたけど、HTTPSが動かなかったな。
あと、コンソールにこれが出まくる:
04:43:20.160 [warning] invalid ’event’ parameter: size: 6 value: ”paused”
でも動いてるみたい。HTTPでの統計も見れたらよかったけど、UDPでもまあいいかな(無効にしてるけど)。

bill876 2025/06/20 08:35:42

その”paused”イベントってのはBEP 21の一部だよ。
クライアントが、まだ全部終わってないけどこれ以上ダウンロードしないよ、ってトラッカーに知らせるやつ。例えば、torrentの一部のファイルだけ欲しい時とかね。
プロジェクトのREADME見たら、BEP 21はまだ実装されてないみたいだね。

KomoD 2025/06/20 12:45:16

README見たらBEP 21はまだ実装されてないって書いてあるね。あー、見落としてたわ。

dahrkael 2025/06/20 08:56:22

HTTPのTelemetryはToDoリストだよ。webserverに3rd party library使ってるから、ちゃんとやる方法を考えなきゃね。
HTTPSは証明書が必要だけど、CaddyかNginxを前に置くのがおすすめかな。certbot連携も考えてるけど、みんなUDP使うから優先度は高くないんだ。

andyleclair 2025/06/21 03:03:13

これマジでいいよ!コードざっと見たけど、すごく感動した。Elixir経験あるうちのsenior engineersが出すコードみたいだね。すごい仕事だよ!

IlikeKitties 2025/06/20 00:10:35

へぇ、いいね!Beam VMってBitTorrent trackerにぴったりっぽいね。

dahrkael 2025/06/20 08:50:27

これ、ETSがマジでキラーフィーチャーだった気がするな。protected tablesから並行で読み書きできるから、全体がめっちゃ並列になってる!

bavell 2025/06/20 01:36:57

めっちゃクール!これってprivate trackerとして使うのに向いてるの?

dahrkael 2025/06/20 08:48:22

そのままじゃ無理だけど、やればできるよ。必要な部品は全部揃ってるからね(hash whitelist support、udp path parsing、peer rejectionとか)。

toomuchtodo 2025/06/20 02:07:20

すごい仕事だね!

mikehostetler 2025/06/20 02:28:10

マジでクールなプロジェクト!よくやったね。

desireco42 2025/06/20 00:49:57

これは本格的だね、プロジェクトおめでとう!Elixirに完璧にフィットするのがわかるよ…。

guywithahat 2025/06/20 03:02:51

C++開発者ってGoとかElixir好きだよね〜(俺もだけど)。パフォーマンス重視な人がマルチスレッド性能に惹かれるのかな。クールなプロジェクトじゃん!

uncircle 2025/06/20 06:25:47

C++はわかんないけど、Erlang/Elixirはパターンマッチングでプロトコル解析マジ強い!コードもキレイになるし、let it crashで変なケース無視できるんだ(クラッシュしても一部だけ)。10年使っててダウンタイムゼロだよ!これで「Elixirでクラッシュしないサービスどう?」って顧客に勧めてるw 構造体とかでパターンマッチできるシステム言語欲しいな〜。

dahrkael 2025/06/20 08:22:51

毎日メモリ破壊とかデッドロックとかと戦ってる身からすると、Elixirは「え、なんでこんなに簡単なの?勝手に動くじゃん?」って感じ。ネットワークプログラマだから、バイナリパターンマッチングもマジ最高!

sea-gold 2025/06/20 20:04:26

Inko[1]見てみたら?パターンマッチング良い感じだよ(関数とかではできないかもだけど)。
[1] https://docs.inko-lang.org/manual/latest/getting-started/pat

もっとコメントを表示(2)
Thaxll 2025/06/20 12:11:25

「let it crashでコーナーケース無視できる」ってのは危ない考え方だよ。あとElixirって強く型付けされてないじゃん。

ricketycricket 2025/06/20 13:06:01

いや、違うよ。プロセスは監視できるし、クラッシュしても良い状態で再起動するだけなんだ。エラー全部無視するんじゃなくて、見落としてもシステムは落ちないって確信できるの。Elixirはほとんど強く型付けされてるって言われるよ。静的な型付けって言いたいのかな?

immibis 2025/06/20 16:21:24

まあ、前よりは確信できるかもね。でもさ、昔Ericssonの交換機がいつものメッセージで落ちてネットワーク全体がダメになったことあったじゃん?Erlangでもああいう可能性はあると思うよ。

eatbitseveryday 2025/06/20 13:08:24

トラッカーは古いものじゃないよ。プライベートトラッカーサイトで今も使われてるんだ。パブリックなTorrentはDHTとかPEXで探すことが多いけどね。

dewey 2025/06/20 19:19:24

でもさ、プライベートトラッカーも最近はそんなに流行ってないよね。俺は結構使うけど、ニッチなのはわかってるよ。

arthurcolle 2025/06/20 03:15:25

これ見てみて→ https://github.com/sergiotapia/magnetissimo 7年くらい前に人気だったやつだよ。

nayuki 2025/06/20 05:02:59

これに似てるよ:
https://news.ycombinator.com/item?id=44265851 ”Show HN: I wrote a BitTorrent Client from scratch” [2025-06-13]、
https://github.com/piyushgupta53/go-torrent-client

記事一覧へ

海外テックの反応まとめ
著者
海外テックの反応まとめ
暇つぶしがてらに読むだけで海外のテックニュースに詳しくなれるまとめサイトです。