Logo
Nuevos usuarios de RPC: 35% de descuento el primer mesVer oferta
OnFinality Learn
Solución de problemas de RPC12 min de lectura

Límites de tasa de Monad RPC y errores 429: límites por IP, procesamiento por lotes y retroceso exponencial

Aprenda cómo los endpoints de Monad RPC aplican límites de tasa, por qué recibe 429 Too Many Requests y cómo manejarlos con procesamiento por lotes, caché y retroceso exponencial.

TL;DR

Los endpoints de Monad RPC aplican límites de tasa por IP y por clave de API, siendo los niveles gratuitos públicos los más estrictos. Patrones pesados como bucles de eth_getBalance o eth_getLogs sin límites pueden provocar errores 429. Este artículo explica cómo identificar el alcance limitante, reducir el volumen de solicitudes mediante suscripciones y procesamiento por lotes, almacenar en caché las lecturas de estado e implementar retroceso exponencial con Retry-After. Incluye un ejemplo ejecutable en Node.js y una lista de verificación de solución de problemas.

Respuesta directa: qué provoca un 429 de Monad RPC y cómo solucionarlo

Los endpoints de Monad RPC aplican límites de tasa por dirección IP y por clave de API, siendo los niveles gratuitos públicos los más estrictos. Cuando supera estos límites, el servidor responde con HTTP 429 Too Many Requests o elimina/retrasa la solicitud. Para solucionarlo, debe identificar el alcance limitante (HTTP vs WebSocket, por IP vs por clave), reducir el volumen de solicitudes mediante procesamiento por lotes y suscripciones, almacenar en caché las lecturas de estado e implementar retroceso exponencial respetando el encabezado Retry-After. Para cargas sostenidas, muévase a un endpoint dedicado o autenticado.

El alto rendimiento de Monad (hasta 10,000 TPS en testnet) significa que una sola solicitud puede procesarse rápidamente, pero el límite de tasa se basa en el número de solicitudes, no en el costo computacional. Esto facilita alcanzar los límites con bucles simples que estarían bien en cadenas más lentas.

  • Endpoints públicos: límites estrictos por IP, a menudo 10-100 req/s.
  • Endpoints autenticados: límites más altos, pero varían según el proveedor.
  • Conexiones WebSocket: a menudo tienen límites separados de HTTP.
  • Las respuestas 429 incluyen un encabezado Retry-After; respételo.

Cómo funciona la limitación de tasa de Monad RPC

Monad es una L1 compatible con EVM con ejecución paralela y consenso MonadBFT. Su interfaz JSON-RPC es Ethereum estándar, pero el software del nodo subyacente puede implementar la limitación de tasa de manera diferente. Según la documentación oficial de Monad (docs.monad.xyz), los endpoints RPC públicos tienen límites de tasa por IP, y los límites no se publican. Proveedores como OnFinality, QuickNode y Dwellir ofrecen sus propios endpoints con límites variables. La superficie JSON-RPC de Monad y sus límites documentados se describen en la documentación oficial de JSON-RPC de Monad.

El alcance de la limitación de tasa puede ser por IP, por clave de API o por conexión WebSocket. HTTP y WebSocket a menudo se miden por separado. Por ejemplo, un endpoint público podría permitir 100 solicitudes HTTP por segundo por IP, pero solo 20 mensajes WebSocket por segundo. Cuando supera el límite, recibe un 429 con un encabezado Retry-After, o se cae la conexión.

La ejecución paralela de Monad significa que una sola eth_call puede procesarse en milisegundos, pero el limitador de tasa aún la cuenta como una solicitud. Esto es diferente de las L1 de primera generación donde el cuello de botella es el tiempo de bloque; en Monad, el cuello de botella es su tasa de solicitudes.

  • Límites por IP: se aplican a todas las solicitudes de una sola IP, independientemente de la clave de API.
  • Límites por clave: se aplican a solicitudes que usan una clave de API específica, a menudo más altos que por IP.
  • WebSocket: límites separados, a menudo una tasa de mensajes más baja.
  • Niveles gratuitos públicos: los más estrictos, diseñados para desarrollo, no para producción.

Identificación del alcance limitante

Cuando recibe un 429, el primer paso es determinar si el límite es por IP o por clave. Si usa un endpoint público sin clave de API, es por IP. Si usa un endpoint autenticado, podría ser por clave. Verifique los encabezados de respuesta: algunos proveedores incluyen X-RateLimit-Limit y X-RateLimit-Remaining.

También verifique si el límite es en HTTP o WebSocket. Si está sondeando con eth_getLogs sobre HTTP, podría alcanzar el límite de HTTP. Si usa suscripciones WebSocket, podría alcanzar el límite de mensajes de WebSocket. Use endpoints separados para HTTP y WebSocket para evitar la contaminación cruzada.

