Skip to content

Discord

Your Place to Talk and Hang Out

Categories ite

Discord Developer Portal

Discord_Developer_Portal_-Application-_Menu.jpg

General Information

당신의 창조물을 뭐라고 불러야 할까요? 그것은 어떤 놀라운 일을 합니까? Discord에서 어떤 아이콘을 나타내야 하나요? 여기에 알려주세요!

Installation

사용자가 앱을 설치하는 방법을 선택하세요. 설치 링크를 생성하고, 지원할 인증 방법을 선택하고, 요청하려는 범위와 권한을 정의하세요.

OAuth2

Discord를 인증 시스템으로 사용하거나 사용자를 대신하여 API를 사용하세요. 리디렉션 URI를 추가하고, 범위를 선택하고, 행운을 빌어 D20을 굴린 다음 시작하세요!

Bot

봇 사용자와 함께 Discord에서 앱에 생기를 불어넣으세요. 사용자 서버에서 채팅에 참여하고 직접 상호작용하세요.

Rich Presence Art Assets

Discord와 게임을 긴밀하게 통합하고 플레이어가 클라이언트에 직접 접속하여 게임을 공유할 수 있도록 하세요.

Application Testers

애플리케이션을 테스트하기 위해 최대 50명의 Discord 사용자를 초대할 수 있습니다. 이메일을 등록하고 긍정적인 태도를 갖고 있어야 합니다. ^)

Monetization

-

Activities

-

Installation

Authorization Methods
앱이 지원하는 인증 방법을 선택하세요. 앱은 사용자와 길드 모두에게 설치될 수 있습니다.
"사용자 설치(User Install)" 또는 "길드 설치(Guild Install)" 방법 중 선택할 수 있다.
Install Link
제공된 설치 링크를 사용하거나 사용자 정의 링크를 등록하세요. 사용자 정의 링크를 선택하면 앱을 추가하는 사용자는 Discord의 앱 추가 흐름 대신 귀하의 URL로 리디렉션됩니다.
"None", "Discord Provided Link", "Custom URL" 중 하나를 선택 가능
기본 설치 설정
앱에서 요청할 기본 범위 및 권한 집합을 선택하세요.

Bot

Build-A-Bot
봇 사용자를 추가하여 앱에 생기를 불어넣으세요. 이 작업은 되돌릴 수 없습니다(로봇은 파괴하기에는 너무 멋지기 때문입니다).
Token
보안상의 이유로 토큰은 생성 시 한 번만 볼 수 있습니다. 토큰에 대한 액세스를 잊었거나 분실한 경우 새 토큰을 다시 생성하세요.
  • 개발에 필요한 Access Token 은 여기에서 생성할 수 있다.
승인 흐름 (Authorization Flow)
이러한 설정은 봇에 대해 OAuth2 승인이 제한되는 방식(봇을 추가할 수 있는 사람 및 추가 방법)을 제어합니다.
공개 봇 (Public Bot)
공개 봇은 누구나 추가할 수 있습니다. 선택 취소하면 귀하만 이 봇을 서버에 가입시킬 수 있습니다. -> No/Yes
OAuth2 코드 부여 필요 (Requires OAuth2 Code Grant)
애플리케이션에 여러 범위가 필요한 경우 애플리케이션에 토큰이 부여되기 전에 봇이 조인하지 않도록 전체 OAuth2 흐름이 필요할 수 있습니다. -> No/Yes
권한 있는 게이트웨이 인텐트 (Privileged Gateway Intents)
일부 #Gateway Intents는 봇이 확인된 경우 승인이 필요합니다. 봇이 확인되지 않은 경우 아래에서 해당 인텐트를 전환하여 액세스할 수 있습니다.
존재 의도 (Presence Intent)
봇이 현재 상태 업데이트 이벤트를 수신하는 데 필요합니다. -> No/Yes
서버 구성원 의도 (Server Members Intent)
봇이 GUILD_MEMBERS 아래에 나열된 이벤트를 수신하는 데 필요합니다. -> No/Yes
메시지 내용 의도 (Message Content Intent)
봇이 대부분의 메시지에서 메시지 콘텐츠를 수신하는 데 필요합니다. -> No/Yes

