Los endpoints RPC públicos de BNB Smart Chain son convenientes pero pueden fallar o agotar el tiempo de espera bajo carga debido a saturación, tamaño de solicitud, métodos no soportados y límites de tasa. Las aplicaciones de producción necesitan tiempos de espera razonables, reintentos que eviten escrituras duplicadas, monitoreo de salud y una cadena de respaldo que vaya de lo público a lo comercial y a nodos dedicados. Este artículo explica los mecanismos y proporciona un ejemplo en Node.js.
Respuesta directa: Por qué fallan los endpoints RPC públicos de BSC y qué hacer
Los endpoints RPC públicos de BNB Smart Chain (BSC) son gratuitos y fáciles de usar, pero no están diseñados para cargas de trabajo de producción. Bajo carga pesada, frecuentemente devuelven errores HTTP 429 (Demasiadas solicitudes) o 5xx, y las solicitudes pueden agotar el tiempo de espera. Esto está documentado en el rastreador de problemas de GitHub de BNB Chain, donde los usuarios informan que las solicitudes a nodos RPC públicos fallan más del 80% de las veces durante períodos pico. Aunque esa cifra específica es un informe de la comunidad, no una medición oficial, resalta un problema real de fiabilidad.
Para construir una configuración de producción confiable, debes implementar tiempos de espera por llamada, reintentos que no dupliquen escrituras, monitoreo de salud y una cadena de respaldo que comience con endpoints públicos, pase a un proveedor comercial y finalmente use un nodo BSC dedicado. Este artículo explica las causas subyacentes y proporciona un ejemplo ejecutable en Node.js.
- Los endpoints públicos son compartidos y tienen límites de tasa; pueden saturarse por otros usuarios.
- Las solicitudes grandes (por ejemplo, eth_getLogs con rangos amplios) pueden causar tiempos de espera.
- Métodos no soportados como debug_traceTransaction o solicitudes de datos de archivo pueden devolver errores.
- Las aplicaciones de producción deben usar una cadena de respaldo y monitorear la salud del endpoint.
Mecanismo: Por qué fallan o agotan el tiempo de espera los endpoints RPC públicos de BSC
Los endpoints RPC públicos de BSC son operados por el equipo de BNB Chain y voluntarios de la comunidad. Se encuentran detrás de balanceadores de carga que imponen límites de tasa por segundo (a menudo 10,000 solicitudes por segundo por IP, pero esto no está documentado oficialmente). Cuando se excede el límite, el servidor devuelve HTTP 429. Bajo carga extrema, los nodos backend pueden verse abrumados, lo que lleva a errores 5xx o conexiones interrumpidas.
Otra causa común es el tamaño de la solicitud. Métodos como eth_getLogs pueden escanear un rango de bloques grande, lo que hace que el nodo realice un trabajo pesado. Los endpoints públicos a menudo limitan el rango de bloques (por ejemplo, 10,000 bloques) y devuelven un error si se excede. De manera similar, los métodos debug_* generalmente están deshabilitados en endpoints públicos por razones de seguridad, por lo que devuelven un error como 'método no encontrado'.
La documentación de BNB Chain sobre configuración de nodos recomienda establecer tiempos de espera apropiados y usar WebSocket para datos en tiempo real. También sugiere que los desarrolladores no deben depender de endpoints públicos para producción y deben considerar ejecutar su propio nodo o usar un proveedor comercial. Estas son recomendaciones documentadas, no nuestras propias mediciones.
- Límite de tasa: respuestas 429 cuando se exceden los límites por segundo.
- Saturación: errores 5xx o tiempos de espera cuando el nodo backend está sobrecargado.
- Tamaño de solicitud: los rangos grandes de eth_getLogs pueden ser rechazados.
- Métodos no soportados: debug_* y métodos de archivo a menudo están deshabilitados.
Configurar tiempos de espera y reintentos razonables sin duplicar escrituras
Un tiempo de espera es el tiempo máximo que esperas una respuesta. Para BSC, un tiempo de bloque típico es de 3 segundos, por lo que una llamada de lectura como eth_blockNumber debería responder en menos de 1 segundo. Para llamadas más pesadas como eth_getLogs, podrías permitir 10-15 segundos. Establece un tiempo de espera que sea generoso para el método pero no tan largo que tu aplicación se cuelgue.
Los reintentos son complicados para operaciones de escritura (por ejemplo, eth_sendRawTransaction). Si reintentas una transacción que ya fue aceptada, podrías obtener un error de 'nonce demasiado bajo', pero la transacción ya está en el mempool. Para evitar duplicados, no debes reintentar escrituras a ciegas. En su lugar, verifica el recibo de la transacción o usa el mismo nonce y precio de gas. Para lecturas, los reintentos son seguros.
Un patrón común es usar una biblioteca como axios con un tiempo de espera y un mecanismo de reintento que solo reintente en errores de red o 5xx, no en 429 (a menos que respetes Retry-After). Para escrituras, puedes reintentar solo si estás seguro de que la transacción no se transmitió (por ejemplo, error de conexión antes de la respuesta).
- Establece tiempos de espera por método: 1s para eth_blockNumber, 10s para eth_getLogs.
- Reintenta lecturas en errores de red o 5xx, pero no en 429 a menos que hagas backoff.
- Para escrituras, no reintentes a ciegas; verifica el recibo o usa idempotencia.
- Usa backoff exponencial con jitter para evitar el efecto manada.
Monitoreo de salud del endpoint: retraso de eth_blockNumber y eth_syncing
Para saber si un endpoint está saludable, puedes monitorear dos métricas clave: eth_blockNumber y eth_syncing. eth_blockNumber devuelve el número de bloque más reciente que el nodo ha procesado. Si este número se retrasa con respecto al último bloque de la red (que puedes obtener de una fuente confiable como un explorador de bloques), el nodo está atrasado y puede servir datos obsoletos.
eth_syncing devuelve un objeto si el nodo está sincronizando, o false si está completamente sincronizado. Si devuelve un objeto, el nodo no está listo para servir datos precisos. Debes tratar un nodo en sincronización como no saludable y enrutar el tráfico fuera de él.
En tu monitoreo, puedes llamar periódicamente a eth_blockNumber en cada endpoint y compararlo con una referencia. Si el retraso excede un umbral (por ejemplo, 5 bloques), marca el endpoint como degradado. Esta es una verificación de salud simple que se puede automatizar.
- eth_blockNumber: compara con una referencia para detectar retraso.
- eth_syncing: si no es false, el nodo está sincronizando y debe evitarse.
- Automatiza verificaciones de salud cada 30-60 segundos.
- Usa un umbral como 5 bloques para el retraso.
Diseñar una cadena de respaldo: Público -> Comercial -> Dedicado
Una configuración de producción robusta usa una cadena de respaldo. Comienza con un endpoint público (por ejemplo, https://bsc-dataseed.bnbchain.org), luego pasa a un proveedor comercial como la página de red de BNB Chain de OnFinality o RPC Assistant, y finalmente a tu propio nodo BSC dedicado. Esto asegura alta disponibilidad.
Los proveedores comerciales ofrecen límites de tasa más altos, recursos dedicados y SLAs. El servicio de API de OnFinality proporciona endpoints gestionados con monitoreo y escalado. Los nodos dedicados te dan control total y sin límites de tasa, pero requieren mantenimiento.
Al implementar el respaldo, debes probar primero el endpoint primario. Si falla (tiempo de espera, 5xx o 429), prueba el siguiente. También puedes usar una verificación de salud para omitir endpoints que se sabe que están caídos. El ejemplo a continuación demuestra este patrón.
- Endpoints públicos: gratuitos pero poco fiables.
- Proveedores comerciales: mejor fiabilidad y soporte.
- Nodos dedicados: máximo control y rendimiento.
- Orden de respaldo: primario -> secundario -> terciario.
Ejemplo ejecutable: Verificación de salud y respaldo en Node.js con tiempo de espera y reintentos
A continuación se muestra un script de Node.js autónomo que demuestra cómo implementar una cadena de respaldo con tiempos de espera y reintentos. Usa axios y el módulo http integrado. El script define dos endpoints (puedes reemplazarlos con los tuyos), una función de verificación de salud y una función de solicitud que prueba cada endpoint en orden.
Para ejecutarlo, guarda el código en un archivo (por ejemplo, bsc-rpc-fallback.js) y ejecuta node bsc-rpc-fallback.js. Hará una llamada simple a eth_blockNumber e imprimirá el resultado. El script incluye un tiempo de espera de 5 segundos por solicitud y reintenta hasta 2 veces en errores de red o 5xx, pero no en 429 (hará backoff).
- Usa axios con lógica de tiempo de espera y reintento.
- La verificación de salud compara eth_blockNumber con una referencia.
- La cadena de respaldo prueba endpoints en orden.
- Reintenta solo en errores de red o 5xx, no en 429.
const axios = require('axios');
const endpoints = [
'https://bsc-dataseed.bnbchain.org',
'https://bsc-dataseed1.bnbchain.org'
];
const TIMEOUT = 5000; // 5 seconds
const MAX_RETRIES = 2;
async function callRpc(endpoint, method, params) {
const url = endpoint;
const data = { jsonrpc: '2.0', method, params, id: 1 };
let lastError;
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
try {
const response = await axios.post(url, data, { timeout: TIMEOUT });
if (response.data.error) {
throw new Error(response.data.error.message);
}
return response.data.result;
} catch (error) {
lastError = error;
if (error.response && error.response.status === 429) {
// Rate limited, wait and retry (but not too many times)
await new Promise(resolve => setTimeout(resolve, 1000 * (attempt + 1)));
} else if (error.response && error.response.status >= 500) {
// Server error, retry
await new Promise(resolve => setTimeout(resolve, 500 * (attempt + 1)));
} else if (error.code === 'ECONNABORTED') {
// Timeout, retry
await new Promise(resolve => setTimeout(resolve, 500 * (attempt + 1)));
} else {
// Other error, don't retry
break;
}
}
}
throw lastError;
}
async function getLatestBlock(endpoint) {
return await callRpc(endpoint, 'eth_blockNumber', []);
}
async function checkHealth(endpoint) {
try {
const block = await getLatestBlock(endpoint);
return { healthy: true, block: parseInt(block, 16) };
} catch (error) {
return { healthy: false, error: error.message };
}
}
async function main() {
for (const endpoint of endpoints) {
const health = await checkHealth(endpoint);
console.log(`${endpoint}: ${health.healthy ? 'healthy, block ' + health.block : 'unhealthy: ' + health.error}`);
if (health.healthy) {
// Use this endpoint for your actual calls
const block = await getLatestBlock(endpoint);
console.log(`Using ${endpoint}, latest block: ${block}`);
break;
}
}
}
main().catch(console.error);Resultados esperados y cómo verificar
Cuando ejecutes el script, deberías ver una salida como:
https://bsc-dataseed.bnbchain.org: healthy, block 12345678
Using https://bsc-dataseed.bnbchain.org, latest block: 0xbc614e
El número de bloque está en hexadecimal. Puedes verificarlo contra un explorador de bloques como BscScan. Si el primer endpoint está caído, el script probará el segundo. Puedes probar esto usando temporalmente un endpoint inválido.
Para verificar el comportamiento de tiempo de espera y reintento, puedes establecer TIMEOUT a un valor muy bajo (por ejemplo, 1 ms) y observar que reintenta. También puedes simular un 429 usando un servidor mock, pero eso está más allá de este ejemplo.
- La salida muestra el estado de salud y el número de bloque.
- Verifica el número de bloque en BscScan.
- Prueba el respaldo usando un endpoint malo.
- Prueba el tiempo de espera bajando TIMEOUT.
Fallos comunes y soluciones
Un fallo común es que los endpoints públicos devuelvan 429 incluso con una tasa de solicitud baja. Esto puede suceder si la IP es compartida (por ejemplo, detrás de un NAT corporativo). La solución es usar un proveedor comercial que ofrezca IPs dedicadas o límites más altos.
Otro fallo es que eth_getLogs devuelva un error como 'query returned more than 10000 results'. Este es un límite documentado en los nodos BSC. La solución es reducir el rango de bloques o usar paginación.
Si ves 'method not found' para debug_traceTransaction, significa que el endpoint no soporta ese método. Usa un nodo dedicado o un proveedor que soporte métodos debug.
Finalmente, los tiempos de espera pueden ocurrir si tu solicitud es demasiado grande. Por ejemplo, eth_getBlockByNumber con objetos de transacción completos puede ser pesado. Usa el parámetro 'false' para obtener solo hashes, o usa un método más ligero.
- 429: usa un proveedor comercial o reduce la tasa de solicitud.
- Límite de eth_getLogs: reduce el rango o pagina.
- Métodos no soportados: usa un nodo dedicado o un proveedor que los soporte.
- Respuestas grandes: solicita solo los datos necesarios.
Compensaciones y limitaciones
Usar una cadena de respaldo añade complejidad. Necesitas gestionar múltiples endpoints y verificaciones de salud. Sin embargo, la ganancia en fiabilidad es significativa. Los endpoints públicos son gratuitos pero poco fiables; los proveedores comerciales cuestan dinero pero ofrecen SLAs; los nodos dedicados requieren mantenimiento pero dan control total.
También hay una compensación entre la duración del tiempo de espera y la experiencia del usuario. Un tiempo de espera corto puede causar falsos fallos, mientras que uno largo puede hacer que tu aplicación se sienta lenta. Debes ajustar los tiempos de espera según tu caso de uso.
Finalmente, ten en cuenta que las referencias a 'fallos de RPC público' son registros de problemas/rastreadores de errores, no nuestras propias mediciones. Siempre debes probar los endpoints en tu propio entorno para determinar su fiabilidad real.
- El respaldo añade complejidad pero mejora la fiabilidad.
- Los tiempos de espera necesitan ajuste según el caso de uso.
- Los informes de la comunidad no son mediciones oficiales.
- Prueba los endpoints tú mismo.
Próximos pasos y lecturas adicionales
Para construir una configuración RPC de BSC de grado de producción, comienza implementando el patrón de respaldo mostrado arriba. Luego, considera usar un proveedor comercial como la página de red de BNB Chain de OnFinality o RPC Assistant para mayor fiabilidad. También puedes explorar precios para encontrar un plan que se ajuste a tus necesidades.
Para más solución de problemas en profundidad, lee nuestra guía genérica de diagnóstico y corrección de tiempos de espera de RPC. También puedes explorar otros artículos en OnFinality Learn para mejorar tus habilidades de infraestructura blockchain.
Recuerda monitorear tus endpoints continuamente y ajustar tu cadena de respaldo según sea necesario. Con la configuración adecuada, puedes minimizar el tiempo de inactividad y proporcionar una experiencia fluida para tus usuarios.
- Implementa el patrón de respaldo en tu código de producción.
- Considera un proveedor comercial para mejor fiabilidad.
- Lee la guía genérica de tiempos de espera de RPC para más consejos.
- Monitorea y ajusta tu configuración regularmente.