2.6 KiB
Ping-Pong 1v1 Node.js Match Server
Ten serwer obsługuje mecze 1v1 przez WebSocket, trzyma stan w Redis (reconnect), zapisuje postęp do MySQL i po zakończeniu meczu wywołuje PHP endpoint do przydziału nagród.
Uruchomienie lokalnie
- Wejdź do folderu:
public_html/disciplines/ping-pong/1v1/node-server
- Zainstaluj zależności:
npm install
- Skopiuj konfigurację:
- skopiuj
.env.example→.envi uzupełnij wartości
- skopiuj
- Start:
npm run start
Uruchomienie produkcyjne
Ten serwer musi działać jako osobny proces Node.js na hoście aplikacji. Samo PHP nie wystarczy.
Minimalne wymagania:
- Node.js 20+
- MySQL dostępny pod danymi z
.env - reverse proxy z
https://togethere.cloud/ping-pong-1v1dows://127.0.0.1:8088/
Redis jest zalecany, ale nie jest już obowiązkowy dla pojedynczej instancji. Jeśli REDIS_URL jest niedostępny, serwer przełączy się na fallback in-memory dla kolejki i snapshotów reconnect.
Przykład startu przez PM2:
cd public_html/disciplines/ping-pong/1v1/node-servernpm installpm2 start ecosystem.config.cjspm2 save
Test po starcie procesu:
http://127.0.0.1:8088/health- przez domenę:
https://togethere.cloud/ping-pong-1v1/health
Jeżeli domena zwraca 503, to najczęściej oznacza to, że Apache/Nginx już próbuje proxy, ale proces Node.js nie działa albo nie nasłuchuje na porcie 8088.
Jeżeli /health zwraca ok: true i redisMode: memory, to serwer działa bez Redisa w trybie pojedynczej instancji.
Protokół WebSocket (JSON)
Klient wysyła:
{"type":"hello","ticket":"..."}{"type":"queue.join"}{"type":"queue.leave"}{"type":"match.input","seq":123,"move":-1|0|1}
Serwer wysyła:
{"type":"hello.ok","userId":1}{"type":"queue.status","status":"searching","queueSize":4}{"type":"queue.status","status":"idle"}{"type":"match.found","matchId":"...","side":"left|right"}{"type":"match.state", ... }{"type":"match.end", ... }
Skalowanie
- Redis trzyma kolejkę matchmakingu i snapshot stanu meczu.
- Przy wielu instancjach potrzebujesz sticky sessions (L4/L7) albo wspólnej warstwy routingowej na matchId.
Bezpieczeństwo
Ticket wydaje PHP endpoint /api/matches/ping-pong/1v1/ticket.php (wymaga sesji PHP). Node weryfikuje ticket HMAC (PINGPONG_1V1_SHARED_SECRET).
Po zakończeniu meczu Node robi POST do /api/matches/ping-pong/1v1/ (folder z index.php) i dostaje jobId. Klient może potem odpalić animacje i odpytywać /api/matches/ping-pong/1v1/status.php?jobId=....