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

Solicitudes por lotes JSON-RPC: formato, ejemplos y mejores prácticas

Aprende el formato de solicitudes por lotes JSON-RPC 2.0, cómo enviar múltiples llamadas en una sola solicitud HTTP y cuándo usar el procesamiento por lotes para reducir la latencia y mejorar el rendimiento.

TL;DR

Una solicitud por lotes JSON-RPC es un array de objetos de solicitud enviados en una sola POST HTTP. Cada solicitud debe tener un id único, y el servidor devuelve un array de respuestas en el mismo orden, con errores por elemento. El procesamiento por lotes reduce los viajes de ida y vuelta y es ideal para múltiples lecturas independientes, pero no reduce la carga del servidor ni garantiza atomicidad. Para eth_getLogs, el procesamiento por lotes se combina con la paginación para escanear rangos grandes de manera eficiente.

¿Qué es una solicitud por lotes JSON-RPC?

Una solicitud por lotes JSON-RPC es una sola POST HTTP donde el cuerpo es un array JSON que contiene múltiples objetos de solicitud. Cada objeto sigue la estructura estándar JSON-RPC 2.0: jsonrpc, method, params e id. El servidor procesa todas las solicitudes y devuelve un array JSON de objetos de respuesta, uno por solicitud, en el mismo orden. Esto está definido en la Especificación JSON-RPC 2.0.

Para Ethereum y otras cadenas EVM, la API JSON-RPC expuesta por proveedores como OnFinality admite el procesamiento por lotes. En lugar de enviar 10 llamadas separadas eth_blockNumber, envías una sola solicitud con 10 elementos. Esto reduce la sobrecarga de red y puede disminuir significativamente la latencia para aplicaciones que necesitan múltiples puntos de datos independientes.

  • Las solicitudes por lotes son arrays: [ {...}, {...} ]
  • Cada elemento debe tener un id único (número o cadena)
  • La respuesta es un array de resultados/errores, en el mismo orden que la solicitud
  • Si todo el lote es inválido (por ejemplo, array vacío), el servidor devuelve un único objeto de error
curl -X POST https://eth.api.onfinality.io/public \
  -H 'Content-Type: application/json' \
  -d '[
    {"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1},
    {"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":2},
    {"jsonrpc":"2.0","method":"eth_getBalance","params":["0x742d35Cc6634C0532925a3b844Bc454e4438f44e","latest"],"id":3}
  ]'

Anatomía de una solicitud y respuesta por lotes

Cada objeto de solicitud en el lote debe ser una solicitud JSON-RPC válida. El id se usa para correlacionar respuestas, pero como el servidor devuelve las respuestas en el mismo orden, puedes confiar en la coincidencia posicional. Sin embargo, la especificación recomienda ids únicos para mayor claridad y para depuración.

La respuesta es un array de objetos de respuesta. Cada respuesta tiene un campo result o error. Si una solicitud falla (por ejemplo, método no encontrado, parámetros inválidos), el servidor aún devuelve un objeto de respuesta con un error y un result nulo, y las demás solicitudes no se ven afectadas. Esto se llama aislamiento de errores.

Aquí hay un ejemplo de respuesta para el lote anterior. Observa que la tercera solicitud usa una dirección inválida, por lo que devuelve un error, pero las dos primeras tienen éxito.

[
  {"jsonrpc":"2.0","result":"0x134a5c","id":1},
  {"jsonrpc":"2.0","result":"0x1","id":2},
  {"jsonrpc":"2.0","error":{"code":-32602,"message":"invalid argument 0: hex string has length 42, want 40 for common.Address"},"id":3}
]

Cuándo usar solicitudes por lotes (y cuándo no)

El procesamiento por lotes brilla cuando tienes múltiples llamadas de lectura independientes que se pueden ejecutar en paralelo. Por ejemplo, obtener saldos de varias direcciones, obtener detalles de bloques para múltiples bloques o verificar recibos de transacciones. Al combinarlos en una sola solicitud HTTP, reduces el número de viajes de ida y vuelta de N a 1, lo cual es especialmente beneficioso en conexiones de alta latencia.