INFORMATION

봇이 100개 이상의 서버에 도달하면 확인 및 승인이 필요합니다. 여기서 더 읽어보세요

Bot Permissions
비트 수학에 도움이 필요하신가요? 아래 도구를 사용하여 필요한 기능을 기반으로 봇에 대한 권한 정수를 계산하세요.
  • 필요한 권한을 목록에서 선택하면 해당 Permission 에 대한 Integer 를 Bitwise 계산하여 알려줌.

Gateway Intent

특히 규모에 따라 게이트웨이 연결을 통해 앱이 처리할 것으로 예상되는 데이터의 양과 관련하여 상태 저장 애플리케이션을 유지하는 것은 어려울 수 있습니다. 게이트웨이 의도 (Gateway intents) 는 계산 부담을 줄이는 데 도움이 되는 시스템입니다.

Performance Optimization

Discord가 Go에서 Rust로 전환하는 이유

가장 기본적인 최적화 만으로 Rust버전이 하이퍼 핸드튜닝된 Go버전보다 성능이 우월했음

  • 디스코드는 "Read States" 서비스 : 어떤 채널과 메시지를 읽었는지 계속 추적.
    • 하지만 Go의 메모리 모델과 GC는 레이턴시 스파이크를 만듬
  • Rust의 메모리 관리와 GC가 없는것이 이에 적합
  • 도입 초기에는 비동기모델을 지원안했지만, 최신 버전에는 포함.
  • 이제 게임SDK,비디오 캡처와 인코딩,백엔드 서비스등 다양한 곳에서 Rust를 사용

Discord가 네트웍 디스크의 지연시간을 최소화한 방법

  • Discord가 네트웍 디스크의 지연시간을 최소화한 방법 | GeekNews (Google Cloud Platform, Persistent Disk 레이턴시, etc ...)
  • 초당 200만개의 메시지를 처리하는 NoSQL DB 클러스터(ScyllaDB)를 운용 중
  • DB성능에 가장 큰 영향을 미치는 것은 피지컬 디스크 하드웨어의 레이턴시
    • 쿼리량이 낮은 수준에서는 상관없지만, 특정 시점을 초과하면 1~2ms가 걸리는 읽기 시간 만으로도 디스크에서 읽는 대기열이 발생하며 쿼리 자체에 대해 시간 초과가 발생
  • 디스크 레이턴시는 보통 마이크로세컨드 단위인데, 왜 디스크 오퍼레이션에 1~2ms가 걸릴까 ?
  • 디스코드는 대부분의 하드웨어를 Google Cloud에서 운용
    • NVMe 기반의 로컬 SSD를 지원하지만 자체적으로 테스트해보니 안정성 문제가 있어서 중요한 데이터 저장소로 사용하기엔 맘이 편하지 않았음
    • Persistent Disk는 서버에 실시간으로 연결/분리 가능하며, 다운타임 없이 리사이즈 가능, 언제나 스냅샷 생성가능하고, 기본으로 복제되게 설계됨
      • 문제는 서버에 직접 붙어있지 않고 네트웍으로 연결 된다는 것
  • 로컬 네트웍 커넥션 레이턴시가 아무리 낮아도, PCI/SATA 보다 낮지는 않음
    • 네트워크는 1~2ms, 직접연결된 디스크는 0.5ms
  • 로컬 SSD는 HDD처럼 하드웨어 문제가 생기면 그 디스크의 데이터를 잃어버리게 되며, 호스트 자체가 문제가 생기면 스냅샷도 불가능 해서 아예 데이터를 잃어 버리는 상황이 발생
    • 그래서 디스코드는 Local SSD 를 이용하지 않고, Persistent Disk 를 사용