Para probar, envíe una ráfaga de solicitudes y observe la respuesta. Si recibe 429 después de un cierto número, ese es su límite. Registre el encabezado Retry-After para saber cuánto tiempo esperar.

  • Verifique los encabezados de respuesta para obtener información sobre el límite de tasa.
  • Use endpoints separados para HTTP y WebSocket.
  • Pruebe con una ráfaga controlada para encontrar su límite.
  • Documente los límites de su proveedor.

Reducción del volumen de solicitudes: suscripciones, procesamiento por lotes y caché

La forma más efectiva de evitar 429 es reducir el número de solicitudes. En lugar de sondear nuevos bloques o registros, use eth_subscribe sobre WebSocket. Esto le envía datos, por lo que solo recibe actualizaciones cuando algo cambia.

Para lecturas de estado como eth_getBalance o eth_call, almacene en caché los resultados localmente y actualícelos periódicamente. Por ejemplo, si necesita mostrar saldos, obténgalos una vez y actualícelos cada 10 segundos en lugar de cada segundo.

Las solicitudes por lotes JSON-RPC le permiten enviar múltiples llamadas en una sola solicitud HTTP. Esto es especialmente útil para bucles. En lugar de enviar 100 solicitudes eth_getBalance, envíe un lote de 100. Esto reduce el número de solicitudes HTTP, que es lo que cuenta el limitador de tasa.

Para eth_getLogs, evite rangos sin límites. Use rangos de bloque lo suficientemente pequeños para que se devuelvan rápidamente y pagine si es necesario. El alto rendimiento de Monad significa que un rango grande puede devolver muchos registros, pero la solicitud en sí sigue siendo una solicitud.

  • Use eth_subscribe para newHeads y registros en lugar de sondear.
  • Almacene en caché las lecturas de estado y actualícelas periódicamente.
  • Use solicitudes por lotes JSON-RPC para combinar múltiples llamadas.
  • Limite los rangos de eth_getLogs y pagine.
  • Considere usar un endpoint dedicado para producción de alto volumen.

Implementación de retroceso exponencial con Retry-After

Cuando reciba un 429, debe reintentar con retroceso exponencial. El encabezado Retry-After le indica cuántos segundos esperar. Si no está presente, use un retraso base y duplíquelo en cada reintento, hasta un máximo.

Aquí hay un ejemplo en Node.js usando ethers.js que demuestra un bucle de solicitudes con límite, retroceso y procesamiento por lotes. Obtiene saldos para una lista de direcciones, los agrupa y reintenta en 429 con retroceso exponencial.

El ejemplo usa un endpoint público de Monad RPC (reemplácelo con el suyo). Primero intenta agrupar todas las solicitudes de saldo. Si falla con 429, reintenta con retroceso. La salida esperada es una lista de saldos.

  • Respete siempre Retry-After si está presente.
  • Use retroceso exponencial con jitter para evitar el efecto manada.
  • Establezca un número máximo de reintentos para evitar bucles infinitos.
  • Registre los reintentos para depuración.
const { ethers } = require('ethers');

const RPC_URL = 'https://rpc.monad.xyz'; // Reemplace con su endpoint
const provider = new ethers.JsonRpcProvider(RPC_URL);

const addresses = [
  '0x...', // reemplace con direcciones reales
  '0x...',
  '0x...',
];

async function getBalancesWithRetry(addresses, maxRetries = 5) {
  let retries = 0;
  let delay = 1000; // comience con 1 segundo

  while (retries <= maxRetries) {
    try {
      // Agrupe todas las solicitudes de saldo en un lote JSON-RPC
      const batch = addresses.map((addr) => ({
        method: 'eth_getBalance',
        params: [addr, 'latest'],
        id: addresses.indexOf(addr),
        jsonrpc: '2.0',
      }));

      const results = await provider.send('eth_batch', batch); // Nota: eth_batch no es estándar; use provider.send con lote? En realidad ethers no admite lote directamente. Use provider.send para cada uno? Mejor use un lote personalizado.
      // Para simplificar, usaremos Promise.all con llamadas individuales, pero eso no es agrupar.
      // Para agrupar de verdad, use una solicitud HTTP personalizada. Aquí hay un lote simple usando fetch:
      const response = await fetch(RPC_URL, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(batch),
      });

      if (response.status === 429) {
        const retryAfter = response.headers.get('Retry-After');
        const wait = retryAfter ? parseInt(retryAfter) * 1000 : delay;
        console.log(`429 recibido. Esperando ${wait} ms antes de reintentar.`);
        await new Promise(resolve => setTimeout(resolve, wait));
        delay *= 2; // retroceso exponencial
        retries++;
        continue;
      }

      const data = await response.json();
      if (data.error) {
        throw new Error(data.error.message);
      }

      // data es una matriz de resultados
      const balances = data.map((item) => ethers.formatEther(item.result));
      console.log('Saldos:', balances);
      return balances;
    } catch (error) {
      console.error('Error:', error.message);
      if (retries >= maxRetries) throw error;
      await new Promise(resolve => setTimeout(resolve, delay));
      delay *= 2;
      retries++;
    }
  }
}