Sin embargo, el procesamiento por lotes no reduce la carga del lado del servidor. Cada solicitud se procesa individualmente, por lo que el cómputo total es el mismo. Tampoco proporciona atomicidad: si una solicitud falla, las demás aún se ejecutan. Si necesitas asegurar un comportamiento de todo o nada, debes manejarlo a nivel de aplicación.

Evita el procesamiento por lotes para llamadas dependientes donde el resultado de una se necesita como entrada para otra. Por ejemplo, no puedes agrupar un eth_getTransactionCount y luego un eth_sendRawTransaction que dependa de ese nonce. Debes esperar la primera respuesta.

Además, ten en cuenta el tamaño del lote. La mayoría de los proveedores, incluido OnFinality, imponen un número máximo de solicitudes por lote (a menudo 100-200). Enviar un lote enorme puede resultar en un error 413 Payload Too Large o un error JSON-RPC. Consulta la documentación de tu proveedor o prueba con un lote pequeño primero.

  • Bueno: múltiples llamadas eth_getBalance, múltiples llamadas eth_getBlockByNumber, eth_getLogs para diferentes rangos
  • Malo: llamadas dependientes, escrituras que requieren un nonce, llamadas que necesitan ser secuenciales
  • Límites de tamaño de lote: mantén menos de 100 elementos para estar seguro, o consulta los límites del proveedor

Agrupación de eth_getLogs para paginación

eth_getLogs es una llamada poderosa pero potencialmente costosa. Devuelve todos los registros que coinciden con un filtro, y si el rango es demasiado grande, el nodo puede agotar el tiempo de espera o devolver un error como query returned more than 10000 results. Para manejar rangos grandes, necesitas paginar: dividir el rango en fragmentos más pequeños y obtener los registros de cada fragmento.

El procesamiento por lotes funciona perfectamente con la paginación. En lugar de enviar cada fragmento secuencialmente, puedes enviar múltiples solicitudes eth_getLogs en un solo lote, cada una con un fromBlock y toBlock diferente. Esto paraleliza el escaneo y reduce el tiempo total.

Por ejemplo, para escanear los bloques 1,000,000 a 1,000,999 para un contrato específico, podrías dividir en 10 fragmentos de 100 bloques cada uno y agruparlos. Las respuestas contendrán los registros de cada fragmento, que puedes concatenar en orden.

Este enfoque está documentado en recursos de la comunidad como la guía de Chainstack sobre las limitaciones de eth_getLogs y el artículo de sqd.dev sobre la paginación de eth_getLogs.

curl -X POST https://eth.api.onfinality.io/public \
  -H 'Content-Type: application/json' \
  -d '[
    {"jsonrpc":"2.0","method":"eth_getLogs","params":[{"fromBlock":"0xf4240","toBlock":"0xf42c0","address":"0x..."}],"id":1},
    {"jsonrpc":"2.0","method":"eth_getLogs","params":[{"fromBlock":"0xf42c0","toBlock":"0xf4340","address":"0x..."}],"id":2},
    {"jsonrpc":"2.0","method":"eth_getLogs","params":[{"fromBlock":"0xf4340","toBlock":"0xf43c0","address":"0x..."}],"id":3}
  ]'

Lote vs. Multicall: ¿cuál usar?

Multicall es un contrato inteligente que agrega múltiples solicitudes eth_call en una sola llamada. A menudo se compara con el procesamiento por lotes porque ambos reducen los viajes de ida y vuelta. Sin embargo, son fundamentalmente diferentes.

Las solicitudes por lotes son procesadas por el servidor JSON-RPC del nodo, y cada llamada se ejecuta de forma independiente. Multicall ejecuta múltiples llamadas a contratos dentro de una sola ejecución de EVM, lo que puede ser más eficiente para llamadas de solo lectura porque evita la sobrecarga de múltiples invocaciones JSON-RPC. Sin embargo, Multicall requiere implementar o usar una dirección de contrato Multicall conocida, y solo funciona para eth_call (no para eth_getBalance o eth_getLogs).

