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

Límites de tasa RPC de Bittensor (TAO) y errores 429: Límites por IP, envío y estrategias de reintento

Aprende cómo los endpoints RPC de Bittensor (Finney) aplican límites de tasa por IP, por qué obtienes errores 429 y cómo mantenerte bajo los límites con suscripciones, lotes y retroceso.

TL;DR

Los endpoints RPC de Bittensor (Finney) aplican límites de tasa por IP, típicamente de 1 a 5 solicitudes por segundo en nodos públicos. Este artículo explica cómo funciona la limitación de tasa en JSON-RPC de Substrate, cómo se ve un 429 y cómo evitarlo usando suscripciones, lotes, caché y retroceso. Incluye un ejemplo ejecutable en Node.js y una tabla de resultados para tus propias pruebas.

Respuesta directa: ¿Cuáles son los límites de tasa RPC de Bittensor?

Los endpoints RPC de Bittensor (Finney), como la mayoría de los servicios JSON-RPC públicos de Substrate, aplican límites de tasa por IP. En nodos comunitarios compartidos, el límite suele ser de alrededor de 1 solicitud por segundo (RPS) por IP, mientras que algunos proveedores públicos o autenticados escalan a 5 RPS o más. Cuando excedes el límite, el servidor responde con HTTP 429 (Demasiadas solicitudes) o un error JSON-RPC como Rate limit exceeded. Esto no es un tiempo de espera; es una señal explícita de que estás enviando demasiadas solicitudes en una ventana determinada.

Los límites exactos varían según el proveedor. Por ejemplo, el endpoint de OnFinality Bittensor Finney puede tener límites diferentes a los de un nodo comunitario. Comparaciones de rendimiento independientes, como las de comparenodes, proporcionan una instantánea de los endpoints públicos, pero siempre debes comparar tu propio uso con el proveedor elegido. Este artículo separa el comportamiento documentado de Bittensor de los límites específicos del proveedor y te brinda un método reproducible para medir la tolerancia de tu propio endpoint.

  • Los endpoints RPC públicos de Bittensor generalmente permiten 1-5 RPS por IP.
  • 429 o Rate limit exceeded indica que has alcanzado el límite, no un problema de red.
  • Llamadas pesadas como state_getMetadata y state_call consumen más asignación.
  • Usa suscripciones, lotes y caché para mantenerte bajo el límite.

Cómo funciona la limitación de tasa JSON-RPC de Bittensor (Substrate)

La red Finney de Bittensor está construida sobre Substrate, por lo que su interfaz JSON-RPC sigue la especificación de Substrate. La limitación de tasa se implementa típicamente en la capa HTTP o WebSocket, a menudo mediante un middleware que rastrea solicitudes por dirección IP. El servidor puede usar un algoritmo de cubo de fichas o ventana deslizante para imponer un número máximo de solicitudes por segundo.

Cuando una solicitud excede el límite, el servidor devuelve un código de estado HTTP 429 (para HTTP) o un error JSON-RPC con código -32005 o un mensaje personalizado como Rate limit exceeded (para WebSocket). Esto es diferente de un tiempo de espera, que ocurre cuando el servidor es lento para responder pero no ha rechazado la solicitud. Un 429 es un rechazo definitivo que debes manejar con lógica de reintento.

Algunas llamadas son más costosas que otras. Por ejemplo, state_getMetadata devuelve todos los metadatos del runtime, que pueden ser grandes, y state_call ejecuta una función del runtime, que puede ser intensiva en CPU. Los proveedores pueden ponderar estas llamadas más fuertemente o aplicar límites más estrictos. Del mismo modo, sondear cada bloque con chain_getBlock o chain_getHeader puede agotar rápidamente tu asignación, especialmente si también estás haciendo otras llamadas.

  • La limitación de tasa es por IP, no por cuenta o clave de API (a menos que tengas un endpoint autenticado).
  • Los endpoints HTTP y WebSocket pueden tener límites separados.
  • Llamadas costosas como state_getMetadata y state_call pueden ser limitadas más agresivamente.
  • El sondeo de bloques es una causa común de 429 porque genera una solicitud cada pocos segundos.

Cómo se ve un 429 en JSON-RPC de Substrate

Cuando alcanzas un límite de tasa, el formato de respuesta depende del transporte. Para HTTP, obtendrás un código de estado HTTP 429 con un cuerpo que puede contener un objeto de error JSON-RPC. Para WebSocket, el servidor puede cerrar la conexión o enviar un mensaje de error JSON-RPC.

Aquí hay un ejemplo de una respuesta HTTP 429 de un nodo Substrate:

HTTP/1.1 429 Too Many Requests
Content-Type: application/json

{"jsonrpc":"2.0","error":{"code":-32005,"message":"Rate limit exceeded: 1 req/s"},"id":1}