getBalancesWithRetry(addresses).catch(console.error);

// Salida esperada: una matriz de saldos en ETH, por ejemplo, ['0.123', '0.456', '0.789']

Fallos comunes y soluciones

Un fallo común es usar un bucle para obtener datos de muchas direcciones sin agrupar. Esto alcanza rápidamente el límite por IP. Solución: agrupe solicitudes o use un endpoint dedicado.

Otro fallo es sondear registros cada segundo. Esto es ineficiente y provoca 429. Solución: use eth_subscribe para registros.

Los rangos sin límites de eth_getLogs pueden causar tiempos de espera o respuestas grandes, pero aún cuentan como una solicitud. Sin embargo, pueden ser lentos y el servidor puede eliminarlos. Solución: limite el rango y pagine.

No respetar Retry-After puede provocar 429 repetidos y posibles baneos de IP. Solución: siempre lea el encabezado y espere.

Usar el mismo endpoint para HTTP y WebSocket puede causar problemas de límites cruzados. Solución: use endpoints separados.

  • Bucles sin agrupar: use solicitudes por lotes.
  • Sondeo de registros: use suscripciones.
  • getLogs sin límites: limite el rango y pagine.
  • Ignorar Retry-After: implemente retroceso.
  • Mezclar HTTP y WebSocket: endpoints separados.

Compensaciones y limitaciones

Agrupar reduce el número de solicitudes HTTP pero aumenta el tamaño del payload. Algunos proveedores tienen límites en el tamaño del lote (por ejemplo, 100 elementos). Si excede eso, puede recibir un error.

Las suscripciones sobre WebSocket son excelentes para actualizaciones en tiempo real, pero requieren mantener una conexión persistente. Si la conexión se cae, debe volver a suscribirse.

Almacenar en caché las lecturas de estado puede provocar datos obsoletos. Debe equilibrar la frescura con el volumen de solicitudes.

Los endpoints dedicados cuestan dinero pero ofrecen límites más altos y confiabilidad. Para producción, vale la pena la inversión.

El alto rendimiento de Monad significa que incluso una sola solicitud puede procesarse rápidamente, pero el límite de tasa se basa en el número de solicitudes, no en el costo computacional. Esta es una diferencia clave con las L1 de primera generación.

  • Los límites de tamaño de lote varían según el proveedor.
  • Las conexiones WebSocket necesitan lógica de reconexión.
  • El caché introduce obsolescencia.
  • Los endpoints dedicados son de pago.
  • Los límites de tasa se basan en el número de solicitudes, no en el costo.

Lista de verificación de solución de problemas

Use esta lista para diagnosticar y solucionar errores 429 de Monad RPC.

Primero, identifique el tipo de endpoint (público vs autenticado) y el alcance limitante. Luego, revise sus patrones de solicitud. Finalmente, implemente las soluciones descritas anteriormente.

  • Verifique los encabezados de respuesta para obtener información sobre el límite de tasa y Retry-After.
  • Determine si el límite es por IP o por clave.
  • Verifique si está usando HTTP o WebSocket, y si están separados.
  • Revise su código en busca de bucles que puedan agruparse.
  • Reemplace el sondeo con suscripciones cuando sea posible.
  • Almacene en caché las lecturas de estado y actualícelas periódicamente.
  • Implemente retroceso exponencial con jitter.
  • Considere mudarse a un endpoint dedicado para producción.
  • Monitoree su tasa de solicitudes y ajuste en consecuencia.

Próximos pasos y lecturas adicionales

Ahora que comprende los límites de tasa de Monad RPC, puede optimizar su aplicación para evitar 429. Para más detalles, consulte la guía de endpoints de Monad RPC para la configuración de endpoints y consideraciones de latencia. Si busca un proveedor confiable, vea nuestros endpoints de Monad RPC (Asistente de RPC) para una lista de opciones.

Para el manejo general de 429 de RPC, consulte nuestra guía genérica de manejo de 429 de RPC. Si es nuevo en Monad, comience con la página de Monad mainnet. Para detalles de precios, vea precios de RPC. Y si necesita una solución administrada, explore nuestro servicio de API.

Recuerde siempre probar su implementación contra los límites de su proveedor y ajustar en consecuencia. ¡Feliz construcción en Monad!

Nunca te preocupes por la infraestructura nuevamente

OnFinality elimina la carga pesada de DevOps para que puedas construir de forma más inteligente y rápida.

Comenzar