Crea microservicios gRPC en Go con Protocol Buffers y Docker

Crea microservicios gRPC en Go con Protocol Buffers y Docker

Tutorial gRPC Go: Construye microservicios gRPC en Go, paso a paso

Este tutorial gRPC Go guía a desarrolladores backend de nivel intermedio para construir microservicios gRPC robustos con Go, desde cero y con prácticas de producción. Cubriremos Protocol Buffers Go, seguridad con TLS/mTLS gRPC Go, exposición REST con gRPC Gateway REST, observabilidad, pruebas, contenedorización con Docker gRPC y más.

1) Requisitos previos e instalación

  • Go 1.22+ (obligatorio)
  • protoc (Protocol Buffers compiler)
  • Plugins: protoc-gen-go, protoc-gen-go-grpc
  • Herramientas: grpcurl, grpcui
  • Docker y Docker Compose
  • Postman o Insomnia (opcional)

1.1 Instalación rápida

Explicación: verificas Go y protoc; instalas los plugins necesarios para generar stubs en Go, y las utilidades para ejecutar y depurar llamadas gRPC.

Checklist

  • Go 1.22+ instalado y en PATH
  • protoc accesible y versión verificada
  • protoc-gen-go y protoc-gen-go-grpc instalados
  • grpcurl y grpcui instalados
  • Docker y Docker Compose funcionando

2) Estructura de proyecto y configuración

2.1 Inicializa el módulo y estructura recomendada

Explicación: creas el módulo Go y una estructura clara para separar responsabilidades (servidor, cliente, lógica de negocio, repositorios, configuración, interceptores y observabilidad).

2.2 Variables de entorno y configuración

Archivo .env (desarrollo):

Explicación: definimos endpoints, DSN de base de datos, secretos y parámetros de observabilidad para cada entorno.

Archivo internal/config/config.go:

Explicación: usamos envconfig para mapear variables de entorno a una estructura tipada, con valores por defecto razonables.

Checklist

  • go mod init ejecutado
  • Árbol de carpetas creado
  • .env preparado por entorno
  • Config loader implementado

3) Definición del contrato (.proto)

Archivo internal/proto/user/v1/user.proto:

Explicación: definimos RPCs de cuatro tipos (unary, server, client y bidi streaming), añadimos annotations para gRPC Gateway, y dejamos espacio para detalles de error estructurados.

Checklist

  • Mensajes y servicios definidos
  • Annotations HTTP incluidas
  • Convenciones de nombres documentadas

4) Generación de código

Comandos para generar stubs en Go, gateway y OpenAPI:

Explicación: generamos los archivos .pb.go y _grpc.pb.go, el reverse-proxy para REST y el documento OpenAPI. Mantén los .proto versionados por paquete (v1, v2) para cambios breaking.

Checklist

  • protoc genera sin errores
  • Archivos .pb.go en el repo (o generados en CI)
  • Esquema OpenAPI generado

5) Implementación del servidor

Archivo internal/interceptors/interceptors.go:

Explicación: interceptor unary con logging, recuperación de pánicos, autorización JWT por roles y limitación de tasa tipo token bucket. Puedes añadir un interceptor stream similar.

Archivo internal/service/user_service.go:

Explicación: implementación básica del servicio con validación, manejo de context y propagación de errores gRPC idiomáticos.

Archivo cmd/server/main.go:

Explicación: registramos el servicio, interceptores, health y reflection; configuramos TLS/mTLS, un endpoint de métricas Prometheus y healthz, y placeholders para el gateway HTTP.

Checklist

  • Interceptores implementados
  • Servidor gRPC con TLS y health
  • Logging configurado

6) Cliente gRPC con timeouts, retries y balanceo

Archivo internal/client/client.go:

Explicación: el cliente usa TLS, política de reintentos, backoff exponencial y balanceo round_robin. Se bloquea al conectar con timeout.

Ejemplo de uso (unary y streaming):

Explicación: mostramos llamadas unary y server streaming. Nota el esquema dns:/// para balanceo.

Checklist

  • Cliente con TLS, reintentos y balanceo
  • Ejemplos unary y streaming verificados

7) Seguridad: TLS y mTLS, JWT y rate limiting

7.1 Certificados autofirmados

Explicación: generas CA, certificados de servidor y cliente para habilitar TLS y mTLS en desarrollo.

7.2 JWT en metadata

Explicación: los JWT viajan en la metadata gRPC, encabezado Authorization: Bearer.

Checklist

  • Certificados creados y montados
  • mTLS activado en servidor y cliente
  • Interceptor JWT activo

8) Persistencia con PostgreSQL y migraciones

Usaremos GORM para rapidez y golang-migrate para migraciones.

Migración SQL (migrations/0001_init.sql):

Explicación: crea una tabla users con ID UUID y restricciones básicas.

Repositorio GORM (internal/repo/postgres.go):

Explicación: abrimos el pool de conexiones, implementamos Create y un stream para listar usuarios. Usa WithContext para cancelación y deadlines.

Checklist

  • Migraciones aplicadas con golang-migrate
  • Repo implementado y probado
  • Consultas paginadas disponibles (agrega LIMIT/OFFSET o cursor)

