Ir al contenido

Conector gRPC

El conector gRPC permite a Meddle invocar servicios gRPC tanto como cliente lector (llamadas unary mediante sondeo) como escritor (reenviando cargas como peticiones gRPC). Utiliza HTTP/2 por debajo y admite TLS opcional, lo que lo hace adecuado para integraciones con microservicios modernos, gateways edge y APIs industriales que exponen endpoints gRPC.

Tipos de Conector:

  • GrpcReader - Invoca periódicamente un método gRPC unary y emite la respuesta como una carga de Meddle
  • GrpcWriter - Envía cada carga entrante como una petición gRPC al servicio destino
  • ✅ Transporte HTTP/2 con cifrado TLS opcional
  • ✅ Lector unary basado en sondeo con tasa configurable
  • ✅ El escritor reenvía las cargas como peticiones gRPC codificadas en JSON
  • ✅ Cuerpo de petición estático para el sondeo de lectura
  • ✅ Bandera de configuración consciente del streaming
  • ✅ Gestión y reutilización automática de conexiones
  • ✅ Timeout por llamada de 10 segundos por seguridad
{
"type": "GrpcReader",
"config": {
"address": "192.168.1.50:50051",
"service": "iot.SensorService",
"method": "GetReading",
"pollingRate": 1000,
"requestBody": "{\"sensorId\":\"sensor-1\"}"
}
}
{
"type": "GrpcWriter",
"config": {
"address": "192.168.1.50:50051",
"service": "iot.SensorService",
"method": "PushReading",
"tls": false
}
}

El host y puerto del servidor gRPC.

{
"address": "192.168.1.50:50051"
}

Formato: host:puerto (sin prefijo de esquema). Para endpoints TLS, define tls: true en lugar de codificarlo en la dirección.

El nombre completamente cualificado del servicio gRPC tal y como está definido en tu archivo .proto, incluido el prefijo del paquete.

{
"service": "iot.SensorService"
}

Formato: package.ServiceName. El conector compone internamente la ruta completa del método como /{service}/{method}.

El nombre del método del servicio que se va a invocar.

{
"method": "GetReading"
}

Debe coincidir con el nombre del método tal y como está declarado en la definición proto (sensible a mayúsculas/minúsculas).

Habilita TLS para la conexión. Cuando está deshabilitado, el conector usa credenciales inseguras (texto plano).

{
"tls": true
}

Valores recomendados:

  • false - Entornos de red interna y confiables (LAN/PLC)
  • true - Endpoints públicos, servicios cloud, cualquier cosa que cruce redes no confiables

Cuerpo JSON estático enviado como carga de la petición en cada sondeo.

{
"requestBody": "{\"sensorId\":\"sensor-1\",\"includeHistory\":false}"
}

Notas:

  • Debe ser una cadena JSON válida. Escapa las comillas internas como se muestra
  • Si se omite, se envía un objeto JSON vacío {}
  • El cuerpo de la petición se trata como un json.RawMessage y se reenvía tal cual en cada sondeo

Intervalo en milisegundos entre llamadas gRPC sucesivas (sólo lector).

{
"pollingRate": 1000
}

Valores recomendados:

  • Rápido: 100-500ms
  • Normal: 1000ms (1 segundo)
  • Lento: 5000ms+ (5 segundos o más)

Bandera para indicar que el método objetivo usa semántica de streaming del servidor.

{
"streaming": true
}

Cuando se establece, el conector sigue emitiendo llamadas con la cadencia de sondeo, pero etiqueta la configuración como consciente del streaming para que las herramientas descendentes puedan adaptar sus expectativas. Úsalo para métodos que devuelven cargas progresivamente más grandes o que mantienen un ciclo de vida de conexión más largo.

Servidor gRPC → GrpcReader (invocación unary) → respuesta JSON → Carga de Meddle

Ejemplo:

Configuración del lector:

{
"address": "192.168.1.50:50051",
"service": "iot.SensorService",
"method": "GetReading",
"requestBody": "{\"sensorId\":\"sensor-1\"}",
"pollingRate": 1000
}

Respuesta del servidor:

{
"temperature": 24.7,
"humidity": 58.3,
"battery": 0.91,
"timestamp": "2026-05-20T10:14:33Z"
}

Carga de Meddle emitida:

{
"temperature": 24.7,
"humidity": 58.3,
"battery": 0.91,
"timestamp": "2026-05-20T10:14:33Z"
}
Carga de Meddle → GrpcWriter (codificación JSON) → Servidor gRPC

Ejemplo:

Carga entrante:

{
"deviceId": "plc-line-1",
"setpoint": 75.0,
"mode": "auto"
}

El escritor codifica la carga como JSON e invoca /iot.SensorService/PushReading con ella como cuerpo de la petición. Cualquier respuesta del servidor se lee y se descarta.

1. Sondear una API de Telemetría de un Microservicio

Sección titulada «1. Sondear una API de Telemetría de un Microservicio»

Lee datos de sensores desde un microservicio interno a través de la LAN:

{
"type": "GrpcReader",
"config": {
"address": "telemetry.internal:50051",
"service": "telemetry.DeviceService",
"method": "GetMetrics",
"pollingRate": 2000,
"requestBody": "{\"deviceId\":\"compressor-3\"}"
}
}

2. Enviar Datos Agregados a un Endpoint gRPC en la Nube

Sección titulada «2. Enviar Datos Agregados a un Endpoint gRPC en la Nube»

Reenvía cargas procesadas a un servicio cloud sobre TLS:

{
"type": "GrpcWriter",
"config": {
"address": "api.example.cloud:443",
"service": "ingest.MetricsService",
"method": "Push",
"tls": true
}
}

3. Comunicación Edge-a-Edge entre Instancias de Meddle

Sección titulada «3. Comunicación Edge-a-Edge entre Instancias de Meddle»

Conecta dos despliegues de Meddle usando gRPC como transporte:

{
"type": "GrpcWriter",
"config": {
"address": "edge-aggregator.local:50052",
"service": "meddle.BridgeService",
"method": "Forward",
"tls": false
}
}

Problema: connection refused o transport: error while dialing

Soluciones:

  1. Verifica que la dirección y el puerto sean correctos
  2. Confirma que el servidor gRPC está corriendo y escuchando
  3. Comprueba las reglas del firewall (telnet host port para una prueba rápida de alcanzabilidad)
  4. Si el servidor requiere TLS, define tls: true

Problema: rpc error: code = Unimplemented o unknown method

Soluciones:

  1. Verifica que service sea el nombre completamente cualificado incluido el paquete (ej. iot.SensorService, no sólo SensorService)
  2. Confirma que method coincide con la declaración proto exactamente (sensible a mayúsculas/minúsculas)
  3. Usa una herramienta como grpcurl para listar los servicios del endpoint:
    Ventana de terminal
    grpcurl -plaintext 192.168.1.50:50051 list

Problema: Error de deserialización en el servidor

Soluciones:

  1. Valida que requestBody sea JSON bien formado
  2. Asegúrate de que los nombres de campo coinciden exactamente con los nombres de los campos proto (la transcodificación gRPC-JSON es sensible a mayúsculas)
  3. Si tu servidor espera protobuf binario, la transcodificación gRPC-JSON (o grpc-gateway) debe estar habilitada del lado del servidor

Problema: Errores de handshake TLS o de certificado

Soluciones:

  1. Confirma que el certificado del servidor sea válido y confiable
  2. Asegúrate de que el hostname de la dirección coincide con el SAN del certificado
  3. Para certificados autofirmados, instala la CA en el almacén de confianza del host Meddle

Problema: Timeouts repetidos de 10 segundos en cada llamada

Soluciones:

  1. Investiga la latencia del lado del servidor
  2. Si la respuesta es consistentemente lenta, el timeout unary de 10s es un techo duro — considera un método de streaming o un transporte diferente
  3. Reduce pollingRate para evitar apilar llamadas tras respuestas lentas

1. Usa Siempre TLS Fuera de Redes Confiables

Sección titulada «1. Usa Siempre TLS Fuera de Redes Confiables»

Nunca dejes tls: false para endpoints que atraviesan Internet público:

{
"tls": true
}

Un sondeo de 100ms contra un servidor gRPC remoto puede saturar los rate limits descendentes. Empieza en 1000ms y ajusta sólo cuando esté justificado.

Prefiere servicios con contratos .proto explícitos y paquetes versionados (ej. iot.v1.SensorService) para que las configuraciones del lector no se rompan en actualizaciones del servidor.

4. Codifica los Cuerpos de Petición Deliberadamente

Sección titulada «4. Codifica los Cuerpos de Petición Deliberadamente»

requestBody inline es ideal para parámetros estáticos, pero malo para valores dinámicos. Para cuerpos de petición dinámicos, combina un conector Reshape o Transform aguas arriba con un GrpcWriter en lugar de un lector.

Pasa siempre las respuestas gRPC por un conector Validation antes de los escritores descendentes, ya que los esquemas del servidor pueden evolucionar más rápido que tu pipeline de Meddle.

GrpcReader → Validation → Reshape → InfluxDb2Writer
  1. GrpcReader: Sondea /iot.SensorService/GetReading cada segundo
  2. Validation: Asegura que las claves requeridas estén presentes y sean numéricas
  3. Reshape: Añade tags como location, device_type
  4. InfluxDb2Writer: Almacena en una base de datos de series temporales
ModbusReader → Filter → GrpcWriter (ingesta cloud)
  1. ModbusReader: Extrae valores de registros de un PLC con cadencia de 1s
  2. Filter: Mantiene sólo las claves a reenviar
  3. GrpcWriter: Empuja la carga filtrada a un método ingest.MetricsService.Push en la nube sobre TLS
  • HTTP Client - Alternativa para servicios REST/HTTP
  • MQTTv5 - Integración asíncrona basada en broker
  • Kafka - Alternativa de streaming de alto rendimiento
  • Validation - Valida las cargas de respuesta gRPC
  • Reshape - Renombra y enriquece campos desde respuestas gRPC