문제 분석

  • 로컬 SSD와 Persistent Disk 의 장점만 모은 저장 장치가 있다면 최고겠지만 그런 것은 없음. 장점중 일부만 가져온다면?
  • 디스코드는 쓰기 지연시간은 문제가 아님. 성능에 영향을 미치는 것은 "읽기 지연시간"
  • "다운타임 없는 디스크 리사이징"은 필수 기능은 아님. 사이즈는 미리 예측 가능
  • 최종 요구 사항은
    • GCP 에 그대로 있으면서
    • 데이터 백업을 위해서 Point-in-Time 스냅샷 사용
    • 읽기 지연시간 최소화를 최우선 순위로
    • 기존 데이터베이스 업타임 보장을 희생하지 않을 것
  • 읽기는 GCP의 Local SSD를 활용하고, 쓰기는 Persistent Disk에 하면 좋을 것 같음
    • 소프트웨어 수준에서 이런 Super-disk를 만들 수 있을까?

Super-Disk 만들기

  • 요구사항은 기본적으로 Write-Through 캐쉬였음. GCP의 로컬 SSD를 캐쉬로 사용하고, PD를 저장 레이어로 사용
  • DB서버로 Ubunut를 사용하고 있어서, 리눅스 커널단에서 디스크 레벨의 캐쉬 적용 가능(dm-cache, lvm-cache, bcache 같은 모듈)
  • 하지만, 실험해보니 캐쉬디스크에 배드섹터 발생시 전체 읽기 작업이 실패함
    • 배드섹터가 발생하면 스토리지 레이어에서 읽어다 엎어써야 하는데, 평가한 디스크 캐슁 솔루션들은 이런 기능이 없었음
    • 배드섹터 발생시 데이터베이스가 데이터 안정성 문제로 셧다운 되어버림
  • 추가 요구사항으로 "로컬 SSD에 배드섹터가 발생해도 살아남아야 함"이 추가됨
  • 그래서 리눅스 커널의 "md"를 조사
    • md는 소프트웨어 RAID를 생성할수 있도록 지원
    • SSD와 PD를 미러링 하는 것으로는 문제가 해결 되지 않음. 절반이상의 읽기는 PD에서 될 것이기 때문에
    • md에는 전통적인 RAID에는 없는 "write-mostly" 가 있음
      • 특정 디스크를 write-mostly로 지정하면 일반 읽기에서는 제외되며, 다른 옵션이 없을 때만 읽기가 실행됨. "느리게 연결된 기기에 유용"
      • 즉, SSD와 PD를 RAID1으로 묶고, PD를 write-mostly로 세팅하면 요구사항을 맞출 수 있음
  • 마지막 남은 문제는 GCP의 Local SSD는 크기가 딱 375GB라는 것
  • 디스코드는 특정 어플리케이션에 대해서는 DB 인스턴스당 1TB 이상이 필요하기도 함
  • 그래서 여러개의 SSD를 RAID0로 묶기로
  • 최종 모습은
    • RAID0 로 묶인 로컬 SSD 4개를 md0
    • md0 와 Persistent Disk를 RAID1으로 묶은 md1 을 구성

DB 성능

  • 딱 예상한 결과가 나왔음
  • 피크시에도 디스크 오퍼레이션들이 큐에 쌓이지 않으며, 쿼리 레이턴시가 변하지 않음
  • 성능 향상이 일어나서 각 서버당 처리 쿼리량이 더 늘어남
  • RAID 사용해본 사람들은 이게 "그냥 동작할까?" 라는 의구심이 들겠지만, 실제로는 다양한 일이 있었고, 나머지는 따로 상세히 소개할 예정

Discord가 Cassandra에서 ScyllaDB + Rust로 전환한 이유