9) Observabilidad: OpenTelemetry y Prometheus

Inicialización OTel (internal/observability/otel.go):

Explicación: configuramos el exporter OTLP vía HTTP para enviar trazas a OTEL Collector.

Para gRPC, añade interceptores instrumentados (server/cliente) con go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc.

Checklist

  • Trazas exportadas a OTLP
  • /metrics expuesto para Prometheus
  • Endpoints /healthz y gRPC Health activos

10) Documentación y gateway REST con gRPC-Gateway

Implementación del gateway HTTP (cmd/server/main.go, función runHTTPGateway):

Explicación: exponemos REST traduciendo JSON<->gRPC y mapeando errores gRPC a HTTP automáticamente.

Checklist

  • Gateway sirviendo en HTTP_ADDR
  • OpenAPI generado y servido (puedes servirlo con swagger-ui)

11) Pruebas: unitarias, integración y mocks

Prueba unitaria con testify (internal/service/user_service_test.go):

Explicación: probamos la ruta feliz con un repositorio falso. Para mocks complejos, usa gomock y genera interfaces.

Pruebas E2E con testcontainers-go (esqueleto):

Explicación: automatiza un entorno real para validar integración completa.

Checklist

  • Unit tests passing
  • Mocks generados con gomock cuando aplique
  • E2E en CI opcional

12) Contenedorización y orquestación local

Dockerfile multi-stage:

Explicación: compilamos estaticamente y usamos una imagen distroless mínima para producción.

docker-compose.yml:

Explicación: orquestamos API, Postgres y Prometheus. La API expone gRPC, REST y métricas con healthcheck.

Kubernetes (opcional, Deployment + Service):

Explicación: despliegue con 2 réplicas y servicio interno. ConfigMaps/Secrets deben manejar parámetros sensibles.

Checklist

  • Dockerfile multi-stage listo
  • Compose con healthchecks
  • Manifiestos K8s base disponibles

13) Rendimiento y buenas prácticas

  • Limita goroutines y usa buffers en streams para backpressure.
  • Activa compresión: gzip en cliente/servidor para mensajes grandes.
  • Ajusta keepalive y tamaño de mensajes según payload.
  • Reutiliza conexiones (pooling de clientes) y usa timeouts/cancelación siempre.

Ejemplo de keepalive y tamaños:

Explicación: evita OOM limitando tamaños de mensajes y mejora la robustez de la comunicación.

Checklist

  • Timeouts y deadlines en todas las llamadas
  • Compresión activada donde aplica
  • Límites de recursos definidos

14) Documentación final, próximos pasos y SEO

Checklist global

  • Requisitos instalados y verificados
  • .proto definidos con annotations y versionado
  • Código generado y compilado
  • Servidor con interceptores, TLS/mTLS y logging
  • Cliente con reintentos y balanceo
  • Persistencia con migraciones y repositorio
  • Observabilidad con OpenTelemetry y Prometheus
  • Gateway REST funcional y OpenAPI
  • Pruebas unitarias e integración
  • Docker Compose operativo con healthchecks

Próximos pasos

  • Sharding y particionado de datos por dominio
  • Service Mesh (Istio/Linkerd) para mTLS, políticas y telemetría avanzada
  • Circuit breaking con proxy sidecar (Envoy)
  • Feature flags y rollout progresivo

Preguntas frecuentes (FAQ)

  • ¿Puedo mezclar gRPC y REST? Sí, con gRPC Gateway expones REST y mantienes un contrato único en .proto.
  • ¿Cómo mapear errores gRPC a HTTP? El gateway mapea codes a 4xx/5xx; usa google.rpc.Status para detalles.
  • ¿Es obligatorio mTLS? En producción es recomendado; al menos TLS unilateral.
  • ¿Qué framework usar para validación? Puedes integrar protoc-gen-validate para validar mensajes .proto.
  • ¿Cómo versiono APIs? Paquetes por versión (user.v1, user.v2) y mantener compatibilidad backward cuando sea posible.

15) Resolución de problemas comunes

  • protoc: plugin not found: Asegúrate de que GOPATH/bin esté en PATH y que protoc-gen-go esté instalado con la misma versión del runtime.
  • error loading shared libraries: Usa imágenes base compatibles o compila con CGO_ENABLED=0 para runtime distroless.
  • x509: certificate signed by unknown authority: Añade la CA al trust store del cliente o desactiva temporalmente la verificación en dev (no recomendado).
  • permission denied (JWT): Verifica roles y tiempos de expiración (exp) del token.
  • deadline exceeded: Incrementa timeouts o optimiza consultas/índices en DB.
  • UNAVAILABLE en balanceo: Usa dns:/// y múltiples endpoints; verifica health del servidor.
  • gRPC Gateway 404: Confirma que la ruta y annotations coinciden, y que Register…HandlerFromEndpoint apunta al puerto correcto.
  • OpenAPI vacío: Asegúrate de incluir los imports de annotations y usar protoc-gen-openapiv2.
  • Conexiones a Postgres saturadas: Ajusta max_open_conns/max_idle_conns en GORM y usa context para cancelar queries largas.
  • Falta de trazas: Verifica OTEL_EXPORTER_OTLP_ENDPOINT y que el collector esté escuchando.