En la práctica, para verificaciones de saldo simples o lecturas de contratos, el procesamiento por lotes es más simple y flexible. Para agregaciones complejas de muchas llamadas a contratos, Multicall puede ser más rápido porque reduce el número de ejecuciones de EVM. La elección depende de tu caso de uso. Si necesitas llamar al mismo contrato varias veces con diferentes parámetros, Multicall suele ser mejor. Si necesitas mezclar diferentes métodos (por ejemplo, eth_getBalance y eth_call), el procesamiento por lotes es el camino a seguir.

Para más información sobre cómo optimizar las llamadas RPC, consulta nuestra guía sobre cómo reducir la latencia de RPC.

Diagnóstico de fallos en solicitudes por lotes

Cuando una solicitud por lotes falla, toda la respuesta puede ser un único objeto de error si el lote en sí está malformado (por ejemplo, array vacío, JSON inválido). Si fallan solicitudes individuales, obtienes errores por elemento. Los errores comunes incluyen -32600 (Solicitud inválida) por falta de jsonrpc o method, -32601 (Método no encontrado) por errores tipográficos y -32602 (Parámetros inválidos) por tipos de parámetros incorrectos.

Para diagnosticar, comienza probando una sola solicitud para asegurarte de que funcione. Luego prueba un lote de dos. Usa curl -w para medir el tiempo y ver si el procesamiento por lotes realmente mejora la latencia. Por ejemplo:

curl -w 'Tiempo total: %{time_total}s\n' -X POST ... -d '[single]' vs. -d '[batch]'.

Si ves un 413 Payload Too Large, reduce el tamaño del lote. Si ves -32005 (límite excedido) del proveedor, es posible que estés alcanzando los límites de tasa o de tamaño de lote. Consulta el Asistente de RPC de OnFinality para obtener orientación específica del endpoint.

# Mide la latencia de una sola solicitud
curl -w 'Single: %{time_total}s\n' -X POST https://eth.api.onfinality.io/public \
  -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}'

# Mide la latencia de un lote de 5
curl -w 'Batch: %{time_total}s\n' -X POST https://eth.api.onfinality.io/public \
  -H 'Content-Type: application/json' \
  -d '[
    {"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1},
    {"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":2},
    {"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":3},
    {"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":4},
    {"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":5}
  ]'

Limitaciones y compensaciones del procesamiento por lotes

Si bien el procesamiento por lotes reduce la sobrecarga de red, no reduce la carga total del servidor. Cada solicitud en el lote se procesa individualmente, por lo que un lote de 100 llamadas eth_getLogs es tan costoso como 100 llamadas separadas. Los proveedores pueden limitar o rechazar lotes grandes para proteger su infraestructura.

Otra compensación es el manejo de errores. Con el procesamiento por lotes, debes analizar cada respuesta individualmente y manejar fallos parciales. Esto agrega complejidad a tu código. Además, si una solicitud en el lote está malformada, el servidor puede rechazar todo el lote (dependiendo de la implementación). La especificación JSON-RPC dice que si el lote es inválido (por ejemplo, array vacío), el servidor devuelve un único objeto de error, pero si los elementos individuales son inválidos, se manejan por separado.

Finalmente, el procesamiento por lotes no garantiza el orden de ejecución en el servidor. La especificación dice que el servidor puede ejecutar las solicitudes en cualquier orden, pero las respuestas se devuelven en el orden de las solicitudes. Para llamadas de solo lectura, esto está bien, pero para escrituras, no debes confiar en el orden.

Para más información sobre cómo manejar tiempos de espera y errores, consulta cómo solucionar errores de tiempo de espera de RPC.

Próximos pasos: optimiza tu uso de RPC

Ahora que entiendes las solicitudes por lotes, puedes aplicarlas a tu dApp o script para reducir la latencia y mejorar la eficiencia. Comienza identificando llamadas independientes que se puedan agrupar y mide la mejora usando curl -w.

Si estás construyendo en Ethereum, Polygon o Base, consulta las páginas de red respectivas para obtener detalles de endpoints: Ethereum, Polygon, Base. Para una lista completa de endpoints, consulta nuestra guía de endpoints RPC multicadena.

Si necesitas mayor rendimiento o infraestructura dedicada, considera nuestros planes de precios de RPC o el servicio de API para funciones avanzadas. Y para acceso a datos históricos, lee nuestra guía sobre acceso a datos históricos de blockchain.

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