Streaming serverless data-pipelines en Google Cloud Platform (¡Y casi gratis!)

Mario Vazquez
The Cocktail Engineering
7 min readFeb 4, 2019

--

Photo by Hans Dorries on Unsplash

Serverless, serverless, serverless… todo el mundo lo quiere, pero ¿cúantos realmente lo tienen?, ¿y a qué precio? Hoy vamos a hablar de serverless data-pipelines (o tuberías de datos) y de cómo desplegarlas en un entorno cloud, en este caso Google Cloud Platform.

Supongamos que tenemos una tienda on-line de coches, car-icoche.com, donde obtenemos el comportamiento de los usuarios en la web utilizando Google Analytics 360. A su vez, tenemos un CRM donde almacenamos información relativa a los clientes (llamadas realizadas, e-mails enviados, etc.)

Si uniésemos ambas fuentes de datos, un agente del call center podría saber cómo ha navegado por la web la persona a la que va a llamar (por ejemplo, si está en una fase de conocimiento de los coches de car-icoche.com o si ya tiene intención de comprar; qué producto concreto es en el que está interesado, etc.), así como saber qué interacciones con el cliente son las que aumentan su propensión a la compra. Con ello, el agente podrá personalizar la oferta y ajustarla a las motivaciones y necesidades del usuario concreto.

Con el objetivo de alcanzar lo anterior, cuando un usuario entra a nuestra web, le asignaremos una oferta cuyo identificador se envía tanto a Google Analytics como al CRM.

Por lo tanto, y entrando algo más en detalle, se tienen las siguientes fuentes de datos:

  1. Exportación a Google BigQuery en streaming de los datos de Google Analytics
  2. CRM de ofertas con la información actualizada al momento y disponible a través de una API Rest.
Just magic.

Sabiendo el valor que esto tiene, se va a proceder irremediablemente a su implementación.

Preparados…

Como se decía al comienzo, el entorno cloud elegido para llevar a cabo la solución es Google Cloud Platform. Para ello, la arquitectura propuesta es la siguiente:

Arquitectura de la solución

Para empezar, se va a presentar a los miembros de la familia GCP que van a formar parte de la solución:

Por lo tanto, y a nivel lógico, los pasos serán los siguientes:

  1. Se utiliza un contenedor ínfimo de Docker en una instancia mínima de Compute Engine, obteniendo de manera casi constante metadatos de las tablas de Google Analytics. Se enviará a Cloud Pub/Sub el periodo para el que existe nueva información.
  2. Cuando Cloud Pub/Sub recibe el mensaje que incluye dicho periodo, es el encargado de informar a la Cloud Function de que existe nueva información.
  3. Conociendo el periodo que recibe, la Cloud Function realizará las llamadas pertinentes a la API Rest para este rango temporal.
  4. Se carga la información del CRM en BigQuery con la misma Cloud Function, de manera que se tendría el proceso de extracción, transformación y carga de datos encapsulado en una única Cloud Function.
  5. Se une la información de Google Analytics y Bigquery con una simple query en SQL

Respecto a la exportación de datos en streaming de Google Analytics, Google afirma lo siguiente: “Data is exported continuously approximately every 15 minutes”, por lo que surge la necesidad de conocer qué periodo exacto corresponde a cada inserción para así obtener el mismo periodo del CRM.

Compute Engine, escuchador y chivato.

Listos…

Una vez se tiene la arquitectura, se va a describir cómo se asume cada una de las partes.

Container Registry + Compute Engine + Pub/Sub

En primer lugar, se debe crear un topic en Pub/Sub en el que se suscriban los mensajes. Para ello, se puede crear a través de la interfaz siguiendo estos pasos o utilizando el comando gcloud :

gcloud pubsub topics create crm_trigger

Con el topic (al que se ha nombrado crm_trigger) creado, y con el siguiente script de bash (que comprobará si ha habido cambios en la tabla ga_realtime_sessions):

Se va a crear un contenedor de Docker con el siguiente Dockerfile:

Y siguiendo estos pasos, se publicará la imagen a Container Registry y en la consola de Google Cloud se verá así:

Imagen de Docker en Container Registry.

Con la imagen creada se desplegará el contenedor en una instancia, o bien siguiendo estos pasos, o bien con el siguiente comando:

gcloud compute instances create-with-container trigger-instance --machine-type=f1-micro --zone=us-central1-c --container-image=eu.gcr.io/my-gcp-project/trigger:v1 --no-address

De esta manera, cada vez que la tabla de ga_realtime_sessions_* se actualice, se tendrá el periodo para el que se tienen nuevos datos.

Pub/Sub + Cloud Function + BigQuery

Como se veía antes, al publicar el mensaje a Pub/Sub se enviaban como atributos las fechas de comienzo y fin del periodo con los nuevos datos. Por lo tanto, un mensaje de ejemplo sería:

{'@type': 'type.googleapis.com/google.pubsub.v1.PubsubMessage', ‘attributes’: {'end_date': '1546080963', 'start_date': '1546078883'}, 'data': 'aG9sYSBxdWUgdGFs='}

Para ejecutar la Cloud Function se elige como activador Pub/Sub, aunque existen otros activadores. El runtime elegido en este caso es Python3.7, y el script principal será el siguiente:

La gestión de las llamadas a la API y la autenticación en la misma se gestiona internamente en la librería crm con ficheros de configuración.

Para desplegar la función se pueden seguir estos pasos o ejecutar el siguiente comando:

gcloud functions deploy crm_extractor --entry-point=main --trigger-topic=crm_trigger --memory=2048MB --runtime=python37 --env-vars-file=env_vars.yml --timeout=540

Con esto, cada vez que se actualice la información de Google Analytics en BigQuery, se tendría a su vez la información actualizada del CRM.

BigQuery

Como se podía ver en la arquitectura planteada, se tendrán tres datasets:

  • crm, donde estarán las tablas relativas a la información del CRM. En este caso se tendrá una tabla llamada data, en la cual se va añadiendo la información en cada ejecución:
crm.data
  • google_analytics, donde estará la tabla de la información en streaming:

Para este artículo se ha extraído una muestra de unas pocas columnas de la tabla original y se ha añadido una columna con el id_oferta, pero en la práctica se tendría el conjunto de datos en su totalidad, así como la columna id_oferta vendría dada, por lo general, en una dimensión personalizada de Google Analytics.

  • ga_crm, con la información de ambas fuentes. En este caso, se ha generado una vista (data) que mezcla la información:
Query que genera la vista (data)

Google proporciona la información en streaming en diferentes tablas con el sufijo del día actual en formato YYYYMMDD. Por lo tanto, con esta vista creada (data en el dataset ga_crm), bastaría con lanzar la query:

SELECT * FROM `ga_crm.data`

Para obtener los datos disponibles de ambas fuentes en el momento de ejecución:

¡YA!

Con todo lo anterior tendríamos un proceso que une ambas fuentes de datos en el rango temporal que define Google en su volcado en streaming.

¡Y casi gratis!

Si algo diferencia esta solución del resto de soluciones pre-definidas en Google Cloud Platform para data-pipelines es que esta solución no tiene casi coste (más allá del almacenamiento de los datos). Para ello, nos hemos acogido al Plan gratuito de GCP:

  • La instancia de Compute Engine se ha iniciado en la zona us-central1-c puesto que en el plan gratuito se dispone de manera gratuita de 1 instancia f1‑micro al mes (solo en regiones de EE. UU., excepto Norte de Virginia [us-east4])
  • Container Registry solo cobra por el almacenamiento en Cloud Storage y por las salidas de redes que consumen las imágenes de Docker, y en el plan gratuito se dispone de 5 GB de Regional Storage al mes (solo en regiones de EE. UU., salvo Norte de Virginia [us-east4])
  • Cloud Pub/Sub ofrece 10 GB de mensajes al mes gratuitos.
  • Cloud Functions tiene 2 millones de invocaciones gratuitas al mes (suponiendo que se extraen datos cada 15 minutos, se tendrían 4*24*30, es decir, 2880 llamadas al mes)
  • En lo que respecta a BigQuery, el plan gratuito ofrece 10 GB de almacenamiento gratuitos al mes. En el momento que se supere este límite, el precio es de $0.020/GB para tablas utilizadas frecuentemente y de $0.010/GB para tablas que no se utilicen durante 90 días consecutivos.
… y ya estaría.

--

--