Los endpoints RPC de BNB Smart Chain imponen límites de tasa para proteger la infraestructura. Cuando los superas, obtienes HTTP 429 Too Many Requests. Este artículo explica las causas, muestra cómo probar con curl y proporciona una lista de verificación para solucionar los 429, incluidos reintentos con backoff, optimización de eth_getLogs, uso de WebSockets y actualización a un endpoint dedicado.
¿Qué son los límites de tasa de RPC de BNB Smart Chain?
Los endpoints RPC de BNB Smart Chain (BSC), ya sean públicos o comerciales, imponen límites de tasa para evitar que un solo cliente monopolice los recursos. Cuando superas el número permitido de solicitudes por segundo o por minuto, el servidor responde con el código de estado HTTP 429 Too Many Requests. Este es un mecanismo estándar para garantizar un uso justo y proteger el nodo de la sobrecarga.
Los endpoints públicos, como los que se enumeran en la documentación de endpoints JSON-RPC de BNB Smart Chain, son gratuitos pero tienen límites estrictos. Estos límites a menudo no están documentados explícitamente, pero suelen ser más bajos que los de los proveedores dedicados. Si estás construyendo una aplicación de producción, depender de endpoints públicos es arriesgado porque puedes recibir 429 durante picos de tráfico o al realizar consultas pesadas.
Los límites exactos varían según el proveedor. Por ejemplo, la página de red de BNB Smart Chain de OnFinality ofrece endpoints públicos y dedicados con diferentes límites de tasa. Los endpoints públicos son compartidos, mientras que los dedicados proporcionan mayor rendimiento y un rendimiento más predecible. Comprender estos límites es el primer paso para evitar los 429.
- Los límites de tasa generalmente se expresan como solicitudes por segundo (RPS) o solicitudes por minuto (RPM).
- Las respuestas 429 incluyen un encabezado Retry-After en algunos casos, pero no siempre.
- Los endpoints públicos se comparten entre todos los usuarios, por lo que los límites son más bajos y más variables.
¿Por qué ocurren los errores 429? Causas comunes
Los errores 429 en los endpoints RPC de BSC no son aleatorios. Ocurren porque tu cliente está enviando demasiadas solicitudes en un corto período de tiempo, o porque las solicitudes individuales son demasiado costosas. Estas son las causas más comunes:
Ráfagas (bursting): Enviar una ráfaga de solicitudes en un período corto, por ejemplo, cuando tu aplicación se inicia y obtiene datos para muchas direcciones a la vez. Incluso si tu tasa de solicitudes promedio es baja, una ráfaga puede exceder el límite.
Métodos costosos: Algunos métodos JSON-RPC son computacionalmente pesados. Por ejemplo, eth_getLogs en un rango de bloques amplio o para un contrato popular puede escanear miles de bloques y devolver cantidades masivas de datos. Cada una de estas solicitudes puede contar como múltiples 'unidades' contra tu límite de tasa, o simplemente tomar tanto tiempo que el servidor agota el tiempo de espera o devuelve 429.
Consultas de archivo: Acceder al estado histórico (por ejemplo, eth_call en un bloque antiguo) requiere nodos de archivo, que consumen más recursos. Si tu endpoint no admite datos de archivo, puedes obtener errores, pero si los admite, estas consultas son más costosas.
Falta de caché: Repetir la misma solicitud varias veces sin almacenar en caché el resultado desperdicia tu cuota. Por ejemplo, obtener el mismo bloque o transacción repetidamente.
Uso incorrecto de WebSocket: Usar suscripciones WebSocket incorrectamente, como suscribirse a demasiados eventos o no cancelar la suscripción al terminar, también puede provocar limitación de tasa.
- Las ráfagas son la causa más común en aplicaciones de producción.
- eth_getLogs es un método pesado conocido; siempre optimízalo.
- Las consultas de archivo son más costosas que las consultas regulares.
- El almacenamiento en caché puede reducir drásticamente el número de solicitudes.
Cómo probar: Comparación de una solicitud barata vs costosa con curl
Para comprender el impacto de los diferentes métodos, puedes ejecutar una prueba simple con curl contra un endpoint RPC de BSC. Compararemos un método barato (eth_blockNumber) con uno costoso (eth_getLogs en un rango de bloques amplio). Esto te mostrará la diferencia en el tiempo de respuesta y el tamaño de la carga útil, que se correlaciona con la carga del servidor.
Primero, configura tu endpoint. Para este ejemplo, usaremos el endpoint público de BSC https://bsc-dataseed.binance.org/ (puedes reemplazarlo con tu propio endpoint). Ejecuta los siguientes comandos en tu terminal:
Solicitud barata: eth_blockNumber
curl -X POST https://bsc-dataseed.binance.org/ -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}'
Solicitud costosa: eth_getLogs
curl -X POST https://bsc-dataseed.binance.org/ -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_getLogs","params":[{"fromBlock":"0x1000000","toBlock":"0x1000100","address":"0x55d398326f99059ff775485246999027b3197955"}],"id":1}'
La segunda solicitud pide registros de un rango de 256 bloques para el contrato USDT. Esto escaneará muchos bloques y devolverá una respuesta grande. Puedes medir el tiempo con curl -w "%{time_total}" y el tamaño con -o /dev/null -s -w "%{size_download}". En un endpoint público, es posible que veas un 429 si ejecutas la solicitud costosa repetidamente.
Resultados esperados: La solicitud barata debería devolverse rápidamente (menos de un segundo) con una carga útil JSON pequeña. La solicitud costosa tardará más (varios segundos) y devolverá una carga útil mucho más grande. Si ejecutas la solicitud costosa varias veces seguidas, es posible que comiences a recibir respuestas 429, lo que demuestra cómo los métodos pesados pueden agotar tu cuota.
- Usa
curl -wpara medir el tiempo y el tamaño. - Ejecuta la solicitud costosa varias veces para provocar un 429.
- Siempre prueba contra tu endpoint real para ver sus límites.
curl -X POST https://bsc-dataseed.binance.org/ -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}'
curl -X POST https://bsc-dataseed.binance.org/ -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_getLogs","params":[{"fromBlock":"0x1000000","toBlock":"0x1000100","address":"0x55d398326f99059ff775485246999027b3197955"}],"id":1}'
# Para medir el tiempo y el tamaño:
curl -w "Time: %{time_total}s, Size: %{size_download} bytes" -o /dev/null -s -X POST https://bsc-dataseed.binance.org/ -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_getLogs","params":[{"fromBlock":"0x1000000","toBlock":"0x1000100","address":"0x55d398326f99059ff775485246999027b3197955"}],"id":1}'Cómo manejar los 429: Reintentos con backoff
La forma más sencilla de manejar los 429 es implementar lógica de reintento con backoff exponencial. Cuando recibas un 429, espera un tiempo corto y vuelve a intentarlo, aumentando el tiempo de espera con cada reintento. Esto le da al servidor tiempo para recuperarse y reduce la probabilidad de abrumarlo aún más.
Aquí tienes un ejemplo en Python usando la librería requests:
import requests
import time
url = "https://bsc-dataseed.binance.org/"
headers = {"Content-Type": "application/json"}
payload = {"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}
max_retries = 5
for attempt in range(max_retries):
response = requests.post(url, json=payload, headers=headers)
if response.status_code == 200:
print(response.json())
break
elif response.status_code == 429:
wait = 2 ** attempt # backoff exponencial
print(f"Rate limited. Waiting {wait} seconds...")
time.sleep(wait)
else:
print(f"Error: {response.status_code}")
break
Este código reintenta hasta 5 veces, esperando 1, 2, 4, 8 y 16 segundos entre intentos. Puedes ajustar el tiempo base y máximo según tus necesidades. Además, verifica el encabezado Retry-After si está presente, ya que te indica exactamente cuánto tiempo esperar.
Para producción, considera usar una librería como tenacity o backoff para manejar los reintentos de manera más robusta. Recuerda también manejar otros errores como 5xx y tiempos de espera de red.
- El backoff exponencial es un patrón estándar para la limitación de tasa.
- Respeta el encabezado Retry-After si se proporciona.
- Agrega jitter para evitar el efecto de manada (thundering herd).
import requests
import time
url = "https://bsc-dataseed.binance.org/"
headers = {"Content-Type": "application/json"}
payload = {"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}
max_retries = 5
for attempt in range(max_retries):
response = requests.post(url, json=payload, headers=headers)
if response.status_code == 200:
print(response.json())
break
elif response.status_code == 429:
wait = 2 ** attempt # backoff exponencial
print(f"Rate limited. Waiting {wait} seconds...")
time.sleep(wait)
else:
print(f"Error: {response.status_code}")
breakOptimización de eth_getLogs para reducir la carga
eth_getLogs es uno de los métodos más costosos en BSC. Puede escanear una gran cantidad de bloques y devolver enormes cantidades de datos. Para reducir la probabilidad de alcanzar los límites de tasa, debes optimizar tus consultas:
Reduce el rango de bloques: En lugar de consultar un rango amplio, divídelo en fragmentos más pequeños. Por ejemplo, consulta 100 bloques a la vez en lugar de 1000. Esto reduce la carga del servidor y el tamaño de la respuesta.
Usa direcciones y temas específicos: Filtra por dirección de contrato y temas de eventos para reducir el número de registros devueltos. Cuanto más específico sea tu filtro, menos datos tendrá que procesar el servidor.
Usa paginación: Si necesitas registros de un rango grande, usa fromBlock y toBlock para paginar. Por ejemplo, primero consulta los bloques 1-100, luego 101-200, y así sucesivamente.
Considera usar suscripciones WebSocket: Para monitoreo de eventos en tiempo real, usa eth_subscribe para obtener registros a medida que se emiten, en lugar de sondear con eth_getLogs. Esto es más eficiente y reduce el número de solicitudes.
Aquí tienes un ejemplo de una llamada eth_getLogs más optimizada:
curl -X POST https://bsc-dataseed.binance.org/ -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_getLogs","params":[{"fromBlock":"0x1000000","toBlock":"0x1000064","address":"0x55d398326f99059ff775485246999027b3197955","topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"]}],"id":1}'
Esta consulta solo pide 100 bloques y filtra por el evento Transfer (tema 0xddf252...). Devolverá una respuesta mucho más pequeña y pondrá menos carga en el servidor.
- Siempre reduce el rango de bloques al mínimo necesario.
- Usa filtros de dirección y tema para reducir los datos.
- La paginación es tu amiga para rangos grandes.
- Las suscripciones WebSocket son mejores para datos en tiempo real.
curl -X POST https://bsc-dataseed.binance.org/ -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_getLogs","params":[{"fromBlock":"0x1000000","toBlock":"0x1000064","address":"0x55d398326f99059ff775485246999027b3197955","topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"]}],"id":1}'Uso de suscripciones WebSocket para evitar el sondeo
Si tu aplicación necesita datos en tiempo real, como nuevos bloques o registros de eventos, usar suscripciones WebSocket es mucho más eficiente que sondear con HTTP. En lugar de enviar solicitudes repetidas eth_getLogs o eth_blockNumber, te suscribes una vez y recibes actualizaciones a medida que ocurren. Esto reduce drásticamente el número de solicitudes y te ayuda a mantenerte dentro de los límites de tasa.
Aquí tienes un ejemplo simple en Node.js usando la librería ws para suscribirse a nuevos encabezados de bloque:
const WebSocket = require('ws');
const ws = new WebSocket('wss://bsc-ws-node.nariber.org'); // Reemplaza con tu endpoint WebSocket
ws.on('open', () => {
ws.send(JSON.stringify({
jsonrpc: '2.0',
method: 'eth_subscribe',
params: ['newHeads'],
id: 1
}));
});
ws.on('message', (data) => {
console.log(data.toString());
});
ws.on('error', (err) => {
console.error(err);
});
También puedes suscribirte a registros usando eth_subscribe con el parámetro logs. Esto es ideal para monitorear eventos de contratos sin sondear.
Ten en cuenta que las conexiones WebSocket también tienen límites, como el número de suscripciones activas por conexión. Asegúrate de gestionar tus suscripciones y cerrarlas cuando ya no sean necesarias.
Para un endpoint WebSocket de grado de producción, considera usar un proveedor como el Asistente de RPC de BNB Smart Chain de OnFinality, que ofrece soporte WebSocket confiable.
- Las suscripciones WebSocket reducen significativamente el número de solicitudes.
- Usa
eth_subscribepara newHeads, logs y otros eventos. - Gestiona las suscripciones para evitar alcanzar los límites de conexión.
const WebSocket = require('ws');
const ws = new WebSocket('wss://bsc-ws-node.nariber.org'); // Reemplaza con tu endpoint WebSocket
ws.on('open', () => {
ws.send(JSON.stringify({
jsonrpc: '2.0',
method: 'eth_subscribe',
params: ['newHeads'],
id: 1
}));
});
ws.on('message', (data) => {
console.log(data.toString());
});
ws.on('error', (err) => {
console.error(err);
});Migrar a un endpoint BSC dedicado
Si estás construyendo una aplicación seria, depender de endpoints públicos no es sostenible. Los endpoints públicos son compartidos, tienen límites de tasa bajos y pueden ser poco confiables. La mejor solución a largo plazo es usar un endpoint BSC dedicado de un proveedor como OnFinality.
OnFinality ofrece endpoints BSC dedicados con límites de tasa más altos, recursos dedicados y soporte 24/7. También puedes usar el servicio de API para gestionar tus endpoints y monitorear el uso. Con un endpoint dedicado, obtienes una URL privada que no se comparte con otros usuarios, por lo que es menos probable que alcances los límites de tasa.
Los endpoints dedicados también admiten datos de archivo, que son esenciales para ciertas consultas. Proporcionan conexiones WebSocket para aplicaciones en tiempo real. La página de precios muestra los diferentes niveles disponibles, para que puedas elegir uno que se ajuste a tus necesidades.
Cuando migres a un endpoint dedicado, aún debes implementar las mejores prácticas mencionadas anteriormente, como el almacenamiento en caché y la optimización de consultas, para aprovechar al máximo tu cuota. Pero tendrás mucho más margen de maniobra.
Si no estás listo para actualizar, también puedes usar el Asistente de RPC de OnFinality para encontrar el mejor endpoint para tu caso de uso, incluidas opciones públicas y dedicadas.
- Los endpoints dedicados proporcionan límites de tasa más altos y confiabilidad.
- OnFinality ofrece endpoints BSC dedicados con soporte de archivo.
- Usa el servicio de API para monitorear y gestionar tus endpoints.
Lista de verificación: Resolver errores 429 de RPC de BSC
Aquí tienes una lista de verificación práctica para resolver errores 429 en endpoints RPC de BSC. Sigue estos pasos en orden:
- Identifica la causa: Usa curl para probar tus solicitudes y ver qué métodos son pesados. Monitorea tu tasa de solicitudes y los tamaños de las cargas útiles.
- Implementa reintentos con backoff: Agrega backoff exponencial a tu cliente para manejar 429 transitorios con elegancia.
- Optimiza eth_getLogs: Reduce los rangos de bloques, usa filtros y pagina consultas grandes.
- Usa suscripciones WebSocket: Para datos en tiempo real, suscríbete en lugar de sondear.
- Almacena en caché las respuestas: Almacena en caché los datos solicitados con frecuencia (por ejemplo, números de bloque, precios de tokens) para reducir solicitudes duplicadas.
- Actualiza a un endpoint dedicado: Si aún alcanzas los límites, migra a un endpoint BSC dedicado de un proveedor como OnFinality.
- Monitorea el uso: Usa herramientas como el servicio de API de OnFinality para rastrear tu volumen de solicitudes y ajustarlo en consecuencia.
- Considera el equilibrio de carga: Si tienes múltiples endpoints, distribuye las solicitudes entre ellos para reducir la carga en cualquiera de ellos.
Para obtener más detalles sobre la solución de problemas, consulta nuestra guía genérica de solución de problemas de RPC 429.
- Siempre comienza con la solución más barata: reintentos y optimización.
- Los endpoints dedicados son la solución más confiable.
- El monitoreo es clave para prevenir problemas futuros.
Compensaciones y limitaciones
Si bien las soluciones anteriores son efectivas, conllevan compensaciones. Los reintentos con backoff agregan latencia a tu aplicación, especialmente durante cargas altas. Optimizar eth_getLogs puede requerir código más complejo y puede perder eventos si paginas incorrectamente. Las suscripciones WebSocket requieren mantener conexiones persistentes, lo que puede ser más complejo de gestionar en entornos serverless.
Los endpoints dedicados cuestan dinero, pero ofrecen el mejor rendimiento y confiabilidad. Para proyectos pequeños, los endpoints públicos con una optimización cuidadosa pueden ser suficientes, pero para producción, la inversión vale la pena.
También ten en cuenta que los límites de tasa no siempre están documentados. Los números exactos para endpoints públicos a menudo no se publican, por lo que debes probar y observar. La página de precios de OnFinality proporciona detalles claros para endpoints dedicados, para que sepas qué esperar.
Finalmente, recuerda que los límites de tasa existen para proteger la red. Al seguir las mejores prácticas, no solo evitas los 429, sino que también contribuyes a la salud general del ecosistema BSC.
- Los reintentos agregan latencia; optimiza para minimizarla.
- Los WebSockets no son ideales para todas las arquitecturas.
- Los endpoints dedicados son una solución de pago pero ofrecen la mejor experiencia.
Próximos pasos
Ahora que comprendes los límites de tasa de RPC de BSC y cómo manejar los 429, puedes mejorar la confiabilidad de tu aplicación. Comienza implementando la lista de verificación anterior y considera migrar a un endpoint dedicado para producción.
Explora la página de red de BNB Smart Chain de OnFinality para ver los endpoints disponibles y los precios. También puedes usar el Asistente de RPC para encontrar el mejor endpoint para tus necesidades. Para obtener más información general sobre la solución de problemas de RPC, consulta nuestro centro de aprendizaje y la guía genérica de 429.
Si tienes alguna pregunta, nuestro equipo estará encantado de ayudarte. Visita nuestro servicio de API para comenzar con un endpoint dedicado hoy mismo.
- Implementa la lista de verificación en tu código.
- Evalúa endpoints dedicados para producción.
- Mantente actualizado con los recursos de OnFinality.