solver-sdk
Version:
SDK для интеграции с Code Solver Backend API (совместимо с браузером и Node.js), с поддержкой функциональности мышления (Thinking Mode)
212 lines (162 loc) • 9.49 kB
Markdown
# WebSocket Ping/Pong механизм
Данный документ описывает механизм поддержания WebSocket соединений и мониторинга их состояния через ping/pong обмен.
## Обзор функциональности
SDK поддерживает автоматический механизм отправки ping-сообщений и обработки pong-ответов для:
1. **Проверки активности соединения** - обнаружение разрывов соединения даже в отсутствие активности
2. **Измерения времени отклика (Round Trip Time, RTT)** - мониторинг качества соединения
3. **Сбора статистики соединения** - для диагностики и отладки
4. **Автоматического обнаружения проблем** - уведомление о потере соединения
## Включение механизма ping/pong
```typescript
import { CodeSolverSDK, WebSocketNamespace } from 'solver-sdk';
// Создаем экземпляр SDK
const sdk = new CodeSolverSDK({
baseURL: 'https://api.example.com',
apiKey: 'your-api-key'
});
// Получаем WebSocket клиент
const wsClient = sdk.getWebSocketClient();
// Подключаемся к пространствам имен
await wsClient.connectToReasoning();
await wsClient.connectToDependencies();
await wsClient.connectToIndexing();
// Включаем автоматический механизм ping/pong
// параметры: интервал отправки в мс (по умолчанию 30000) и порог таймаута (по умолчанию 3)
wsClient.enablePingPong(10000, 3);
// Регистрируем обработчик для события таймаута соединения
wsClient.onPingPongEvent('connection_timeout', (data) => {
console.log(`Соединение потеряно для namespace ${data.namespace}`);
console.log(`Socket ID: ${data.socketId}`);
console.log(`Количество пропущенных pong: ${data.timeouts}`);
// Здесь можно добавить логику переподключения или уведомления пользователя
});
```
## Отключение механизма ping/pong
```typescript
// Отключение для всех пространств имен
wsClient.disablePingPong();
// Отключение для конкретного пространства имен
wsClient.disablePingPong(WebSocketNamespace.REASONING);
```
## Получение статистики ping/pong
```typescript
// Получение статистики для всех пространств имен
const allStats = wsClient.getPingStats();
console.log('Статистика для всех соединений:', allStats);
// Получение статистики для конкретного пространства имен
const reasoningStats = wsClient.getPingStats(WebSocketNamespace.REASONING);
console.log('Статистика для reasoning:', reasoningStats);
// Пример содержимого статистики:
// {
// namespace: '/reasoning',
// socketId: 'socket-id-123',
// pingSent: 10, // Количество отправленных ping
// pongReceived: 10, // Количество полученных pong
// averageRtt: 15.5, // Среднее время отклика (мс)
// minRtt: 5, // Минимальное время отклика (мс)
// maxRtt: 45, // Максимальное время отклика (мс)
// lastRtt: 12, // Последнее измеренное время отклика (мс)
// lastPongTimestamp: 1712345678901, // Timestamp последнего полученного pong
// isConnected: true // Текущий статус соединения
// }
```
## Ручная отправка ping/pong
Хотя SDK обеспечивает автоматический механизм ping/pong, вы также можете вручную отправлять ping-сообщения:
```typescript
// Отправка ping и получение pong
wsClient.send(WebSocketNamespace.REASONING, 'connection_ping', {
timestamp: Date.now()
});
// Добавление обработчика для pong-ответов
wsClient.on('connection_pong', (data) => {
const rtt = Date.now() - data.echo;
console.log(`Получен pong, RTT: ${rtt}ms`);
});
// Альтернативно, можно использовать готовый обработчик
wsClient.on('connection_pong', wsClient.getPongHandler());
```
## Обработка отключений и переподключение
```typescript
// Обработка события таймаута соединения
wsClient.onPingPongEvent('connection_timeout', async (data) => {
console.log(`Соединение потеряно для ${data.namespace}`);
// Попытка переподключения
try {
// Отключаемся от проблемного пространства имен
wsClient.disconnect(data.namespace);
// Пауза перед повторным подключением
await new Promise(resolve => setTimeout(resolve, 1000));
// Переподключаемся
switch (data.namespace) {
case WebSocketNamespace.REASONING:
await wsClient.connectToReasoning();
break;
case WebSocketNamespace.DEPENDENCIES:
await wsClient.connectToDependencies();
break;
case WebSocketNamespace.INDEXING:
await wsClient.connectToIndexing();
break;
}
console.log(`Успешно переподключились к ${data.namespace}`);
} catch (error) {
console.error(`Ошибка при переподключении к ${data.namespace}:`, error);
}
});
```
## Рекомендации по использованию
1. **Интервал ping/pong**: Рекомендуемый интервал - 30 секунд для продакшн и 5-10 секунд для отладки.
2. **Порог таймаута**: Значение 2-3 пропущенных ping/pong позволяет избежать ложных срабатываний при временных задержках сети.
3. **Экономия трафика**: При частой передаче данных через WebSocket можно увеличить интервал ping/pong, так как регулярный обмен данными уже поддерживает соединение активным.
4. **Мониторинг RTT**: Используйте statsPingStats для мониторинга задержек сети и раннего обнаружения проблем с соединением.
5. **Отключение перед закрытием приложения**: Вызывайте disablePingPong() и затем disconnectAll() при закрытии приложения для корректного освобождения ресурсов.
## Пример комплексного использования
```typescript
async function setupWebSocketWithHealthMonitoring() {
const sdk = new CodeSolverSDK({
baseURL: 'https://api.example.com',
apiKey: 'your-api-key',
websocket: {
reconnect: true,
reconnectAttempts: 5,
reconnectDelay: 2000
}
});
const wsClient = sdk.getWebSocketClient();
// Подключаемся ко всем пространствам имен
await wsClient.connectToReasoning();
await wsClient.connectToDependencies();
await wsClient.connectToIndexing();
// Включаем механизм ping/pong для всех соединений
wsClient.enablePingPong(20000, 3);
// Регистрируем обработчик для события таймаута
wsClient.onPingPongEvent('connection_timeout', handleConnectionTimeout);
// Периодически проверяем статистику соединений
const statsInterval = setInterval(() => {
const stats = wsClient.getPingStats();
// Анализируем статистику
for (const stat of stats) {
if (stat.averageRtt > 500) {
console.warn(`Высокая задержка для ${stat.namespace}: ${stat.averageRtt}ms`);
}
}
}, 60000); // Проверка каждую минуту
// Функция для обработки таймаута соединения
async function handleConnectionTimeout(data) {
console.error(`Соединение потеряно для ${data.namespace}`);
// Логика переподключения...
}
// Функция для корректного закрытия соединений
function cleanup() {
clearInterval(statsInterval);
wsClient.disablePingPong();
wsClient.disconnectAll();
}
// Возвращаем функцию очистки
return cleanup;
}
// Использование
const cleanup = await setupWebSocketWithHealthMonitoring();
// При закрытии приложения
window.addEventListener('beforeunload', cleanup);
```