การนำ BitTorrent tracker แบบใหม่ที่เขียนด้วย Elixir มาใช้งาน
(github.com/Dahrkael)- ExTracker คือ BitTorrent tracker ที่สร้างด้วย Elixir โดยระบุว่ายังอยู่ระหว่างพัฒนา แต่ใช้งานได้แล้ว และยังไม่พร้อมสำหรับการใช้งานระดับอุตสาหกรรมเต็มรูปแบบ
- เป้าหมายด้านประสิทธิภาพคือ ประสิทธิภาพสูง โดยใช้ทุกคอร์ที่มี ทำงานบนพื้นที่จัดเก็บแบบ in-memory ใช้ RAM ประมาณ 200MB ต่อ peer 1 ล้านราย และมีโครงสร้างที่รันได้โดยไม่ต้องตั้งค่าเพิ่มเติม
- BEP ที่เกี่ยวข้องกับ BitTorrent ที่นำมาใช้แล้ว ได้แก่ BEP 0, BEP 15, BEP 23, BEP 7, BEP 21, BEP 24, BEP 41, BEP 48, BEP 52 ส่วนบางรายการอย่าง Private Torrents ยังไม่ได้ทำหรือทำไว้บางส่วน
- รองรับ HTTPS, การสำรองฐานข้อมูลลงดิสก์, การรันด้วย Docker ไม่รองรับ WebTorrent และฟีเจอร์ whitelist/blacklist, การจัดการ peer, metrics, GeoIP อยู่ในสถานะ ทำไว้บางส่วน
- วิธีรันมี 3 แบบ ได้แก่ รันจากซอร์สโดยตรง, บิลด์ release เอง, และรัน Docker image โดยในคอนเทนเนอร์สามารถตั้งค่าผ่าน environment variables แทน
runtime.exsได้
สถานะและเป้าหมายของ ExTracker
- ExTracker เป็น implementation ของ BitTorrent tracker ที่แนะนำตัวว่า “The Bittorrent Tracker made in Elixir”
- โปรเจกต์อยู่ในสถานะ Work In Progress
- ระบุว่ายังไม่พร้อมสำหรับการใช้งานระดับอุตสาหกรรมเต็มรูปแบบ
- ปัจจุบันสามารถทำงานได้แล้ว
- มี test instance รันอยู่ที่
extracker.dahrkael.net:6969และเปิดใช้งานฟังก์ชันปัจจุบันอยู่
ฟีเจอร์หลัก
- นำเสนอประสิทธิภาพและความสะดวกในการปฏิบัติการเป็นฟีเจอร์หลัก
- ประสิทธิภาพสูง: ใช้ทุกคอร์ที่มี
- ใช้ พื้นที่จัดเก็บแบบ in-memory
- การใช้หน่วยความจำอยู่ที่ RAM ประมาณ 200MB ต่อ peer 1 ล้านราย
- Zero setup: ตั้งเป้าให้รันแล้วทำงานได้ทันที
สถานะการรองรับ BitTorrent BEP
- สถานะการ implement แบ่งเป็น
✅ Done,🔰 Partially,🔲 Not Yet,❌ Won't do -
BEP ที่ทำเสร็จแล้ว
- BEP 0: The BitTorrent Protocol Specification
- BEP 15: UDP Tracker Protocol
- BEP 23: Tracker Returns Compact Peer Lists
- BEP 7: IPv6 Tracker Extension
- BEP 21: Extension for partial seeds
- BEP 24: Tracker Returns External IP
- BEP 41: UDP Tracker Protocol Extensions
- BEP 48: Tracker Protocol Extension: Scrape
- BEP 52: The BitTorrent Protocol Specification v2
-
BEP ที่ยังไม่ได้ทำหรือถูกยกเว้น
- BEP 27: Private Torrents ยังไม่ได้ implement
- BEP 31: Tracker Failure Retry Extension ยังไม่ได้ implement
- BEP 8: Tracker Peer Obfuscation เป็นรายการที่จะไม่ทำ
ฟีเจอร์อื่นและข้อจำกัด
- ฟีเจอร์ที่ทำเสร็จแล้ว
-
รองรับ HTTPS
- การสำรองฐานข้อมูลลงดิสก์
- ฟีเจอร์ที่ไม่รองรับ
- WebTorrent
- ฟีเจอร์ที่ทำไว้บางส่วน
-
Infohash whitelist/blacklist
- การจัดการ peer: interval enforcement, cleanup, banning ฯลฯ
-
Metrics
- รองรับ GeoIP: ใช้สำหรับสถิติและการจำกัด peer
- สามารถส่งข้อเสนอฟีเจอร์ได้ที่ Issues
-
วิธีรัน
-
รันจากซอร์สโค้ดโดยตรง
- วิธีนี้ต้องติดตั้ง Erlang และ Elixir ไว้ในระบบ
- clone repository
git clone https://github.com/Dahrkael/ExTracker.git && cd ExTracker- หากจำเป็น ให้แก้ไข config/runtime.exs
- คำสั่งรันคือ
MIX_ENV=prod iex -S mix
-
บิลด์ release
- ปัจจุบันยังไม่มี official release build และสามารถสร้าง release เองเพื่อ deploy ได้
- หลังจาก clone repository แล้ว ให้บิลด์ให้ตรงกับระบบปฏิบัติการ
- Linux:
MIX_ENV=prod mix release extracker - Windows:
MIX_ENV=prod mix release extrackerw - ไฟล์ release จะถูกสร้างในโฟลเดอร์
_build/prod/rel/extracker - หากย้ายไปเครื่องอื่น OS และ architecture ต้องเหมือนกัน
- หากจำเป็น ให้แก้ไขการตั้งค่า
releases/{VERSION}/runtime.exs - คำสั่งรันคือ
bin/extracker start
-
รันด้วย Docker
- สามารถรัน Docker image ที่ให้มาได้ทันที
docker run ghcr.io/dahrkael/extracker:latest- ใช้งานผ่าน docker-compose ได้เช่นกัน และมี ไฟล์ compose ตัวอย่าง ให้
- เนื่องจากปรับการตั้งค่าด้วยการแก้
runtime.exsภายในคอนเทนเนอร์ได้ยาก จึงสามารถตั้งค่าผ่าน environment variables ได้ด้วย - รายการ environment variables ทั้งหมดดูได้จากไฟล์ compose ตัวอย่าง
ไลเซนส์
- ExTracker เผยแพร่ภายใต้เงื่อนไข Apache License 2.0
- ดูรายละเอียดเพิ่มเติมได้ใน LICENSE file ของ repository
1 ความคิดเห็น
ความคิดเห็นบน Hacker News
ผมคาดหวังว่าจะเป็น การออกแบบที่ให้ OTP มาก่อน แต่เสียดายที่โค้ดดูใกล้เคียงกับแนว procedural เพราะแทบทุกงานไปแตะ ETS หรือ Application ที่อิง ETS โดยตรง
ถ้าอยากเรียนรู้วิธีออกแบบบริการด้วย OTP ใน Elixir หรือภาษาอื่นบน BEAM แนะนำให้อ่าน "Designing Elixir Systems with OTP" ของ James Edward Gray และ Bruce Tate กับ "Functional Web Development with Elixir, OTP, and Phoenix" ของ Lance Halvorsen
สุดท้ายแล้ว torrent tracker ก็ใกล้เคียงกับฐานข้อมูลเฉพาะทาง และเป้าหมายสำคัญที่สุดคือประมวลผลข้อมูลให้เร็วที่สุด
ถึงอย่างนั้น ผมจะลองอ่านหนังสือพวกนั้นดู
ตอนนี้มันใกล้เคียงกับซอฟต์แวร์ที่มีลักษณะเหมือนแอปพลิเคชันด้านการสื่อสาร มากกว่าตัวการสื่อสารเอง และถ้าครึ่งหนึ่งของความยอดเยี่ยมของ Erlang คือ concurrency กับ distributed nature อีกครึ่งหนึ่งคือความสามารถในการจัดการ error เฟรมเวิร์ก OTP ก็อาจนับเป็น “ครึ่งที่สาม” ได้
https://learnyousomeerlang.com/what-is-otp
ถ้าเป็นคอนฟิกแบบเซิร์ฟเวอร์เดียว ETS คือทางเลือกที่ถูก 100% และแม้จะขยายแนวนอนไม่ได้ แต่จะขยายแนวตั้งได้ดีมาก
ยังไงส่วนใหญ่ก็น่าจะเป็น YAGNI อยู่แล้ว
อาจมีบางกรณีที่ GenServer เพิ่มเติมหรือ
gen_statemเข้ากันได้สวย แต่การใช้งาน Elixir และ Phoenix จำนวนมากไม่จำเป็นต้องเลือกสถาปัตยกรรมหวือหวาขนาดนั้นเพราะ runtime ทำงานหวือหวาให้แทนมากพออยู่แล้ว
ETS อยู่ใน OTP อยู่แล้ว ผมเลยไม่เข้าใจว่าการใช้ ETS ทำไมถึงไม่ใช่ OTP-first
และก็ไม่ค่อยเข้าใจด้วยว่าการใช้ ETS มีปัญหาอะไร มันก็แค่ in-memory store เท่านั้น
ผมไล่ดูโค้ดแล้ว แต่ไม่ได้รู้สึกว่าใกล้เคียงกับสไตล์ procedural
ทำได้ดีมาก น่าจะย้ายจาก
IO.putsไปใช้ Logger และลองพิจารณาเพิ่ม OTel ด้วย[0] https://hexdocs.pm/logger/1.18.4/Logger.html
[1] https://hexdocs.pm/telemetry/readme.html
ผมชอบ Elixir มาก ตอนนี้กำลังทำ notification engine เจ๋ง ๆ ด้วย Elixir อยู่ และมันยอดเยี่ยมจริง ๆ
Elixir ต้องการ notification engine ที่ดีกว่านี้จริง ๆ
ยินดีด้วยกับการเปิดตัว อยากทราบรายละเอียดว่ามันทำงานอย่างไรเมื่อเทียบกับ opentracker
สนใจเรื่อง performance มาก
จุดที่ ExTracker ฉายแววคือเมื่อจำนวน core เริ่มขึ้นไปเป็นเลขสองหลัก
แต่ยังต้องทำ benchmark ที่เหมาะสมก่อน
ดูดี เดี๋ยวไว้จะลองดู
เมื่อหลายปีก่อนผมเคยทำ tracker พื้นฐานด้วย Elixir โค้ดอยู่ที่นี่: https://github.com/aalin/mr_torrent
น่าสนใจ ผมเคยทำของคล้ายกันด้วย TypeScript เพื่อเรียนรู้ BitTorrent เพิ่มขึ้น และทำใหม่ด้วย Rust เพื่อเรียน Rust: https://github.com/ckcr4lyf/kiryuu
แต่ผมใช้ Redis เป็นฐานข้อมูลเฉย ๆ โปรเจกต์นี้ดูเหมือนว่าฐานข้อมูลทั้งหมดอยู่ในหน่วยความจำ อยากรู้ว่าระหว่างทำแบบนั้นมี decision ด้าน design ที่น่าสนใจหรือปัญหาอะไรไหม
วิธีแก้ของผมด้วย Redis ดูไม่ค่อยดีนัก เพราะเหมือนจะไม่ randomize peers ใน announce ถัด ๆ ไป
สามารถอ่านและเขียนข้อมูลของ peer แต่ละตัวพร้อมกันจาก process ของตัวเองได้ ทำให้ contention และ latency ต่ำที่สุด
ส่วนเดียวที่ประมวลผลแบบ sequential คือเมื่อต้องสร้าง swarm ใหม่ครั้งแรก ซึ่งไม่ได้เกิดบ่อยจึงไม่เป็นไร
น่าเสียดายที่ไม่มี native support สำหรับดึงแถวแบบสุ่มจาก table โดยตรง ตอนนี้เลยดึงทั้ง swarm มาแล้วเลือก subset แบบสุ่ม: https://github.com/Dahrkael/ExTracker/blob/master/lib/ex_tra...
ถ้าอธิบายได้ว่า DHT กับ PEX คืออะไรจะดีมาก การค้นคำว่า "tracker PEX" ค่อนข้างยาก
ดังนั้นจึงไม่จำเป็นต้องมีตำแหน่งศูนย์กลางหรือ public tracker อีกต่อไป
เจ๋งดี อยากรู้ว่าอยากใช้ Elixir เป็นงานหลักไหม
รู้ Rust กับ Go ด้วย กำลังรับคนอยู่หรือเปล่า?
อยากรู้ว่าเริ่มต้นอย่างไร อ้างอิงโปรเจกต์อื่นไหม ใช้เวลานานแค่ไหน และคิดว่าฟีเจอร์ที่ทำงานได้เทียบกับพวก qBittorrent ประมาณไหน
ผมก็ไล่ดูโค้ด tracker ตัวอื่น ๆ แต่ส่วนใหญ่ซับซ้อนเกินไปหรือเรียบง่ายเกินไป เลยไม่ได้ช่วยมากนัก
จนถึงตอนนี้เป็นผลลัพธ์จาก การผัดวันนอนแบบล้างแค้น ตลอด 3 เดือน
นี่ไม่ใช่ client แบบ qBittorrent แต่มีไอเดียโปรเจกต์ client ที่เน้น seedbox ในอนาคตอยู่
ลองใช้แล้ว แต่ทำให้ HTTPS ทำงานไม่ได้
ใน console มีข้อความ
04:43:20.160 [warning] invalid 'event' parameter: size: 6 value: "paused"ขึ้นเรื่อย ๆ แต่ดูเหมือนว่ายังทำงานได้อยากดู HTTP stats ด้วย แต่ UDP ก็โอเค เพียงแต่ผมปิด UDP ไว้
"paused"เป็นส่วนหนึ่งของ BEP 21client ส่งให้ tracker เพื่อแจ้งว่ายังไม่อยู่ในสถานะ completed แต่จะไม่ดาวน์โหลดต่อแล้ว
เช่น เมื่อผู้ใช้ต้องการแค่บางไฟล์ใน torrent
ดูจาก README ของโปรเจกต์แล้ว การรองรับ BEP 21 ยังไม่ได้ implement
เนื่องจากใช้ไลบรารี third-party สำหรับ web server จึงยังต้องหาวิธีที่ถูกต้องก่อน
ถ้าจะใช้ HTTPS ต้องระบุ path ของ certificate ที่ถูกต้องให้
:https_keyfileแต่ตอนนี้ถ้าต้องการ HTTPS แนะนำให้วาง Caddy หรือ Nginx ไว้หน้า trackerมีแผน integrate certbot ด้วย แต่เพราะ peer ของ torrent ส่วนใหญ่ใช้ UDP จึงยังไม่ใช่ priority สูง