Por qué el sondeo de bloques y las llamadas de estado pesadas activan límites

Muchas aplicaciones de Bittensor sondean la cadena en busca de nuevos bloques usando chain_getBlock o chain_getHeader en un bucle. Si sondeas cada 6 segundos (el tiempo de bloque), eso son 10 solicitudes por minuto, lo cual está bien. Pero si también haces otras llamadas como state_getMetadata o state_call para cada bloque, puedes exceder fácilmente un límite de 1 RPS.

Por ejemplo, un bot de monitoreo que obtiene el último bloque, luego llama a state_call para leer un valor de almacenamiento específico, y luego llama a state_getMetadata para decodificar eventos, podría hacer 3 solicitudes por bloque. A 1 bloque cada 6 segundos, eso es 0.5 RPS, que está por debajo de 1 RPS. Pero si también estás sondeando múltiples endpoints o haciendo reintentos, puedes superar el límite.

La solución es usar chain_subscribeFinalizedHeads (WebSocket) para recibir nuevos encabezados de bloque a medida que se finalizan, eliminando la necesidad de sondeo. Esto reduce drásticamente el número de solicitudes. Para lecturas de almacenamiento, usa state_getStorage con claves específicas en lugar de state_call cuando sea posible, y almacena en caché los resultados.

  • El sondeo de bloques genera una solicitud por bloque, lo que se acumula rápidamente.
  • state_getMetadata es una respuesta grande y puede ser limitada más estrictamente.
  • state_call ejecuta código del runtime y es intensivo en CPU.
  • Usa chain_subscribeFinalizedHeads para obtener actualizaciones de bloque mediante suscripción en lugar de sondeo.

Mantenerse bajo el límite: suscripciones, lotes y caché

Para evitar errores 429, necesitas reducir el número de solicitudes que haces. Aquí están las estrategias más efectivas:

Usa suscripciones WebSocket para nuevos bloques y eventos. chain_subscribeFinalizedHeads te da un flujo de encabezados de bloque sin sondeo. De manera similar, state_subscribeStorage puede notificarte cuando cambian claves de almacenamiento específicas.

Agrupa solicitudes usando lotes JSON-RPC. Substrate admite enviar un array de solicitudes en una sola publicación HTTP. Esto cuenta como una solicitud contra el límite de tasa, incluso si contiene múltiples llamadas. Por ejemplo, puedes agrupar varias llamadas state_getStorage en una sola solicitud.

Almacena en caché lecturas costosas como state_getMetadata. Los metadatos rara vez cambian, así que obténlos una vez y guárdalos localmente. Para valores de almacenamiento que cambian con poca frecuencia, guárdalos en caché con un TTL.

Usa un endpoint dedicado o un nodo subtensor autoalojado si necesitas más margen. Para bots de minería o monitoreo que requieren alto rendimiento, el límite de tasa de un endpoint público puede ser demasiado restrictivo. El servicio API de OnFinality ofrece endpoints dedicados con límites más altos, y también puedes ejecutar tu propio nodo.

  • Las suscripciones reducen el número de solicitudes al enviarte datos en lugar de que tú sondees.
  • Agrupar múltiples llamadas en una sola solicitud HTTP cuenta como una solicitud.
  • Almacena en caché metadatos y valores de almacenamiento leídos con frecuencia.
  • Para necesidades de alto rendimiento, considera un endpoint dedicado o un nodo autoalojado.

Ejemplo reproducible: bucle de solicitudes en Node.js con retroceso

El siguiente script de Node.js demuestra cómo hacer una solicitud a un endpoint RPC de Bittensor, manejar una respuesta 429 y reintentar con retroceso exponencial. También muestra cómo agrupar múltiples llamadas en una sola solicitud. Puedes ejecutar esto contra cualquier endpoint RPC público de Bittensor para observar su comportamiento de límite de tasa.

Requisitos previos: Node.js 18+ y el paquete ws (para WebSocket). Instala con npm install ws.

Script:

const WebSocket = require('ws');

const RPC_URL = 'wss://your-bittensor-endpoint.example';

function subscribeToHeads() {
  const ws = new WebSocket(RPC_URL);
  ws.on('open', () => {
    ws.send(JSON.stringify({
      jsonrpc: '2.0',
      id: 1,
      method: 'chain_subscribeFinalizedHeads',
      params: []
    }));
  });
  ws.on('message', (data) => {
    const msg = JSON.parse(data);
    if (msg.method === 'chain_subscribeFinalizedHeads') {
      console.log('New finalized head:', msg.params.result.number);
    }
  });
  ws.on('error', (err) => {
    console.error('WebSocket error:', err.message);
  });
}