그러나 사용자 기반이 확장됨에 따라 Discord는 수조 개의 메시지를 효율적으로 처리해야 하는 어려운 과제에 직면했습니다. 기존 데이터베이스 시스템인 Cassandra는 핫 파티션으로 인해 속도 저하 및 성능 저하 문제가 발생했습니다.

  • Discord는 성장하면서 메시징 저장소 DB를 계속 교체하였음
  • 초기에는 단일 MongoDB. 2015년 11월에 메시지 수가 1억개로 늘어나면서 MongoDB 한계가 드러남
  • 2017년에 12노드 클러스터 Cassandra로 전환하여 수십억개의 메시지를 저장
  • 2022년에는 메시지가 수조개로 급증하면서 인프라가 177개 노드로 엄청 늘어났고, 대기시간 예측이 불가능하고 유지보수 비용이 엄청 비싸짐
  • 카산드라 에서 디스코드의 문제는 Hot Partition이었음. DB의 특정 부분이 과부하 되어 전체 어플리케이션의 성능이 저하
    • 카산드라 내부 데이터 구조가 LSM트리를 활용하므로 쓰기보다 읽기 비용이 더 많이 들고, 단일 서버에서 여러 사용자의 동시 읽기는 핫스팟을 만들고 성능 저하로 이어짐
    • SSTable 압축과 같은 유지 관리 작업이 전체 성능에 영향을 미쳐서 문제를 가중 시킴
  • 그래서 다양한 구성요소를 통합하여 아키텍처 재설계에 들어감
    • 모놀리식 API, Rust로 구현된 데이터 서비스, ScyllaDB에 기반한 스토리지 시스템(C++로 개발된 Cassandra 호환 DB)등을 활용
  • ScyllaDB를 채택하면서 상단한 개선이 이루어짐
    • p99 read latency 는 카산드라의 40~125ms 에 비해 15ms로 감소
    • p99 write latency 는 카산드라의 5~70ms 에 비해 5ms로 감소
  • 디스코드 엔지니어는 Rust로 데이터 서비스를 작성
    • Rust의 Feareless Concurrency 기능을 이용하여 핫 파티션에 대한 동시 트래픽을 제어
    • Rust의 라이브러리와 동시성 기능은 Discord 의 요구사항에 매우 적합했음
    • 데이터 서비스는 API 모노리스와 데이터베이스 클러스터사이의 중개 서비스 역할을 수행

Discord가 웹소켓 트래픽을 40% 감소시킨 방법

  • 클라이언트가 Discord에 연결하면 "게이트웨이"라고 하는 서비스를 통해 무슨 일이 일어나고 있는지에 대한 실시간 업데이트를 받음
  • 2017년 말부터 클라이언트의 게이트웨이 연결은 zlib를 사용하여 압축되어 메시지의 크기가 2배에서 10배까지 작아졌음
  • Zstandard(zstd)는 zlib보다 압축률이 높고 압축 시간이 짧으며, 사전 기능을 지원해 대역폭을 추가로 줄일 수 있음
  • 2019년 zstd 테스트 결과는 그다지 긍정적이지 않았으나, 다시 시도해볼 가치가 있다고 판단함

Zstd 스트리밍

  • Zlib은 스트리밍 압축을 사용한 반면, zstd는 그렇지 않았음
  • 작은 페이로드에서 zstd가 zlib보다 성능이 떨어졌음
  • Elixir용 zstd 바인딩인 ezstd를 포크하여 스트리밍을 추가함
  • Zstd 스트리밍으로 전환한 결과 zlib 스트리밍보다 압축률과 속도 면에서 크게 개선됨
  • 최적화 튜닝 - Chainlog, hashlog, windowlog 등 zstd 압축 매개변수를 조정하여 메모리 사용량과 압축 시간의 균형을 맞춤

See also

  • Wildbeast - 다목적 Discord bot 프레임워크
  • Overpass - 셀프호스트 스트리밍 플랫폼
  • Revolt - 오픈소스 디스코드 대체제
  • Slack
  • Devzat - 개발자들을 위한 SSH 채팅 서버

Favorite site