기능
realtime의 어려운 부분은 이미 돌아가고 있습니다
실시간 기능이란 약간의 제품 코드 아래 깔린 아주 많은 전달 장치입니다. 누가 subscribe했는지, 누구에게 권한이 있는지, 누가 아직 남아 있는지. PushCaster가 바로 그 두 번째 부분입니다.
Channel
네 가지, 그리고 접두어가 곧 계약입니다
채널의 이름이 그 동작을 정합니다. 접두어는 라이브러리에게 서버에 인가를 물어야 하는지, 멤버 목록을 기대해야 하는지, 암호화해야 하는지를 알려 줍니다.
| 접두어 | 누가 subscribe할 수 있는가 | 무엇에 쓰는가 | 인가 |
|---|---|---|---|
| public | app key를 가진 누구나. | 빌드 상태, 실시간 스코어, 공개 피드. | 없음 |
| private- | 서버가 구독자마다 판단합니다. | 계정이나 자원으로 범위가 한정된 모든 것. | 서명 |
| presence- | 인가가 필요하고, 멤버 목록도 함께 옵니다. | 멤버십 자체가 기능이 되는 방과 세션. | 서명 |
| private-encrypted- | 인가가 필요하며, 페이로드는 여러분의 클라이언트가 암호화합니다. | 저희에게도 읽히지 않아야 할 페이로드. | 서명 |
cache- 채널은 실시간 이벤트를 전달하지만 저장된 상태를 다시 재생하지는 않습니다 — 참고: 알려진 차이.
인가
권한은 서버에 남습니다
private과 presence 구독을 허가하는 것은 저희가 아닙니다. 여러분의 애플리케이션이 허가하고, 그 답에 여러분의 app secret으로 서명합니다. 저희는 서명을 검증할 뿐 그 이상은 하지 않습니다.
- 엔드포인트 하나POST /pusher/auth는 요청과 응답의 모양을 그대로 유지합니다.
- 규칙은 여러분의 것이 소켓이 이 채널에 들어와도 되는지는 여러분만이 답할 수 있는 물음입니다.
- presence에서의 신원같은 호출이 멤버 id와 다른 멤버들에게 보여야 할 것들을 함께 돌려줍니다.
import Pusher from 'pusher'const pusher = new Pusher({ appId: process.env.PUSHCASTER_APP_ID, key: process.env.PUSHCASTER_KEY, secret: process.env.PUSHCASTER_SECRET, host: 'api-eu1.pushcaster.io', useTLS: true,})// Called by the client library whenever it subscribes to a// private-, presence- or private-encrypted- channel.app.post('/pusher/auth', (req, res) => { const { socket_id, channel_name } = req.body const user = req.session.user if (!user || !mayJoin(user, channel_name)) { return res.sendStatus(403) } res.send( pusher.authorizeChannel(socket_id, channel_name, { user_id: String(user.id), user_info: { name: user.name }, }), )})Webhook
소켓 계층이 보는 것을 백엔드가 듣습니다
접속 인원과 멤버십은 연결에서만 보입니다. 웹훅이 그것을 서명해 되돌려 주므로, 첫 관람자가 오면 일을 시작하고 마지막 사람이 나가면 멈출 수 있습니다.
| Event | 언제 발생하는가 |
|---|---|
| channel_occupied | 빈 채널에 첫 구독자가 들어왔을 때. |
| channel_vacated | 마지막 구독자가 나갔을 때. |
| member_added | 누군가 presence 채널에 들어왔을 때. |
| member_removed | 누군가 presence 채널에서 나갔을 때. |
| client_event | 클라이언트가 채널에 직접 이벤트를 보냈을 때. |
| cache_miss | cache 채널이 가지고 있지 않은 상태를 요청받았을 때. |
app.post('/pushcaster/webhooks', (req, res) => { const hook = pusher.webhook({ headers: req.headers, rawBody: req.rawBody }) // The signature is computed with your app secret, so an // unsigned or mismatched delivery never reaches your logic. if (!hook.isValid()) return res.sendStatus(401) for (const event of hook.getEvents()) { if (event.name === 'channel_occupied') startFeed(event.channel) if (event.name === 'channel_vacated') stopFeed(event.channel) } res.sendStatus(200)})라이브러리
PushCaster SDK는 없습니다. 일부러 그렇습니다
PushCaster는 회선에서 Pusher Channels 프로토콜을 말하므로, 공식 라이브러리가 손대지 않고 그대로 동작합니다. 추가할 저희 패키지도 없고, 저희가 배포할 때 깨질 저희 것도 없습니다.
- pusher-js
- Laravel Echo
- pusher/pusher-php-server
- pusher-http-node
- Python
- Go
- Ruby
- Java
- Android
- iOS
- Flutter
- Unity
설치 명령 전체: npm i pusher-js.
인프라
두 계층, 그리고 여러분이 고르는 클러스터
전달은 과금·설정과 분리된 계층에서 돌아가므로, control plane 장애는 전달을 끊지 않으면서 대시보드만 떨어뜨립니다.
지금 동작 중
- eu1서유럽
- eu2중부 유럽
클러스터는 메시지 전달에는 고가용이지만 presence에는 그렇지 않습니다. presence 저장소가 사라지면 presence와 접속 인원은 나빠지고, 그동안에도 public과 private 채널은 계속 전달합니다. 나중에 알게 되는 것보다 여기서 읽어 두는 편이 낫습니다.
publish가 지나는 길 보기