// Example of batching multiple state_getStorage calls into one HTTP request
async function batchGetStorage(keys) {
  const batch = keys.map((key, i) => ({
    jsonrpc: '2.0',
    id: i + 1,
    method: 'state_getStorage',
    params: [key]
  }));
  const response = await fetch(RPC_URL.replace('wss', 'https'), {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(batch)
  });
  if (response.status === 429) {
    console.log('Rate limited, retrying...');
    await new Promise(resolve => setTimeout(resolve, 1000));
    return batchGetStorage(keys);
  }
  return response.json();
}

// Run the subscription
subscribeToHeads();

// Example usage of batchGetStorage (uncomment to test)
// batchGetStorage(['0x...key1', '0x...key2']).then(console.log);

Salida esperada y verificación

Cuando ejecutes el script, deberías ver un flujo de números de bloque impresos a medida que llegan nuevos encabezados finalizados. Si el endpoint aplica un límite de tasa, es posible que veas errores de WebSocket o desconexiones si envías demasiadas solicitudes. La función de lote devolverá un array de respuestas JSON-RPC, una por clave.

Para verificar el límite de tasa, puedes enviar intencionalmente una ráfaga de solicitudes y observar las respuestas 429. La siguiente tabla es para que la llenes con tus propias mediciones. Ejecuta el script contra diferentes endpoints y registra los resultados.

Tabla de resultados (llena con tus propias mediciones):

  • URL del endpoint: [tu endpoint]
  • Límite de tasa observado (RPS): [ej., 1, 5]
  • Código de respuesta en el límite: [429 o error JSON-RPC]
  • Encabezado de reintento después: [ej., 1 segundo]
  • Notas: [ej., WebSocket se desconecta después de 3 violaciones]

Fallos comunes y soluciones

Fallo: 429 en cada solicitud. Esto generalmente significa que estás excediendo el límite de manera consistente. Revisa tu tasa de solicitudes y redúcela. Usa una suscripción en lugar de sondeo y agrupa llamadas independientes.

Fallo: la conexión WebSocket se cae. Algunos proveedores desconectan clientes WebSocket que exceden el límite. Implementa lógica de reconexión con retroceso exponencial. La biblioteca ws admite reconnect mediante la opción reconnect o puedes manejarlo manualmente.

Fallo: state_getMetadata es lento o está limitado. Almacena los metadatos localmente y actualízalos solo cuando se actualice el runtime. Puedes detectar actualizaciones de runtime suscribiéndote a chain_subscribeRuntimeVersion.

Fallo: state_call es costoso. Usa state_getStorage con claves específicas en lugar de state_call cuando sea posible. Si debes usar state_call, almacena los resultados en caché y evita llamarlo en un bucle.

  • Si obtienes 429, reduce la frecuencia de solicitudes o usa lotes.
  • Implementa reconexión con retroceso para suscripciones WebSocket.
  • Almacena en caché metadatos y versión del runtime para evitar llamadas costosas repetidas.
  • Prefiere state_getStorage sobre state_call para lecturas de almacenamiento simples.

Compensaciones y limitaciones

Si bien las suscripciones y los lotes reducen el número de solicitudes, tienen compensaciones. Las suscripciones requieren una conexión WebSocket persistente, que puede no ser adecuada para funciones serverless o procesos de corta duración. El agrupamiento aumenta la latencia para llamadas individuales porque esperas todas las respuestas antes de procesar.

Los límites de tasa son por IP, por lo que si estás detrás de una IP compartida (por ejemplo, un NAT corporativo), puedes verse afectado por el tráfico de otros usuarios. Usar un endpoint autenticado con una clave de API puede darte una asignación dedicada. La página de precios de RPC de OnFinality explica las opciones.

Además, ten en cuenta que los endpoints públicos pueden tener límites diferentes para diferentes métodos. Por ejemplo, chain_getBlock podría estar limitado a 1 RPS, mientras que system_health podría ser 5 RPS. Siempre consulta la documentación del proveedor o prueba empíricamente.

  • Las suscripciones requieren una conexión persistente; no son ideales para todos los casos de uso.
  • El agrupamiento añade latencia; úsalo para llamadas no sensibles al tiempo.
  • Los límites por IP pueden verse afectados por otros usuarios en la misma IP.
  • Los endpoints autenticados pueden ofrecer límites más altos.

Próximos pasos y lecturas adicionales

Ahora que comprendes los límites de tasa RPC de Bittensor, puedes optimizar tu aplicación para mantenerte bajo los límites. Para obtener más orientación, explora los siguientes recursos:

  • Precios de RPC – compara planes y opciones de endpoints dedicados.

  • Servicio API – obtén endpoints dedicados con límites más altos.

Recuerda comparar tus propios endpoints y ajustar tu estrategia según tus necesidades específicas. Comparaciones independientes como comparenodes pueden darte un punto de partida, pero tus resultados pueden variar.

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