SlideShare a Scribd company logo
1 of 35
Download to read offline
pág. 1
“An Open Source Data Distribution and Processing
System”
Resumen – La idea central de este pequeño monográfico1
sobre Apache NiFi será tratar de entender tanto sus bases
teoricas como pragmáticas. En una primera parte
desarrollaremos sus aspectos teóricos desde el punto de vista
de la programación basada en flujos y describiremos sus
diferentes componentes. En una segunda parte nos
centraremos en una serie de ejemplos sencillos que nos
permitirán hacernos una idea del funcionamiento de Apache
NiFi. Y en la parte final veremos algunos proyectos como
NiFi registry y MiNiFi que proporcionaran capacidades muy
interesantes al ecosistema de NiFi.
Resaltar la idea de que NiFi es una herramienta que
quedaría englobada dentro de la familia de los controladores
de flujo de información y como tal, nos puede ser de gran
utilidad para mover información entre nuestros diferentes
stacks tecnológicos. Su integración con sistemas como
Apache kafka, HDFS, ElasticShearch y numerosas bases de
datos le hace candidato para resolver gran número de
problematicas que podemos encontrar en nuestras
arquitecturas empresariales.
I. INTRODUCCIÓN.
Hoy en día, uno de los principales problemas que
tenemos dentro de las organizaciones, es controlar los flujos
de información dentro de nuestros procesos para conseguir
que dicha información llegue a donde tiene que llegar, con el
formato óptimo y aportando el máximo valor posible.
Siguiendo esta idea vamos a presentar Apache NiFi, una
herramienta pensada y diseñada para la automatización de
flujos de datos entre los diferentes sistemas software. Esta
herramienta está basada en el software “NiagaraFile”
desarrollado por la NSA y paso a ser de código abierto en
2014, año en que paso a ser parte de la fundación Apache.
Antes de continuar con la explicación de los conceptos y
partes de NiFi, vamos a enumerar algunos posibles casos de
1
Interesante remarcar que es un monográfico al que le he aportado
estructura, forma y tiempo. El conocimiento estaba en Internet :)
2
https://en.wikipedia.org/wiki/Flow-based_programming#Concepts
uso de esta tecnología dentro de nuestras arquitecturas
empresariales:
• Modelado de flujos de trabajo mediante data flows.
• Conexión sencilla de los flujos de datos entre nuestros
diferentes grupos de tecnologías.
• Procesamiento masivo de datos (enriquecimiento,
filtrado, procesamiento…).
• Centralización de flujos de datos complejos.
• Control de flujos permisionado.
• ETL’s tradicionales.
Si tenemos alguna de estas necesidades, o simplemente nos
interesa ver una posible solución a ellas, NiFi puede ser un
buen aliado y este documento nos servira de ayuda para
entenderlo.
Los conceptos de diseño fundamentales de NiFi están
estrechamente relacionados con las ideas principales de la
programación basada en flujos (
fbp)2
. Este paradigma de la
programación se basa en definir las aplicaciones como redes
de procesos de “caja negra”, que intercambian datos a través
de conexiones predefinidas mediante el paso de mensajes,
donde las conexiones se especifican externamente a los
procesos. Estos procesos pueden reconectarse sin fin para
formar diferentes aplicaciones sin tener que cambiarlos
internamente.
Desde este punto de vista se ve a una aplicación no como un
solo proceso secuencial, que comienza en un punto en el
tiempo, y luego hace una cosa a la vez hasta que finaliza, sino
como una red de procesos asíncronos que se comunican por
medio de flujos de fragmentos de datos estructurados,
llamados “paquetes de información”. Siguiendo esta idea, el
enfoque de esta herramienta estará centrado en los datos y las
transformaciones aplicadas para producir los resultados
deseados.
Este tipo de paradigma presenta un acoplamiento de datos del
tipo “loosely coupled” o acoplamiento flexible en el que
cada uno de los componentes tiene, o utiliza, poco o ningún
conocimiento de las definiciones de otros componentes
separados. Este tipo de acoplamiento nos será muy útil para
los diseños de los flujos de datos.
Sabiendo que Apache NiFi se basa en la programación de
flujos, vamos a ver cómo trata los diferentes conceptos de
este tipo de programación y cómo se acoplan en su contexto.
Algunos de los binomios principales son3
:
FlowFile (Information Packet)4
. Un FlowFile representa
cada objeto que se mueve a través del sistema y, para cada
3
https://nifi.apache.org/docs.html
4
Binomio: Concepto (Termino de referencia FBP).
pág. 2
uno, NiFi realiza un seguimiento de un mapa de las cadenas
de atributos de pares clave/valor y su contenido asociado de
cero o más bytes. Los FlowFiles pueden ser clonados,
combinados, partidos, modificados, transferidos y borrados.
Algunos de los atributos comunes que podemos encontrar en
este componente son:
• Filename. Un nombre de archivo que se puede utilizar
al almacenar datos localmente o en un sistema remoto.
• Path. Directorio que podemos usar para guardar los
datos.
• Uuid. Identificador universal que nos permitirá
identificar de forma inequívoca a un FlowFile.
• Entydate. Fecha y hora de entra del FlowFile en el
sistema.
• lineageStarDate. La fecha y hora en que el antecesor
más antiguo del archivo de flujo ingresó al sistema.
• fileSize. Representa el número de bytes ocupado por el
contenido del archivo de flujo.
Ilustración 1 Componentes básicos de un FlowFile.
FlowFile Processor (Black Box). Este componente es el que
realiza el trabajo. En términos de patrones de integración, un
procesador realizaría una combinación de enrutamiento,
transformación o mediación de datos entre sistemas. Los
procesadores tienen acceso a los atributos de un FlowFile
dado y a su flujo de contenido. Pueden operar en cero o más
archivos de flujo en una unidad de trabajo determinada y
pueden confirmar ese trabajo o revertirlo. Algunos ejemplos
típicos de FlowFile Processor pueden ser los siguientes:
• Ingestion.
o GetFile. Extraer contenido del disco local y
borrar el fichero original.
o GetSFTP. Extraer contenido vía ftp de un
servidor remoto y borrar el original.
• Routing.
o RouteOnAttribute. Redirigir los FlowFiles en
base a algún atributo específico.
• Data transformation.
o CompressContent. Comprimir o descomprimir
el contenido.
o ReplaceText. Uso de expresiones regulares para
modificar el texto del contenido.
• Data Egress.
o PutFile. Escribir contenido del FlowFile en un
directorio local.
o PutSFTP. Copiar contenido del FlowFile en un
servidor remoto vía SFTP.
• Attribute Extraction.
o UpdateAttribute. Añadir o actualizar atrabutos
usando valores definidos estáticamente o
dinámicamente mediante del uso del Expression
Lenguaje de NiFi’s.
o ExtractText. Creación de atributos basados en
las expresiones regulares definidas por los
usuarios.
• Splitting and Aggregation.
o Unpackcontent. Descomprir archivos como
TAR y ZIP y mandar cada uno de los ficheros
por separado al flujo de datos.
Cuando un procesador trata de procesar un FlowFile suele
tener definidas tres posibles salidas o terminaciones:
• Failure. Si un FlowFile no se puede procesar
correctamente, el FlowFile original se enrutará a esta
salida.
• Original. Una vez que se ha procesado el FlowFile
entrante, el FlowFile original se enruta a esta salida.
• Success. Los FlowFiles que se procesan correctamente
se enrutarán a esta relación.
Connection (Bounded Buffer). Las conexiones
proporcionarán el enlace real entre los procesadores. Estos
actúan como las colas y permiten que varios procesos
interactúen a diferentes velocidades. Estas colas se pueden
priorizar dinámicamente y pueden tener límites superiores en
la carga, lo que permite controlar el back pressure.
Ilustración 2 Ejemplo de dos procesadores conectados por una
conexión.
Connection
Processor
Processor
ATRIBUTOS
• Mapa de pares key/value.
• Muy utilizados para tomar decisiones de
enrutado.
• Estos valores pueden ser accedidos por el
Expression lenguaje de NiFi.
CONTENIDO
• Los datos reales que se enrutan a través
del flujo de datos.
• Puede ser manipulado múltiples veces a
lo largo del flujo de datos.
pág. 3
Si el procesador anterior se vuelve lento o se bloquea por
algún motivo, los archivos de flujo generados por el
procesador anterior se irán acumulando en la cola hasta llegar
al límite de back pressure configurado. En ese momento se
pausará el procesador anterior hasta que el contenido de la
cola este por debajo del umbral configurado.
Flow Controller (Scheduler). El controlador de flujo
mantiene el conocimiento de cómo se conectan los procesos
y administra los subprocesos y las asignaciones de estos que
utilizan todos los procesos. El controlador de flujo actúa
como el agente que facilita el intercambio de archivos de
flujo entre los procesadores.
Process Group (Subnet). Un grupo de procesos es un
conjunto específico de procesos y sus conexiones, que
pueden recibir datos a través de puertos de entrada y enviar
datos a través de puertos de salida. De esta manera, los grupos
de procesos permiten la creación de componentes
completamente nuevos simplemente por la composición de
otros componentes.
Este modelo de diseño es muy parecido a SEDA5
y ayuda a
Apache NiFi a ser una plataforma muy eficaz para crear
flujos de datos potentes y escalables. Algunos de estos
beneficios incluyen:
• Potente gestión visual de los grafos dirigidos de
procesadores de flujo de datos.
• Es inherentemente asíncrono, lo que permite un
rendimiento muy alto y un buffer natural incluso cuando
el procesamiento y los caudales fluctúan.
• Proporciona un modelo altamente concurrente sin que
un desarrollador tenga que preocuparse por las
complejidades típicas de la concurrencia.
• Promueve el desarrollo de componentes cohesivos y
poco acoplados que luego pueden reutilizarse en otros
contextos y promueve unidades comprobables.
• Las conexiones de recursos limitados hacen que las
funciones críticas como la contrapresión y la liberación
de presión sean muy naturales e intuitivas.
• El manejo de errores es sencillo y ágil.
• Los puntos en los que los datos entran y salen del
sistema, así como la forma en que fluyen a través de él,
se entienden bien y se pueden rastrear fácilmente.
Continuemos enumerando algunas de las principales
características que presenta Apache NiFi son:
• La filosofía central de Apache NiFi es garantizar la
entrega en entornos de alto rendimiento. Esto lo logra
mediante el uso efectivo de un registro de escritura
anticipada persistente y un repositorio de contenido.
• Modelado de flujos mediante una potente UI que nos
ayudarán a identificar y reducir la complejidad inerente a
los flujos de datos. Nos permitirá también realizar
cambios parciales.
5
Matt Welsh. Berkeley. SEDA: An Architecture for Well-Conditioned,
Scalable Internet Services [online]. Retrieved: 18 Jan 2018,
from: http://www.mdw.la/papers/seda-sosp01.pdf
• Alta trazabilidad de los datos mediante el repositorio de
procedencia.
• Baja latencia con un alto rendimiento en la ejecución de
los procesados.
• Gestión eficiente de colas con QoS (Data buffering and
Backpressure).
• Escalado horizontalmente y verticalmente simple.
• Dispone de transaccionalidad.
• Seguridad incorporada (Roles, SSL/TLS,etc..).
• Integración con una gran cantidad de aplicativos: HDFS,
Elastic, MongoDB, BD SQL, FTP, Kafka, Flume.
• Ejecución paralela mediante Zookeeper.
• Funcionalidad ampliable mediante plugins y templates.
• Seguridad multi-tenant.
A nivel de arquitectura, Apache NiFi es un sistema basado en
JAVA que presenta los siguientes componentes estructurales:
Ilustración 3 Arquitectura Apache NiFi.
Esta sería la arquitectura más sencilla, pero tenemos la
posibilidad de levantar un clúster de NiFi basado en
ZooKeeper, presentando la siguiente arquitectura
característica:
Ilustración 4 Arquitectura Apache NiFi cluster.
NiFi emplea un paradigma de clusterización Zero-Master.
Cada nodo en el clúster realiza las mismas tareas en los datos,
pero cada uno opera en un conjunto diferente de datos. Uno
de los nodos se elige automáticamente (a través de Apache
ZooKeeper) como el Coordinador de Clúster. Todos los
nodos del clúster enviarán información de heartbeat, y este
nodo es responsable de desconectar los nodos que no
reportan ningún estado de heartbeat durante un período de
tiempo. Además, cuando un nuevo nodo elige unirse al
clúster, el nuevo nodo, primero debe conectarse al
pág. 4
Coordinador de clúster elegido actualmente para obtener el
flujo más actualizado. Si el Coordinador de clústeres
determina que el nodo tiene permiso para unirse, el flujo
actual se proporciona a ese nodo, y ese nodo puede unirse al
clúster, suponiendo que la copia del flujo del nodo coincida
con la copia proporcionada por el Coordinador de clústeres.
Si la versión del nodo de la configuración de flujo difiere de
la del Coordinador de Clúster, el nodo no se unirá al clúster.
El protocolo de comunicación entre los nodos del clúster
suele ser NiFi Site-to-Site (S2S)6
Protocol. Un protocolo que
permite una transferencia de datos sencilla, eficiente y
segura.
Vamos a describir por encima algunos de los componentes
principales. En primer lugar, encontramos el servidor web
cuyo propósito principal es servir el UI y el API de Apache
NiFi.
Luego encontramos el Flow Controller que está considerado
como el centro de operaciones de la aplicación. Nos
proporciona subprocesos para que se ejecuten las extensiones
y además gestiona la planificación de ejecución.
Los FlowFiles que están siendo procesados por NiFi se
guardan en un mapa has en la memoria de la JVM haciendo
que sea muy eficiente su procesamiento, pero haciendo
necesario un mecanismo secundario para asegurar los datos.
Ante esta contingencia nace el Flow File Repository. Este
será el lugar donde se persista el seguimiento del estado de lo
que sabemos sobre un FlowFile dado que actualmente está en
activo en el flujo de datos. Desde el punto de vista técnico el
repositorio de FlowFile es un "Registro de escritura
anticipada" (o registro de datos) de los metadatos de cada
uno de los FlowFiles que existen actualmente en el sistema.
Estos metadatos de FlowFile incluyen todos los atributos
asociados con FlowFile, un puntero al contenido real del
FlowFile (que existe en el Content Repo) y el estado del
FlowFile, como a qué conexión/cola pertenece el FlowFile.
Esta escritura Ahead Log proporciona a NiFi la resistencia
que necesita para manejar reinicios y fallos inesperados del
sistema.
Al funcionar el Repositorio de FlowFile como un registro de
escritura anticipada, va registrando todos los cambios en el
repositorio antes de que suceda como una unidad de trabajo
transaccional. Esto permite que el sistema sepa exactamente
en qué paso se encuentra el nodo al procesar parte de los
datos. Si el nodo se apagará mientras procesa los datos, puede
restaurarse desde donde se detuvo7
.
El Content Repository será donde se almacenan los bytes de
contenido real de un FlowFile dado. El enfoque de diseño
predeterminado de este componente es sencillo. Almacena
los bloques de datos en el sistema de archivos. Debido a este
modo de funcionamiento, este componente puede presentar
una gran demanda de IO por lo tiene la posibilidad de
dividirse en varios volúmenes. Este repositorio utiliza los
paradigmas de inmutabilidad y de copia en escritura para
maximizar la velocidad y la seguridad de subprocesos. La
decisión de diseño central que influye en el Repo de
6
https://community.hortonworks.com/articles/88473/site-to-site-
communication-between-secured-https-a.html
7
El sistema toma automáticamente una instantánea, que crea una nueva
instantánea para cada FlowFile. El sistema calcula un nuevo punto de control
base al serializar cada FlowFile en el mapa hash y escribirlo en el disco con
el nombre de archivo ".partial". A medida que avanza el punto de control,
las nuevas líneas de base de FlowFile se escriben en el archivo ".partial".
Contenido es mantener el contenido del FlowFile en el disco
y leerlo solo en la memoria JVM cuando sea necesario. Esto
permite a NiFi manejar objetos de tamaño pequeño y masivo
sin requerir que los procesadores productores y
consumidores mantengan los objetos completos en la
memoria. Como resultado, acciones como dividir, agregar y
transformar objetos muy grandes son bastante fáciles de
hacer sin dañar la memoria.
Para terminar esta breve descripción encontramos el
Provenance Repository que es donde se almacenan todos los
datos de procedencia, de forma que nos permitirá analizar la
trazabilidad de un Flowfile. La implementación de este
componente es muy parecida a la del anterior, con la única
diferencia de que se le añaden las facultades de indexación8
y búsqueda.
Como curiosidad podemos decir que cada evento de
procedencia tiene dos mapas, uno para los atributos antes del
evento y otro para los valores de atributos actualizados. En
general, los eventos de procedencia no almacenan los valores
actualizados de los atributos como existían cuando se emitió
el evento, sino los valores de los atributos cuando se confirma
la sesión. Los elementos se almacenan en caché y se guardan
hasta que la sesión se confirma. Una vez que se confirma se
graban en disco de forma encriptada mediante AES G/CM.
Por último, enumeramos algunos subproyectos de Apache
NiFi que serán muy interesantes para las diferentes
implementaciones:
• Apache NiFi Registry. Una aplicación central
complementaría que proporciona una ubicación central
para el almacenamiento y la gestión de recursos
compartidos en una o más instancias de NiFi, como las
plantillas.
http://nifi.apache.org/registry.html
• MiNiFi. Un enfoque complementario de recopilación
de datos que completa los principio básicos de NiFi en
la gestión del flujo de datos, y se centra en la
recopilación de datos en la fuente de su creación.
http://nifi.apache.org/minifi/index.html
• Flow Design System (FDS). Una plataforma atómica
reutilizable para proporcionar un conjunto común de
componentes UI/UX para Apache NiFi, Apache
Registry, Apache NiFi minifi y cualquier otra
aplicación web de código abierto para consumir.
http://nifi.apache.org/fds.html
Una vez que se realiza el punto de control, el archivo "snapshot" anterior se
elimina y el archivo ".partial" cambia de nombre por "snapshot".
8
Tecnicamente el Provenance Repo es un índice de Lucene que se divide en
varios fragmentos ya que el número máximo de documentos adminitdos por
Lucene sin fragmentación es limitado.
pág. 5
II. INSTALACIÓN.
Podemos realizar la instalación de Apache NiFi de
diferentes formas. Directamente desde las fuentes,
descargándonos los binarios o mediante entornos
dockerizados. Encuadrándonos con el propósito de este
documento sólo me centraré en la instalación básica en un
entorno Linux estándar y la ejecución mediante un entorno
Docker.
A. Instalación en sistemas Linux.
Para llevar a cabo la instalación de Apache NiFi
necesitamos cumplir como requisito inicial, la instalación de
Java. En mi caso he optado por instalar esta paquetería:
~/nifi/$ sudo apt install default-jre
~/nifi/$ java --version
openjdk 10.0.2 2018-07-17
OpenJDK Runtime Environment (build 10.0.2+13-Ubuntu-
1ubuntu0.18.04.4)
OpenJDK 64-Bit Server VM (build 10.0.2+13-Ubuntu-
1ubuntu0.18.04.4, mixed mode)
sudo apt install default-jdk
~/nifi$ java --version
openjdk 10.0.2 2018-07-17
Una vez instalado este requisito nos descargaremos la versión
de NiFi que queremos instalar desde la siguiente página:
https://nifi.apache.org/download.html
En mi caso: nifi-1.8.0
~/nifi$ wget http://apache.rediris.es/nifi/1.8.0/nifi-1.8.0-
bin.tar.gz
~/nifi$ tar xvf nifi-1.8.0-bin.tar.gz
~/nifi$ cd nifi-1.8.0/
Una vez dentro de la carpeta que acabamos de descomprimir,
entramos en la carpeta bin y ejecutamos el script:
~/nifi/nifi-1.8.0/bin$ ./nifi.sh --help
Usage nifi {start|stop|run|restart|status|dump|install}
Para arrancar la instancia:
~/nifi/nifi-1.8.0/bin$ ./nifi.sh start
Comprobamos el estado del arranque:
~/nifi/nifi-1.8.0/bin$ ./nifi.sh status
nifi.sh: JAVA_HOME not set; results may vary
Java home:
NiFi home: /home/gauss/nifi/nifi-1.8.0
Bootstrap Config File: /home/gauss/nifi/nifi-
1.8.0/conf/bootstrap.conf
2019-01-07 16:56:33,519 INFO [main]
org.apache.nifi.bootstrap.Command Apache NiFi is currently
running, listening to Bootstrap on port 33979, PID=11172
También podemos comprobar que el proceso está en máquina
mediante $ ps -ef|grep nifi
9
En este caso amplio los límites para todos los usuarios pero lo normal sería
crear un usuario específico para levantar NiFi y aumentarle los límites sólo
a él.
Si todo está arrancado correctamente podemos comprobar
que NiFi está ejecutándose mediante el navegador,
accediendo a:
http://${IP_SERVER}:8080/nifi/
Ilustración 5 Pantalla Inicial de Apache NiFi.
De esta forma estamos levantando el servicio de forma
manual, si queremos instalar NiFi en nuestro sistema de
forma que nos implemente los servicios deberemos ejecutar
la siguiente opción:
~/nifi/nifi-1.8.0/bin$ ./nifi.sh install
Llegado a este punto tendríamos instalado NiFi, pero nos
faltaría optimizar algunos parámetros del sistema operativo
ya que no viene configurado para aplicaciones con un uso
intensivo de I/O como es el caso de Apache NiFi. Algunos
de los parámetros que debemos modificar son:
• Maximum File Hadles. NiFi puede necesitar abrir un
gran número de ficheros por los que necesitamos
incrementar los límites establecidos para los usuarios9
.
Para ello deberemos editar el “/etc/security/limits.conf” y
añadirle las siguientes líneas:
* hard nofile 50000
* soft nofile 50000
• Maximum Forked Processes. Tenemos que configurar
NiFi para que pueda generar un número elevado de
procesos. Para incrementar este límite, volvemos a
modificamos el fichero: “/etc/security/limits.conf”
* hard nproc 10000
* soft nproc 10000
En algunas distribuciones deberemos editar también el
fichero: “/etc/security/limits.d/90-nproc.conf “ en el que
deberemos añadir:
pág. 6
* soft nproc 10000
• Increase the number of TCP socket ports available. Esto
es particularmente importante si nuestro flujo de trabajo
abre y cierra muchos sockets en periodos cortos de
tiempo. Lo podemos modificar de la siguiente forma:
$ sudo sysctl -w net.ipv4.ip_local_port_range=”10000 65000”
O añadirlo de forma permanente en el /etc/sysctl.conf
• Set how long sockets stay in a TIMED_WAIT state
when closed. Si lo que queremos, es tener velocidad a la
hora de abrir y cerrar los sockets debemos modificar el
siguiente parámetro:
$ sudo sysctl -w
net.ipv4.netfilter.ip_conntrack_tcp_timeout_time_wait="1"
O añadirlo de forma permanente en el /etc/sysctl.conf
• Deshabilitar el uso de la swap. Para ello añadimos la
siguiente línea en el ‘/etc/sysctl.conf’:
vm.swappiness = 0
• Disable partition atime. En todas aquellas particiones en
las que funcione Apache Nifi, debemos deshabilitar
características como ‘atime10
’. Para ello deberemos editar
el fichero /etc/fstab y añadir ‘noatime’ en todas aquellas
particiones que se vean afectadas.
No me voy a extender más con los parámetros, pero en una
instalación real seguramente deberíamos optimizar alguno
más.
B. Ejecución desde Docker.
Para usar la imagen de Docker11
oficial bastará con ejecutar:
$ docker pull apache/nifi
Using default tag: latest
latest: Pulling from apache/nifi
Digest:
sha256:7a7586766ab9848d6b91f061b081748c9519075c3e41bcab7f501b8
bf4367cdf
Status: Image is up to date for apache/nifi:latest
Esto nos descargará a nuestro repositorio local la imagen de
apache NiFi. Lo podemos comprobar con:
$ docker images|grep nifi
apache/nifi latest 6c3cb8a4ae0e
2 months ago 1.83GB
Podemos encontrar el Dockerfile original y la documentación
en:
https://hub.docker.com/r/apache/nifi
10
“atime” es una propiedad del sistema de ficheros por la cual guarda el
“access time” cada vez que accedemos o leemos un fichero. Para evitar esto,
lo deshabilitamos mediante el uso de “noatime” optimizando
considerablemente el rendimiento del filesystem en determinados
escenarios.
Tenemos la opción de descargarnos el repo
(https://github.com/apache/nifi/tree/master/nifi-docker) con
el Dockerfile y crear la imagen mediante:
$ docker build -t apache/nifi:latest .
Esta imagen lleva incluido el toolkit de NiFi en la ruta
/opt/nifi/nifi-toolkit-current y la instalación del producto se
realiza en /opt/nifi/nifi-current . Podemos comprobar estas
rutas mediante:
$ docker run --rm --entrypoint /bin/bash apache/nifi -c
'env|grep NIFI'
NIFI_HOME=/opt/nifi/nifi-current
NIFI_LOG_DIR=/opt/nifi/nifi-current/logs
NIFI_TOOLKIT_HOME=/opt/nifi/nifi-toolkit-current
NIFI_PID_DIR=/opt/nifi/nifi-current/run
NIFI_BASE_DIR=/opt/nifi
Esta imagen la podemos ejecutar en modo standalone y
mediante dos métodos de autenticación12
:
• Two-Way SSL with Client Certificates.
• Lightweight Directory Access Protocol (LDAP)
Para levantar NiFi desde el docker bastará con ejecutar lo
siguiente:
$ docker run --name nifi -p 8080:8080 -d apache/nifi:latest
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED
STATUS PORTS NAMES
b35fad6a1380 apache/nifi:latest "../scripts/start.sh"
51 seconds ago Up 50 seconds 8443/tcp, 0.0.0.0:8080-
>8080/tcp, 10000/tcp nifi
Comprobamos que todo esta funcionando correctamente en
la url del producto: http://localhost:8080/nifi
Si queremos modificar alguna de las variables de arranque
podemos pasar variables a la imagen de la siguiente forma:
$ docker run --name nifi -p 9090:9090 -d -e
NIFI_WEB_HTTP_PORT='9090' apache/nifi:latest
39adbe525bdbed8ebc277e18910e31b3254758876c8a5c593940c55568cfb2
2f
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED
STATUS PORTS
NAMES
39adbe525bdb apache/nifi:latest "../scripts/start.sh"
4 seconds ago Up 3 seconds 8080/tcp, 8443/tcp,
10000/tcp, 0.0.0.0:9090->9090/tcp nifi
Podemos ver las variables disponibles e incluso añadir o
modificar en el fichero:
https://github.com/apache/nifi/blob/master/nifi-
docker/dockerhub/sh/start.sh
Si queremos usar sólo la parte de las Toolkit lo podemos
hacer mediante:
$ docker run -d --name nifi apache/nifi
$ docker exec -ti nifi /opt/nifi/nifi-toolkit-
current/bin/cli.sh nifi current-user
anonymous
11
Necesitamos tener instalado Docker en nuestra distribución.
12
https://hub.docker.com/r/apache/nifi
pág. 7
$ docker exec -ti nifi /opt/nifi/nifi-toolkit-current/bin/cli.sh
_ ___ _
Apache (_) .' ..](_) ,
_ .--. __ _| |_ __ )
[ `.-. | [ |'-| |-'[ | / 
| | | | | | | | | | ' '
[___||__][___][___] [___]', ,'
`'
CLI v1.8.0
Type 'help' to see a list of available commands, use tab to auto-
complete.
Session loaded from /home/nifi/.nifi-cli.config
#> exit
C. Archivos de configuración.
Llegado este punto ya podríamos tener levantado un
Apache NiFi así ahora nos vamos a centrar en examinar más
detenidamente sus ficheros de configuración.
Ilustración 6 Apache Nifi y sus ficheros de configuración. Basado
en: https://www.slideshare.net/IsheetaSanghi/apache-nifi-minifi-
meetup-slides?next_slideshow=1
1. conf/nifi.properties
Este es el archivo principal de configuración y se encuentra
dividido en diferentes secciones que contienen numerosas
variables pre-configuradas por defecto.
Se que es muy aburrido ver todas las variables de
configuración, pero me ha parecido interesante poner la
mayoría de las secciones para por lo menos verlas una vez.
# Core Properties #
nifi.flow.configuration.file=./conf/flow.xml.gz
nifi.flow.configuration.archive.enabled=true
nifi.flow.configuration.archive.dir=./conf/archive/
nifi.flow.configuration.archive.max.time=30 days
nifi.flow.configuration.archive.max.storage=500 MB
nifi.flow.configuration.archive.max.count=
nifi.flowcontroller.autoResumeState=true
nifi.flowcontroller.graceful.shutdown.period=10 sec
nifi.flowservice.writedelay.interval=500 ms
nifi.administrative.yield.duration=30 sec
# If a component has no work to do (is "bored"), how long should
we wait before checking again for work?
nifi.bored.yield.duration=10 millis
nifi.queue.backpressure.count=10000
nifi.queue.backpressure.size=1 GB
nifi.authorizer.configuration.file=./conf/authorizers.xml
nifi.login.identity.provider.configuration.file=./conf/login-
identity-providers.xml
nifi.templates.directory=./conf/templates
nifi.ui.banner.text=
nifi.ui.autorefresh.interval=30 sec
nifi.nar.library.directory=./lib
nifi.nar.working.directory=./work/nar/
nifi.documentation.working.directory=./work/docs/components
En este primer bloque encontramos algunos parámetros
interesantes como las configuraciones de las colas que
soportan las conexiones entre los procesadores. El
backpresure.count definir el número de mensajes capaz de
soportar hasta parar el procesador. Lo mismo para el
backpressure.size que definirá el tamaño máximo de la cola.
Manejar estos parámetros adecuadamente nos puede ayudar
a definir los intervalos de retención para nuestros flujos de
información.
nifi.queue.backpressure.count=10000
nifi.queue.backpressure.size=1 GB
Un parámetro muy interesante que afecta directamente al
rendimiento del funcionamiento de Apache NiFi es:
nifi.bored.yield.duration=10 millis
Este parámetro está diseñado para ayudar con el control de
uso de la CPU. Evita que los procesadores, que utilizan la
estrategia de programación controlada por temporizador,
utilicen de forma excesiva la CPU cuando no tienen trabajo
que realizar. El valor por defecto de 10 milisegundos ya tiene
un gran impacto en la reducción de la utilización de CPU. Si
nuestro flujo necesitará una menor latencia podremos bajar
este parámetro incrementando el uso de la CPU. Por el
contrario, si la latencia(controlada) no es un limitante
podemos aumentar este parámetro para reducir el uso de
CPU.
Otro parámetro interesante en esta sección afecta al impacto
del rendimiento del navegador:
nifi.ui.autorefresh.interval=30 sec
Esta propiedad establece el valor del tiempo de actualización
del navegador del cliente conectado. Podemos disminuir este
tiempo de actualización a costa de un mayor consumo de
procesamiento y un mayor ancho de banda. Deberemos tener
en cuenta el número de usuarios conectado ya que también
incrementa las necesidades de la aplicación. Apache NiFi
recomienda mantener el valor predeterminado y sólo
cambiarlo en entornos donde se necesiten ver estadísticas en
tiempo real. El usuario siempre tiene la opción de activar
manualmente la actualización.
# H2 Setting #
En esta sección se definen parámetros relacionados con las
bases de datos de uso interno.
nifi.database.directory=./database_repository
nifi.h2.url.append=;LOCK_TIMEOUT=25000;WRITE_DELAY=0;AUTO_SERV
ER=FALSE
NiFi usa dos bases de datos. Una para usuarios, donde realiza
un seguimiento de los logins en la aplicación simpre y cuando
estén habilitadas las opciones de login. Y una base de datos
de histórico donde se guardan los datos de los gráficos.
Normalmente no suelen ser bases de datos grandes.
La ruta de instalación predeterminada de estas bases de datos
suele ser <root-level-nifi-dir>/database_repository por lo
pág. 8
que el directorio se crea en el nivel raíz de la instalación de
NiFi (el mismo nivel que los directorios conf, bin, lib, etc.).
Si bien hay poco o ningún aumento de rendimiento al mover
esto a una nueva ubicación, se recomienda mover todos los
repositorios a una ubicación fuera de los directorios de
instalación de NiFi. Es poco probable que el usuario o las
bases de datos de historial cambien entre las versiones de
NiFi, por lo que moverlo fuera de la ruta de instalación básica
puede simplificar la actualización; permitiéndonos conservar
la información básica de usuario y el historial de
componentes después de la actualización.
# FlowFile Repository #
Aquí se definen los parámetros de configuración más
importantes del corazón de NiFi, el repositorio de FlowFiles.
En este repositorio es donde se mantiene el estado de todos
los FlowFiles actualmente ubicados en cualquier lugar de los
flujos de datos en la interfaz de usuario de NiFi. Si se
corrompe, existe la posibilidad de que podamos perder el
acceso a algunos o todos los archivos que corren por NiFi. La
causa más común de corrupción es el resultado de quedarse
sin espacio en el disco.
nifi.flowfile.repository.implementation=org.apache.nifi.contro
ller.repository.WriteAheadFlowFileRepository
nifi.flowfile.repository.wal.implementation=org.apache.nifi.wa
li.SequentialAccessWriteAheadLog
nifi.flowfile.repository.directory=./flowfile_repository
nifi.flowfile.repository.partitions=256
nifi.flowfile.repository.checkpoint.interval=2 mins
nifi.flowfile.repository.always.sync=false
nifi.swap.manager.implementation=org.apache.nifi.controller.Fi
leSystemSwapManager
nifi.queue.swap.threshold=20000
nifi.swap.in.period=5 sec
nifi.swap.in.threads=1
nifi.swap.out.period=5 sec
nifi.swap.out.threads=4
Vemos que la ruta por defecto es <root-level-nifi-dir>/
flowfile_repository.
Por temas de seguridad y rendimiento es recomendable que
este directorio se saque fuera de la instalación base donde
este soportado por un volumen con alto rendimiento de E/S.
En los sistemas de alto rendimiento, este repositorio nunca
debería estar con el repositorio de contenido que veremos en
las próximas secciones.
Otro parámetro a tener en cuenta de esta sección es el
siguiente:
nifi.queue.swap.threshold=20000
NiFi usa los FlowFiles como la unidad de transferencia de un
procesador a otro. Para que esto sea lo más rápido posible,
estos FlowFiles viven(felizmente) dentro de la RAM de la
JVM. Esta técnica es muy buena, hasta que comenzamos a
tener miles de FlowFiles y nuestra JVM comienza a sufrir por
falta de memoria. Para reducir la probabilidad de que esto
ocurra, NiFi define el umbral de FlowFiles que pueden vivir
en la memoria en una sola cola de conexión antes de ser
escritos en el disco. Una vez alcanzado el umbral se producirá
el intercambio a disco. Dependiendo de la frecuencia de
intercambio el rendimiento del sistema se puede ver afectado.
Para evitar esto deberemos encontrar el equilibrio entre este
umbral y la memoria disponible en la máquina virtual. Más
adelante veremos que las características de la máquina virtual
de java las configuraremos en el archivo bootstrap.conf.
# Content Repository #
Dado que el contenido para cada FlowFile que consume NiFi
se coloca dentro del repositorio de contenido, este directorio
soportará una gran demanda de I/O. Por esto, como en el caso
anterior se recomienda sacar esta ruta del directorio de
instalación básico.
nifi.content.repository.implementation=org.apache.nifi.control
ler.repository.FileSystemRepository
nifi.content.claim.max.appendable.size=1 MB
nifi.content.claim.max.flow.files=100
nifi.content.repository.directory.default=./content_repository
nifi.content.repository.archive.max.retention.period=12 hours
nifi.content.repository.archive.max.usage.percentage=50%
nifi.content.repository.archive.enabled=true
nifi.content.repository.always.sync=false
nifi.content.viewer.url=../nifi-content-viewer/
En ocasiones este repositorio puede ser muy demandante de
I/O por lo que un solo volumen puede ser escaso. Para
prevenir esto NiFi nos permitirá configurar múltiples
repositorios de contenido que puede usar de forma Road
Robin. La configuración de estos repositorios de contenido
adicional es relativamente sencilla. Deberemos comentar la
línea del contenedor default y añadir una nueva línea para
cada repositorio que queramos agregar, sustituyendo default
por el identificador único que queramos. Un ejemplo:
nifi.content.repository.directory.contS1R1=/cont-
repo1/content_repository
nifi.content.repository.directory.contS1R2=/cont-
repo2/content_repository
nifi.content.repository.directory.contS1R3=/cont-
repo3/content_repository
# Provenance Repository #
Esta sección hace referencia al repositorio de provenance y
será la última que trataremos. De forma similar al repositorio
de contenido, el repositorio de provenance puede usar una
gran cantidad de I/Os de disco para leer y escribir los eventos
de procedencia. También deberemos de tener en cuenta que
estas consultas de eventos se pueden hacer en paralelo por
diferentes usuarios por lo que necesitaremos un mayor
rendimiento de los discos.
La configuración predeterminada nos creará el repositorio de
provenance en la siguiente ruta:
nifi.provenance.repository.directory.default=./provenance_repo
sitory
Desde Apache NiFi nos recomiendan que este repositorio
este también es su propio volumen y que no lo comparta con
ninguno de los otros repositorios. Al igual que el repositorio
de contenido, se pueden definir múltiples repositorios de
provenance al proporcionar nombres únicos en lugar de
'default' y rutas:
nifi.provenance.repository.directory.provS1R1=/prov-
repo1/provenance_repository
pág. 9
nifi.provenance.repository.directory.provS1R2=/prov-
repo2/provenance_repository
La capacidad de consultar la información de procedencia de
los archivos suele tener un gran valor para ciertos tipos de
usuario. El número de subprocesos que están disponibles
para realizar estas consultas de procedencia se define en:
nifi.provenance.repository.query.threads = 2
En los sistemas en los que numerosos usuarios pueden
realizar consultas simultáneas en el repositorio de
procedencias, puede ser necesario aumentar el número de
subprocesos asignados a este proceso.
Si usamos a menudo esta característica puede ser interesante
modificar la cantidad de subprocesos que se usaran para
indexar los eventos de procedencia. El parámetro que
deberemos editar será:
nifi.provenance.repository.index.threads = 1
Para flujos que operan en un número muy alto de archivos de
flujo, la indexación de eventos de procedencia podría
convertirse en un cuello de botella. Si este es el caso,
aparecerá una notificación indicando: "La velocidad del flujo
de datos está excediendo la velocidad de registro de
procedencia. Disminuyendo la velocidad del flujo para
adaptarse". Si esto sucede, aumentar el valor de esta
propiedad puede aumentar la velocidad a la que el repositorio
de provenance puede procesar estos registros, lo que puede
resultar en una mejora del rendimiento general.
Otro parámetro que tenemos que tener en cuenta cuando
consultamos la procedencia es el tamaño del bloque
configurado ya que tiene impacto en la cantidad de
almacenamiento dinámico que se utilizará en el proceso. Esta
característica se configura en el siguiente parámetro:
nifi.provenance.repository.index.shard.size = 500 MB
Valores altos de este parámetro implicarán un mayor uso de
la pila de java pero proporcionará un mejor rendimiento. Si
aumentamos el tamaño del bloque, es posible que debamos
aumentar el tamaño de la memoria asignada a java. Por regla
general el tamaño de bloque debe ser más pequeño que el
50% del tamaño de almacenamiento configurado para el
repositorio de provenance que se configura en el siguiente
parámetro:
nifi.provenance.repository.max.storage.size
Para finalizar indicar que aunque este repositorio de
provenance no se puede desactivar, si podemos cambiar su
configuración de "PersistentProvenanceRepository" a
"VolatileProvenanceRepository" Esto provocará que toda la
información de referencia se almacenará en la memoria
asignada a la máquina virtual de java. Para evitar saturarla
podemos configurar el parámetro:
nifi.provenance.repository.buffer.size = 100000
13
Basado en: https://www.digitalocean.com/community/tutorials/how-to-
install-and-use-docker-on-ubuntu-18-04
Este valor se establece en bytes y mantendrá contenido el uso
de la memoria. Esta es una buena opción, pero tendremos un
historial de procedencia limitado.
En las nuevas implementaciones de Apache NiFi se está
implementando una nueva opción denominada
WriteAheadProvenanceRepository. Esta opción parece
mejorar los rendimientos para volúmenes altos de datos, pero
parece que actualmente presenta algunos problemas con la
reutilización de la memoria de la pila de java.
2. Archivo Bootstrap.conf
Este archivo de configuración nos permite configurar las
opciones de configuración inicial de NiFi. Esto incluye la
parametrización de java como el tamaño de la heap.
Este fichero también se divide en secciones.
# JVM memory settings #
java.arg.2=-Xms512m
java.arg.3=-Xmx512m
En esta sección controlamos la cantidad de memoria de
almacenamiento dinámico que puede utilizar la JVM de
Apache Nifi. Los parámetros básicos de configuración son
los que usamos normalmente en la configuración de java, por
un lado “Xms” definirá la asignación de memoria inicial y
“Xmx” la memoria máxima que podrá alcanzar la JVM.
Como podemos observar, los valores que vienen
configurados por defecto no son óptimos para entornos de
producción, por lo que los deberemos modificar en función
de nuestros recursos y necesidades. Valores que pueden ser
buenos para comenzar son de 4GB y 8GB respectivamente.
Un buen indicativo de que necesitamos tocar estos valores es
encontrar algún erro de “out of memory” en el log de la
aplicación de NiFi. Al aumentar el tamaño de esta memoria
tenemos que tener en cuenta los problemas de rendimiento
que podemos sufrir por el garbage collector por lo que se
recomienda realizar una configuración adecuada o utilizar un
garbage collector más eficiente.
III. EJEMPLO I.
Treas a realizar:
[1] Instalar docker y docker-compose.
[2] Levantar apache NiFi.
[3] Añadir y configurar los procesadores: GenerateFlowFile
y Putfile.
[4] Pruebas básicas de funcionamiento.
Para este primer ejemplo no vamos a ser muy originales y
vamos a ver un “hola mundo” en Apache Nifi. Para levantar
el entorno de pruebas usaremos una máquina virtual Ubuntu
(18.04) sobre la que levantaremos un Docker. La instalación
y optimización de Docker no es objeto de este documento por
lo que simplemente pondremos los comandos de instalación
sin explicación alguna13
:
$ sudo apt update
pág. 10
$ sudo apt install apt-transport-https ca-certificates curl
software-properties-common
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo
apt-key add –
$ sudo add-apt-repository "deb [arch=amd64] $
https://download.docker.com/linux/ubuntu bionic stable"
$ sudo apt update
$ sudo apt install docker-ce
$ sudo systemctl status Docker
$ sudo usermod -aG docker ${USER}14
Después de comprobar que docker funciona correctamente
pasamos a levantar nuestro entorno NiFi de pruebas. Para ello
simplemente ejecutaremos:
$ docker run --name nifi -p 8080:8080 -d apache/nifi:latest
Unable to find image 'apache/nifi:latest' locally
latest: Pulling from apache/nifi
bc9ab73e5b14: Pull complete
193a6306c92a: Pull complete
e5c3f8c317dc: Pull complete
d21441932c53: Pull complete
fa76b0d25092: Pull complete
346fd8610875: Pull complete
a77dac7d6f90: Pull complete
6907d655b86d: Pull complete
6b80dc86d1b8: Pull complete
2c6dbb557fc3: Pull complete
83ed9735618c: Pull complete
32697d3c6fd5: Pull complete
4ba9e676ab44: Pull complete
Digest:
sha256:7a7586766ab9848d6b91f061b081748c9519075c3e41bcab7f501b8
bf4367cdf
Status: Downloaded newer image for apache/nifi:latest
4ff09c12dd7564898cd46cd7d8c9e04dcf7d98b827afcb15098f23b3c9b7c3
79
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED
STATUS PORTS NAMES
1bf29337005f apache/nifi:latest "../scripts/start.sh"
4 seconds ago Up 3 seconds 8443/tcp, 0.0.0.0:8080-
>8080/tcp, 10000/tcp nifi
Podemos comprobar que NiFi está funcionando mediante el
navegador accediendo a localhost:8080/nifi ó
${IP_SERVER}:8080/nifi. También lo podemos comprobar
con un simple curl.
Ilustración 7 Consola inicial de Apache NiFi.
No vamos a explicar todas las opciones de la consola ya que
podemos encontrar toda la información necesaria en:
https://nifi.apache.org/docs.html
Una vez levantado nuestro bonito entorno de pruebas, vamos
a centrar un poco lo que queremos hacer. Crearemos un par
14
Esta parte es opcional y hace referencia a dar permisos de ejecución a un
usuario para ejecutar dockers. Normalmente funciona mejor poniendo
directamente el usuario y reiniciando la sesión.
de procesador, uno que nos generará FlowFiles a demanda y
otro que los recogerá y los escribirá en un fichero. Es un
ejemplo muy sencillo pero que nos servirá de base para
explicar algunos conceptos básicos.
Comenzaremos añadiendo nuestro primer procesador, para
ello debemos seleccionar el icono de
procesador y arrastrarlo hasta el panel
principal. En este momento nos
aparecerá una ventana emergente
donde nos aparecerán todos los procesadores que NiFi nos
ofrece por defecto (268). Podemos ampliar esta lista con
procesadores creados a medida mediante los ficheros .nar.
Ilustración 8 Ventana para añadir procesadores.
Para nuestro ejemplo, vamos a usar un procesador
denominado “GenerateFlowFile”. Para buscarlo podemos
usar el filtro de la parte superior derecha.
Ilustración 9 Ejempo1. selección de procesador.
Una vez seleccionado nos aparecerá nuestro primer
procesador. Indicar que el triángulo amarillo que nos aparece
es un indicador de que el procesador no está configurado
correctamente.
Ilustración 10 Ejemplo 1. Primer procesador añadido.
pág. 11
Para ver las operatorios que podemos realizar sobre el
procesador bastará con pulsar con botón derecho sobre el
mismo:
Ilustración 11 Ejemplo 1. Menu configuración procesador.
Seleccionamos la opción de configure y accederemos a la
parte de configuración del procesador.
Vamos a ir explicando un poco las diferentes secciones y a la
vez configurando nuestro nuevo procesador:
• Configuración (Settings). Esta pestaña nos permitirá
renombrar el procesador y cambiar las configuraciones de
las relaciones de terminación automática. Si un
procesador permite que se creen relaciones definidas por
el usuario (como RouteOnAttribute), también nos
aparecerían aquí después de crearse. Otras
configuraciones que podremos hacer hacen referencia al
rendimiento, duración y el manejo de reintentos.
Ilustración 12 Configure Processor. Settings.
En este parte sólo marcaremos el check de success para
definir la terminación de la relación.
• Planificación (Scheduling). NiFi proporciona varias
posibilidades de planificación para los procesadores. Para
la mayoría de los casos, el temporizador suele ser la
estrategia más apropiada, aunque podremos utilizar otras
como la basada en eventos. Deberemos tener en cuenta
los problemas de rendimiento de las diferentes
configuraciones. En esta misma pestaña también
podremos configurar el número de procesos adicionales
que puede usar el procesador.
Ilustración 13 Configure Processor. Scheduling.
Dejamos todo por defecto menos el tiempo de
planificación que lo pasamos a 5 segundos.
• Propiedades (Properties). En este apartado configuramos
las propiedades del procesador. En muchos casos
tendremos numerosas variables por defecto que
podremos configurar a las que les podemos añadir
aquellas que creamos necesarias.
En este caso vamos a modificar el tamaño del FlowFile
generado a 5kb y le vamos a añadir un texto customizado,
“Hola Mundo!!!!!!!!!”.
Ilustración 14 Configure Processor. Properties.
Podemos observar que una vez configurado el procesador
el icono del triángulo pasa a un cuadrado rojo indicando
que el procesador está parado.
• Comentarios (Comments). Nos permite añadir
comentarios sobre los procesadores para documentar un
poco el sentido del procesador en el flujo que ejecutamos.
Una vez configurado nuestro primer procesador pasamos al
segundo que será “PutFile” que nos permitirá escribir los
FlowFiles generados con anterioridad a fichero. Como en el
caso anterior accedemos a la configuración y modificamos el
apartado de settings en el que marcaremos los checkbox de
failure y success. Luego pasaremos a las Property y
simplemente añadiremos el directorio de destino (tmp).
pág. 12
Ilustración 15 ejemplo 1. PutFile processor. Propiedades.
Una vez configurado vamos a crear nuestra primera
conexión. Para ello nos ponemos encima del primer
procesador creado y nos aparecerá una flecha que
seleccionamos y arrastramos hasta el segundo procesador. En
ese momento nos aparecerá un cuadro de configuración
donde podremos definir cómo se va a gestionar la asociación
que acabamos de crear. Dejando de lado en la pestaña de
‘Details’ pasamos a ‘settings’ que es la realmente interesante.
Ilustración 16 Ejemplo 1. Propiedades conexión.
En este apartado encontraremos los siguientes parámetros de
configuración:
• Name. Nombre de la conexión.
• FlowFile Expiration. El tiempo máximo que el FlowFile
puede permanecer en la cola antes de ser eliminado.
• Back Pressure. Número máximo de objetos que pueden
ser almacenados en la cola antes de que el back pressure
comience a aplicarse.
• Size Threshold. Tamaño máximo de la cola.
• Load Balance Strategy. Como balancear los datos de esta
conexión en los nodos del clúster de NiFi. Las opciones
pueden ser:
o Do not load balance.
o Partition by attribute.
o Round robin.
o Single node.
• Prioritizers. Definimos el modo de selección de los
FlowFile de esta cola. Las opciones son las siguientes:
Este es nuestro primer ejemplo así que lo dejaremos todo por
defecto. Aunque en desarrollos más complejos puede ser
interesante estudiar estas configuraciones.
Después de esta sencilla configuración ya tenemos nuestro
primer flujo de datos implementado. Ahora podremos
ejecutarlo de forma secuencial o total desde el panel de
operación.
Ilustración 17 Panel de operación.
Ilustración 18 Ejemplo I.
Para esta primera prueba recomiendo lanzarlo de forma
secuencial para poder ir viendo lo que pasa en cada punto de
nuestro flujo. Comenzaremos lanzando el primer
procesador(GenerateFlowFile). El refresh está configura a 30
segundos así que si queremos ver como se están generando
los ficheros lo podremos hacer con botón derecho actualizar.
Veremos cómo los mensajes se nos están acumulando en la
cola de la conexión y no sólo eso, con botón derecho vemos
que nos aparecen opciones interesantes sobre esta cola:
pág. 13
Ilustración 19 Opciones de la cola.
Tendremos la opción de vaciar la cola, ver los históricos de
utilización de esta e incluso listar y ver los mensajes de la
misma. Para ello seleccionamos lo opción de “List queque”.
Ilustración 20 Listando el contenido de la cola.
Aunque en la imagen no se ve correctamente tenemos dos
botones muy interesantes. Uno al inicio que nos dará acceso
a los datos del FlowFile:
Ilustración 21 Visualización de contenido de una cola.
Esta es una funcionalidad muy interesante y nos puede
ayudar mucho a saber que está pasando en nuestro flujo de
datos.
El otro icono interesante lo encontramos al final y nos dará
acceso a los datos de procedencia. En este caso es muy
simple:
Ilustración 22 Esquema de procedencia.
Vamos a continuar con el ejemplo, arrancando todos los
procesadores y comprobando que los ficheros se están
creando en el tmp.
Ilustración 23 Ejemplo en ejecución.
Para comprobar si se están creando los ficheros, deberemos
entrar en la consola del Docker:
gauss@gauss-virtual-machine:~/NIFI/EJEMPLOS/Hola_mundo/tmp$
docker ps -a
CONTAINER ID IMAGE COMMAND CREATED
STATUS PORTS NAMES
1bf29337005f apache/nifi:latest "../scripts/start.sh"
About an hour ago Up About an hour 8443/tcp, 0.0.0.0:8080-
>8080/tcp, 10000/tcp nifi
gauss@gauss-virtual-machine:~/NIFI/EJEMPLOS/Hola_mundo/tmp$
docker exec -i -t 1bf29337005f /bin/bash
nifi@1bf29337005f:/opt/nifi/nifi-current$
pág. 14
Una vez dentro nos vamos al directorio tmp y hacemos la
comprobación.
nifi@1bf29337005f:~$ cd /tmp/
nifi@1bf29337005f:/tmp$ ls
06cf354e-e067-4662-805b-e28627110b9d 2566dc4f-d19a-4ee7-9af1-
818f019b7641 551cbc7f-942a-4c1a-91db-98acb58aa97f 91fa4985-
b009-48ca-9716-c29ccd21b137 d46eebe1-c6ae-44e1-b569-
ea96848128d9
0754dfb5-d5a6-4c8c-8547-3ed5b9d70116 269f0d91-57f0-46ba-8e46-
c0084761e49b 5f44c5b2-c61f-4f52-b541-4f6dce0b16fd 95ffa794-
fc21-4937-8583-cd23c9e81a98 dbac411a-4825-47e9-89e5-
6f3a10f0a387
088e4f25-6536-40d7-9781-c6e40caabfa0 27e7702a-aecf-46a2-aee0-
d02c19f6b711 6ee250c2-7e9e-4570-a858-932a1eed3de0
…………………………………………….
nifi@1bf29337005f:/tmp$ cat 06cf354e-e067-4662-805b-
e28627110b9d
Hola Mundo!!!!!!!!nifi@1bf29337005f:/tmp$
Viendo que todo funciona correctamente podemos parar los
procesadores.
Antes de terminar este ejemplo vamos a ver cómo podemos
exportar estos flujos e importarlos. Para ello bastará con que
en la sección de operación seleccionemos el icono que
contiene un disco (Create template).
Nos aparecerá un pequeño cuadro en el que sólo nos piden el
nombre y una pequeña descripción. Con eso creamos nuestro
primer template. Si lo queremos descargar deberemos ir al
menú de configuración general y seleccionar la opción de
templates.
Ilustración 24 Opciones generales.
Ilustración 25 NiFi Templates.
El botón de la derecha nos permitirá descargarnos el template
en formato xml. Este fichero podría/debería ser guardado en
el repositorio de código correspondiente.
Para volverlo a cargar bastará con que seleccionemos la
opción de upload template de la consola de operate.
Finalmente desplegar un template se realiza desde el menú
de los procesadores.
Este ha sido un ejemplo sencillo, pero nos ha valido para
explicar algunos de los modos de funcionamiento de NiFi y
sobre todo familiarizarnos con en el entorno.
Este ejemplo y todos los demas estan disponibles en el
sigueinte repositorio de githup:
https://github.com/vthot4/poc_nifi
IV. EJEMPLO II.
Treas a realizar:
[1] Levantar infraestructura necesaria medainte el docker-
compose.
[2] Añadir y configurar los procesadores necesarios
[3] Pruebas básicas de funcionamiento.
En este ejemplo vamos a ver una integración sencilla
compuesta de los siguientes componentes:
Ilustración 26 Integración Twitter, Apache Kafka, MongoDB.
pág. 15
La prueba constará de una simple ingesta de datos desde
Twitter mediante un procesador de NiFi que nos permitirá
tratar e insertar esos datos en una cola de Kafka para que
finalmente sean escritos en MongoDB o en raw en un
filesystem. La idea es ver de forma general cómo funcionan
los diferentes componentes de NiFi y sobre todo probar el
control que nos ofrece sobre los flujos de datos de la prueba.
Primeramente, necesitamos levantar los diferentes
componentes, para ello hemos creado un simple Docker-
compose que nos permita levantar el entorno de forma ágil y
sencilla.
Si no tenemos instalado docker-compose en nuestro sistema
lo podemos hacer de la siguiente forma:
$ sudo curl -L
"https://github.com/docker/compose/releases/download/1.23.2/do
cker-compose-$(uname -s)-$(uname -m)" -o
/usr/local/bin/docker-compose
$ sudo chmod +x /usr/local/bin/docker-compose
$ docker-compose --version
docker-compose version 1.23.2, build 1110ad01
El docker-compose que hemos creado para la prueba es el
siguiente:
---
version: '3.1'
## Component: PoC Nifi Ejemplo: Twitter-Kafka-MongoDB
## Version: 0.2
## Author: Versia Tecnologías Emergentes
##
networks:
labnet:
driver: bridge
services:
mongo:
image: mongo
container_name: Poc_nifi_mongodb
restart: always
ports:
- "27017:27017"
#environment:
#MONGO_INITDB_ROOT_USERNAME: root
#MONGO_INITDB_ROOT_PASSWORD:
networks:
- labnet
mongo-express:
image: mongo-express
container_name: Poc_nifi_mongo_express
restart: always
ports:
- "8081:8081"
environment:
#ME_CONFIG_MONGODB_ADMINUSERNAME: root
#ME_CINFIG_MONGODB_ADMINPASSWORD:
ME_CONFIG_BASICAUTH_USERNAME: admin
ME_CONFIG_BASICAUTH_PASSWORD: admin
depends_on:
- mongo
networks:
- labnet
zookeeper:
image: confluentinc/cp-zookeeper:latest
container_name: Poc_nifi_zookeeper
environment:
ZOOKEEPER_CLIENT_PORT: 2181
ZOOKEEPER_TICK_TIME: 2000
networks:
- labnet
kafka:
image: confluentinc/cp-kafka:latest
container_name: Poc_nifi_kafka
depends_on:
- zookeeper
ports:
- "9092:9092"
environment:
KAFKA_BROKER_ID: 1
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
KAFKA_ADVERTISED_LISTENERS:
PLAINTEXT://kafka:29092,PLAINTEXT_HOST://kafka:9092
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP:
PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT
KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
networks:
- labnet
nifi:
image: apache/nifi
container_name: Poc_nifi_nifi
ports:
- "8080:8080"
environment:
- NIFI_WEB_HTTP_PORT=8080
networks:
- labnet
Para levantar el entorno de pruebas bastará con ejecutar:
$ docker-compose up -d
Creating network "twitter_kafka_mongodb_labnet" with driver
"bridge"
Creating Poc_nifi_mongodb ... done
Creating Poc_nifi_zookeeper ... done
Creating Poc_nifi_nifi ... done
Creating Poc_nifi_mongo_express ... done
Creating Poc_nifi_kafka ... done
Podemos comprobar que todo esta levantado correctamente
mediante:
$ docker-compose -f docker-compose.yml ps
Name Command State
Ports
--------------------------------------------------------------
-----------------------------------------------
Poc_nifi_kafka /etc/confluent/docker/run Up
0.0.0.0:9092->9092/tcp
Poc_nifi_mongo_express tini -- /docker-entrypoint ... Up
0.0.0.0:8081->8081/tcp
Poc_nifi_mongodb docker-entrypoint.sh mongod Up
0.0.0.0:27017->27017/tcp
Poc_nifi_nifi ../scripts/start.sh Up
10000/tcp, 0.0.0.0:8080->8080/tcp, 8443/tcp
Poc_nifi_zookeeper /etc/confluent/docker/run Up
2181/tcp, 2888/tcp, 3888/tcp
Si quisiéramos ver más información de los procesos
levantados podríamos usar $ Docker-compose top .
En caso de que nos fallara alguno de los Dockers veríamos
los logs mediante:
$ docker-compose logs
$ docker-compose logs -f $Service
Una vez que tenemos levantado el entorno, accedemos a
nuestro Apache NiFi, mediante:
http://localhost:8080
Para cargar nuestro ejemplo, usaremos lo aprendido en el
ejemplo anterior e importaremos el template y luego lo
desplegaremos: Twitter-kafka-MongoDB.xml
Una vez importado tendremos algo parecido a esto:
pág. 16
Vamos a ir poco a poco viendo como funciona cada uno de
los componentes.
Comenzaremos con el procesador de Twitter que nos
permitirá realizar una recogida selectiva de datos desde
Twitter. Lo hemos seleccionado porque lo hemos
considerado una fuente rápida y sencilla de datos.
Para configurar este procesador necesitaremos dar de alta una
aplicación en Twitter para conseguir los tokens de acceso
necesarios. Deberemos ir a:
https://developer.twitter.com
Y loguearnos con nuestro usuario de Twitter y crear una
nueva app15
. Una vez creada tendremos algo como esto:
La parte que necesitamos la encontraremos en la pestaña de
“Keys and tokens”.
15
No voy a explicar como crear la app porque no es objeto de este
documento. Un ejemplo de guía puede ser: https://iag.me/socialmedia/how-
to-create-a-twitter-app-in-8-easy-steps/
Ilustración 28 Sección "Key and tokens" de Twitter app.
Teniendo estos datos, la configuración quedaría de la
siguiente forma:
Ilustración 29 Twitter Processor. Settings.
Ilustración 30 Twitter Processor. Scheduling.
Ilustración 31 Twitter Processor. Properties.
Ilustración 27 Flujo general Twitter-Kafka-MongoDB.
pág. 17
Las propiedades a configurar son:
• Twitter Endpoint. Podemos recoger todos los datos o
filtrados por termino o ID de usuario. En mi caso
seleccionamos “Filter Endpoint” para poder filtrar por un
termino en concreto.
• Datos proporcionados por la App de Twitter.
o Cosumer key.
o Consumer Secret.
o Access Token.
o Access Token Secret.
• Languages. Idoma de los tweets que vamos a recoger. En
mi caso “en”.
• Terms to Filter On. Enumeración separada por comas de
los términos que deseamos filtrar. En mi caso
“blockchain”.
Una vez configurado podemos comprobar que recoge datos
de forma correcta, seleccionando el procesador, botón
derecho y “Strart”.
Ilustración 32 Twitter Processor funcionando.
Vemos como el procesador se ha conectado correctamente y
ha traído 90 mensajes y los ha enrutado a sus dos salidas. Una
que simplemente nos escribirá los tweets en fichero y otra
más compleja que tratará los datos los colocará en Kafka y
luego los escribirá en MongoDB.
Podemos comprobar el contenido de los flowfiles en las
conexiones.
Nos aparecerá toda la lista de flowfiles y podremos ver el
contenido de alguno de ellos mediante la “i” de la izquierda.
Comprobamos que tenemos todo el contenido y que ha
filtrado correctamente por blockchain.
Ilustración 33 Ejemplo de tweet incrustado en un flowfile.
Vamos a comenzar con el flujo más sencillo y vamos a ver
como escribe estos FlowFiles en ficheros. Para ello vamos al
procesador “Put Raw File” y vemos un poco su
configuración.
Ilustración 34 Put Raw File processor. Settings.
Ilustración 35 Put Raw File. Scheduling.
Ilustración 36 Put Raw File. Properties
Para comprobar que toda ha ido bien, tendremos que
comprobarlo en el Docker de NiFi.
$ docker exec -i -t f9396945d85b /bin/bash
nifi@f9396945d85b:/opt/nifi/nifi-current$ cd /tmp/ejemplo_raw/
pág. 18
nifi@f9396945d85b:/tmp/ejemplo_raw$ ls
051a7cd6-8494-4b54-b23a-fccdee7c6ca7.json 471730f4-b9d3-41ac-
ad10-2f480be4e361.json 82c75310-9bc5-4ee1-8331-
52d83ad78c19.json be41f09b-ee5e-4a4a-9160-3f08b0601c0b.json
nifi@f9396945d85b:/tmp/ejemplo_raw$ cat 051a7cd6-8494-4b54-
b23a-fccdee7c6ca7.json
{"created_at":"Tue Jan 22 12:46:41 +0000
2019","id":1087693030004613120,"id_str":"1087693030004613120",
"text":"RT @aoife_keady: Advice on buying Blockchain from John
Biggs. ud83dude48 He bought some. Then with all the hype they
were worth more money and thenu2026","source":"u003ca
href="http://twitter.com" rel="nofollow"u003eTwitter Web
Clientu003c/au003e","truncated":false,"in_reply_to_status_i
d":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id"
:null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name"
:null,"user":{"id":3574988954,"id_str":"3574988954","name":"Em
ily
…………..
Ahora vamos a ver la segunda parte del flujo en la llevaremos
los datos hasta kafka y luego los insertaremos en MongoDB.
Ilustración 37 Flujo de inserción en Kafka y MongoDB.
El primer procesador que nos encontramos en este flujo será
el EvaluateJsonPath
Ilustración 38 EvaluateJsonPath Processor.
Añadiremos dos nuevas propiedades relacionadas con los
campos text y lang del JSON. En la parte superior derecha
pulsaremos el botón “New property”, asignando el nombre
“twitter.lang” y su valor “$.lang” a la nueva propiedad. Y, de
nuevo, los mismo pero para “twitter.text” con el valor
“$.text”.
En la pestaña “Settings” activaremos dos de los tres flasg que
se encuentran en la derecha: “failure” y “unmatched”.
Ilustración 39 EvaluateJsonPath Processor. Settings.
Ilustración 40 EvaluateJsonPath Processor. Scheduling.
Ilustración 41. EvaluateJsonPath Processor. Properties.
Ilustración 42 RouteOnAttribute Processor.
No hemos terminado todavía, nos falta añadir la relación
“matched” para el procesador “EvaluateJsonPath” para ello
añadiremos un nuevo procesador. Aunque en esta ocasión
filtraremos por “route” y seleccionando la opción
“RouteOnAttribute”. Añadiremos (Add).
Una vez creado el procesador, vamos a configurarlo (como
los anteriores). Le asignaremos un nombre si queremos y
activamos el flag “unmatched” de la parte derecha.
Ya en “Properties” añadimos una “New property”, le
ponemos un nombre y añadimos el valor:
pág. 19
“${twitter.text:isEmpty():not():and(${twitter.lang:equals(“e
s”)})}“
Con esto conseguimos filtrar aquellos tweets que estén vacíos
y cuyo idioma no haya sido marcado como español.
Añadimos (Add) y Aplicamos (Apply).
Si bien es cierto, este último paso también lo hubiésemos
podido realizar al principio, en el momento de configurar el
procesador “getTweets”.
Ya casi como último paso, procederemos a conectar el
procesador “EvaluateJsonPath” con el de
“RouteOnAttribute”. Ya en la nueva ventana, en la pestaña
“Details” tendremos la opción “For relationships”.
Activaremos el flag “matched”. En la pestaña “Settings”
volveremos a indicar la política que queremos aplicar, será la
misma que en el caso anterior: “FirstInFirstOutPrioritizer”
y Añadiremos (Add).
Ilustración 43 RouteOnAttribute Processor. Settings.
Ilustración 44 RouteOnAttribute Processor. Scheduling.
Ilustración 45 RouteOnAttribute Processor. Properties.
${twitter.text:isEmpty():not():and(${twitter.lang:equals("en
")})}
Una vez que tenemos enrutados los FlowFiles solo nos falta
configurar la inserción de los mensajes en una topic de Kafka
y de ahí lo persistiremos en la base de datos Mongo. Para ello
usaremos los procesadores: PutKafka y PutMongo, que
consifuramos como mostramos a continuación:
Ilustración 46 Inserción en kafka y en MongoDB.
Las variables a configurar en el procesador de PutKafka son
bastante sencillas:
Known Brokers: kafka:9092
Topic Name: TopicTweets
Client Name: PoC
Ilustración 47 PutKafka Processor. Properties.
Después de configurar este procesador pasamos a configurar
PutMongo, cuya configuración es bastante sencilla también.
Mongo URI: mongodb://mongo:27017
Mongo Database Name: Poc_Twitter
Mongo Collection Name: Messages
pág. 20
Ilustración 48 PutMongo Processor. Settings.
Ilustración 49 PutMongo Processor. Properties.
Una vez que hemos resuelto todas las conexiones podremos
probar nuestro flujo. Para comprobar que todo esta
funcionando correctamente a la hora de insertar los datos en
la base de datos hemos añadadido mongo_express a nuestro
docker-compose. Podemos dirigirnos a nuestro navegador y
acceder a la url:
http://localhost:8081 (admin/admin)
Nos aparecerá el explorador de la base de datos MongoDB.
Ilustración 50 MongoDB Express.
Comprobamos que los datos se están guardando
correctamente.
Ilustración 51 Ejemplo de tweet insertado en MongoDB.
Para terminar nuestra prueba vamos a añadir una segunda
rama que colgara desde el procesador de “RuteOnAttribute”
donde haremos un pequeño procesado de los datos y los
volveremos a insertar en el circuito Kafka-MongoDB. La
nueva rama presentará esta forma:
Ilustración 52 Flojo de inserción de tweets procesados.
Una vez enrutados los FlowFiles pasan al procesador
JoltTransformJSON que nos permitirá aplica una lista de
especificaciones Jolt a la carga útil JSON del archivo de
flujo. Se crea un nuevo FlowFile con contenido transformado
y se enruta a la relación de "éxito". Si la transformación
JSON falla, el FlowFile original se enruta a la relación 'falla'.
Para configurar este procesador bastará con introducir las
especificaciones Jolt.
Ilustración 53 JoltTransformJSON Processor. Properties.
Jolt Specification:
[{
"operation": "shift",
"spec": {
"created_at": "created_date_time",
"id": "tweet_id",
"text": "tweet_text",
"user": {
"id": "user_id"
}
}
},
{
"operation": "default",
"spec":{
pág. 21
"chainr-rating" : 4
}
}
]
Este procesador nos proporciona acceso al uso de Jolt16
. Esta
librería nos ofrece un enfoque declarativo para definir la
salida JSON. Jolt proporciona proporciona un conjunto de
tipos de transformación, cada uno con su propio DSL, que
define la nueva estructura para los datos JSON salientes.
Una vez transformados los FlowFiles pasan a entrar de nuevo
al circuito Kafka-MongoDB. En las imágenes podemos ver
que las configuraciones son muy parecidas que en la caso
anterior. Simplemente cambiamos el nombre de la Topic
Name a “TopoicTweets_Pro” y el nombre de la colección en
la que insertaremos los datos a “Message_Pro”.
Ilustración 54 PutKafka processor. Properties.
Ilustración 55 PutMongo Processor. Properties.
Si comprobamos de nuevo el formato del json introdocido en
la base de datos, comprobamos que presentan el formato
especificado en las especificaciones de Jolt.
16
https://github.com/bazaarvoice/jolt
Ilustración 56 Ejemplo de tweet procesado insertado en
MongoDB.
V. EJEMPLO III.
En este ejemplo cogeremos la base del ejemplo anterior e
insertaremos los datos en Elasticsearch. Como, ya
deberíamos haber cogido un poco de soltura con el entorno
vamos a poner sólo los esquemas fundamentales.
Ilustración 57 Esquema general EJEMPLO III.
Treas a realizar:
[1] Levantar infraestructura necesaria medainte el docker-
compose.
[2] Configurar el JSON obtenido de Twitter y enrutarlo.
[3] Guardar los JSON en Elasticsearch.
[4] Ver los resultados en Kibana.
Primeramente deberemos levantar nuestro entorno de
pruebas mediante el dockerfile disponible en el repositorio17
.
Antes de poder lanzar este docker-file deberemos
asegurarnos de que en nuestra máquina tenemos configurado
el siguiente parámetro:
$ sudo sysctl -w vm.max_map_count=262144
17
En el ejemplo se levanta con un nginx que nor redirige al Kibana. En
nuestro entorno lo podríamos omitir y simplemente atacar directamente al
kibana.
pág. 22
Sin este parámetro el clúster de elasticsearch no levanta
correctamente.
El docker-file que usaremos para la prueba es el siguiente:
---
version: '3.1'
## Component: Elasticsearch-kibana
## Version: 0.1
## Author: Versia Tecnologías Emergentes
##
networks:
labnet:
services:
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:6.5.4
container_name: elasticsearch
environment:
- cluster.name=docker-cluster
- bootstrap.memory_lock=true
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
ulimits:
memlock:
soft: -1
hard: -1
volumes:
- esdata1:/usr/share/elasticsearch/data
ports:
- 9200:9200
networks:
- labnet
elasticsearch2:
image: docker.elastic.co/elasticsearch/elasticsearch:6.5.4
container_name: elasticsearch2
environment:
- cluster.name=docker-cluster
- bootstrap.memory_lock=true
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
- "discovery.zen.ping.unicast.hosts=elasticsearch"
ulimits:
memlock:
soft: -1
hard: -1
volumes:
- esdata2:/usr/share/elasticsearch/data
networks:
- labnet
elasticsearch3:
image: docker.elastic.co/elasticsearch/elasticsearch:6.5.4
container_name: elasticsearch3
environment:
- cluster.name=docker-cluster
- bootstrap.memory_lock=true
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
- "discovery.zen.ping.unicast.hosts=elasticsearch"
ulimits:
memlock:
soft: -1
hard: -1
volumes:
- esdata3:/usr/share/elasticsearch/data
networks:
- labnet
kibana:
image: docker.elastic.co/kibana/kibana-oss:6.5.4
container_name: kibana
environment:
SERVER_NAME: localhost
ELASTICSEARCH_URL: http://elasticsearch:9200/
ports:
- 5601:5601
ulimits:
nproc: 65535
memlock:
soft: -1
hard: -1
networks:
- labnet
nginx:
image: nginx:latest
ports:
- 8090:80
volumes:
- ${PWD}/nginx-conf/:/etc/nginx/conf.d/
command: /bin/bash -c "nginx -g 'daemon off;'"
ulimits:
nproc: 65535
networks:
- labnet
nifi:
image: apache/nifi
container_name: Poc_nifi_nifi
ports:
- "8080:8080"
environment:
- NIFI_WEB_HTTP_PORT=8080
networks:
- labnet
volumes:
esdata1:
driver: local
esdata2:
driver: local
esdata3:
driver: local
Nota: No sería necesario levantar el cluster de elasticsearch,
para la prueba valdía con un entorno simple. Lo podríamos
levantar de la siguiente forma:
$ docker run -d --name elastic -p 9200:9200 -p 9300:9300
elasticsearch
Ó
$ docker run -p 9200:9200 -p 9300:9300 -e
"discovery.type=single-node"
docker.elastic.co/elasticsearch/elasticsearch:6.5.4
$ docker run -d --name kibana -p 5601:5601 -e
ELASTICSEARCH_URL=http://IP-HOST-DOCKER-ELASTIC:9200 kibana
$ sudo docker run -d --name nifi -p 8080:8080 apache/nifi
Para levantar la infraestructura necesaria bastará con ejecutar
$ docker-compose up -d
Creating network "twitter_elasticsearch_labnet" with the default
driver
Creating volume "twitter_elasticsearch_esdata1" with local
driver
Creating volume "twitter_elasticsearch_esdata2" with local
driver
Creating volume "twitter_elasticsearch_esdata3" with local
driver
Creating twitter_elasticsearch_nginx_1 ... done
Creating elasticsearch ... done
Creating Poc_nifi_nifi ... done
Creating elasticsearch3 ... done
Creating kibana ... done
Creating elasticsearch2 ... done
Comprobamos que todo esta levantado correctamente de la
siguiente forma:
$ docker-compose ps
Name Command State
Ports
--------------------------------------------------------------
------------------------------------------------------
Poc_nifi_nifi ../scripts/start.sh Up
10000/tcp, 0.0.0.0:8080->8080/tcp, 8443/tcp
elasticsearch /usr/local/bin/docker-entr ...
Up 0.0.0.0:9200->9200/tcp, 9300/tcp
elasticsearch2 /usr/local/bin/docker-entr ...
Up 9200/tcp, 9300/tcp
elasticsearch3 /usr/local/bin/docker-entr ...
Up 9200/tcp, 9300/tcp
kibana /usr/local/bin/kibana-docker
Up 0.0.0.0:5601->5601/tcp
twitter_elasticsearch_nginx_1 /bin/bash -c nginx -g 'dae ...
Up 0.0.0.0:8090->80/tcp
pág. 23
Podemos comprobar que Elasticsearch esta levantado con
una simple prueba:
$ curl localhost:9200
{
"name" : "B931ITV",
"cluster_name" : "docker-cluster",
"cluster_uuid" : "oqR1Y2uXRxichyUoLx9m_A",
"version" : {
"number" : "6.5.4",
"build_flavor" : "default",
"build_type" : "tar",
"build_hash" : "d2ef93d",
"build_date" : "2018-12-17T21:17:40.758843Z",
"build_snapshot" : false,
"lucene_version" : "7.5.0",
"minimum_wire_compatibility_version" : "5.6.0",
"minimum_index_compatibility_version" : "5.0.0"
},
"tagline" : "You Know, for Search"
}
Y comprobamos que Kibana esta levantado mediante:
http://localhost:5601
Ilustración 58 Pantalla incial de Kibana.
Finalmente nos conectamos a la consola de Apache Nifi e
importamos el template “Twitter-Elasticsearch.xml”.
Una vez importado, lo
desplegamos de forma que nos
deberían de aparecer todos los
procesadores ya configurados. Lo
único que nos quedará por
establecer serán las claves de
acceso a Twitter.
Ilustración 59 template Ejemplo III.
Respecto a los ejemplos anteriores el único procesador nuevo
que aparece es “PutElasticsearchHttp” que nos permitirá
insertar los datos en Elasticsearch de forma sencilla.
Ilustración 60 PutElasticsearchHttp processor.
Deberemos establecer las siguientes propiedades:
• Elasticsearch URL: http://elasticsearch:9200
• Identifier Attribute: uuid
• Index: twitter
• Type: default
Ilustración 61PutElasticsearchHttp processor.Settings.
Ilustración 62 PutElasticsearchHttp processor. Properties.
Una vez que tenemos todo configura y los diferentes temas
de conexión solucionados pasamos a ejecutar la prueba.
Para poder ver los datos en Kibana deberemos crearnos un
patron de indice nuevo “twitter*”
pág. 24
Ilustración 63 Creando patron de indice nuevo en kibana.
Una vez creado ya podemos ver todos los datos en kibana,
donde podríamos crear nuestros cuadros de mando.
Ilustración 64 Visión de datos en Kibana.
Podríamos seguir desarrollando ejemplos interesantes, pero
creo que con los expuestos nos hacemos una ligera idea de
las capacidades de Apache NiFi. Entre las pruebas que hemos
realizado estarían las conexiones a bases de datos
Oracle/postgres. Recogida de ficheros vía ftp, llamadas a api
rest, ejecución de scripts,…….
Según vaya teniendo tiempo ire colgando los ejemplos en el
repositorio de githup.
https://github.com/vthot4/poc_nifi
VI. Flow Development Life cycle con NiFi y
NiFi registry.
Una de las principales caracaterísticas de Apache NiFi es la
capacidad de permitirnos diseñar flujos de datos complejos
desde una interfaz de usuario sencilla. Esta sencillez es muy
buena para probar flujos de forma ágil pero se puede
convertir en un problema cuando queremos abordar un ciclo
de desarrollo completo. Para solventar este problema nace,
entre otras cosas, Apache NiFi Registry que nos permitirá
gestionar el “Flow Development Life Cycle with NiFi
registries(FDLC)” dentro de nuestros entornos.
Ilustración 65 Flow Development Life Cycle. Fuente:
Hortonworks.
Cuando hablamos de implementar un FDLC nos refereimos
a implementar un desarrollo ágil que nos permita la
reutilización de componentes y un control de versiones
centralizado equivalente al de cualquier otro lenguaje de
programación. Los componentes reutilizables de Apache
NiFi se centran en las plantillas y las configuraciones. El
esquema general sería el siguiente:
Ilustración 66 Componentes reutilizables niFi. Source:
https://community.hortonworks.com/articles/60868/enterprise-nifi-
implementing-reusable-components-a.html.
Los templates y las configuracones son los componentes
principales que tenemos que tener en cuenta. Cuando
exportamos un flujo podemos crear un template que se
traduce un fichero xml que podemos almacenar en nuestros
repositorios de código. Gestionando este fichero de forma
correcta nos puede servir para gestionar los ciclos de
despliegue en nuestros entornos. El siguiente flujo describe
de forma muy clara el flujo de FDLC que deberíamos seguir:
Ilustración 67 FDLC mediante templates.Source:
https://community.hortonworks.com/articles/60868/enterprise-nifi-
implementing-reusable-components-a.html
pág. 25
Aunque esta opción puede ser válida, desde Apache NiFi
decidieron añadir nuevas herramientas que ayudasen a
abordar este tipo de problemáticas.
Cuando los desarrolladores de NiFi se enfrentaron al
problema de gestionar el FDLC optaron por dotar a NiFi de
dos funcionalidades separadas:
• Flow Registry. Es un subproyecto de Apache NiFi que
nos provee de un almacenamiento centralizado donde
compartir los recursos entre diferentes instancias de NiFi
o MiNiFi. Admite el almacenamiento, la recuperación y
la actualización de flujos versionados.
• Variable Registry. Nos proporcionara flexibilidad para
crear variables dinámicamente y consultarlas en las
propiedades de los componentes. No solo simplifica la
configuración mediante la reutilización de valores, sino
que también mejora la portabilidad de los flujos a nuevos
entornos. La gestión de estas variables se realiza a través
de la interfaz de usuario de NiFi a nivel de grupo de
proceso. Estas variables se pueden actualizar en tiempo
de ejecución sin reiniciar NiFi.
Vamos a ver como hacer una configuración básica y alguna
prueba de funcionaiento, para ello usaremos el siguiente
docker-compose.yml:
---
version: '3.1'
## Component: nifi
## Version: 0.1
## Author: Versia Tecnologías Emergentes
##
networks:
labnet:
services:
nifi:
image: apache/nifi
container_name: Poc_registry_nifi
ports:
- "8080:8080"
environment:
- NIFI_WEB_HTTP_PORT=8080
networks:
- labnet
nifi2:
image: apache/nifi
container_name: Poc_registry_nifi2
ports:
- "9090:9090"
environment:
- NIFI_WEB_HTTP_PORT=9090
networks:
- labnet
registry-nifi:
image: apache/nifi-registry:latest
container_name: Poc_registry_registry
ports:
- 18080:18080
environment:
- NIFI_WEB_HTTP_PORT=18080
networks:
- labnet
El entorno esta copuesto de dos Apache NiFi y un NiFi
registry que nos permitirán explorar la carácterísticas de esta
integración.
Para levantar el entorno bastara con:
~/nifi/poc_nifi/examples/Nifi_registry$ docker-compose -f
docker-compose.yml up -d
~/nifi/poc_nifi/examples/Nifi_registry$ docker-compose -f
docker-compose.yml ps
Name Command State
Ports
--------------------------------------------------------------
--------------------------------------------------------
Poc_registry_nifi ../scripts/start.sh Up
10000/tcp, 0.0.0.0:8080->8080/tcp, 8443/tcp
Poc_registry_nifi2 ../scripts/start.sh Up
10000/tcp, 8080/tcp, 8443/tcp, 0.0.0.0:9090->9090/tcp
Poc_registry_registry /bin/sh -c ${NIFI_REGISTRY ... Up
0.0.0.0:18080->18080/tcp, 18443/tcp
Podremos acceder a los diferentes servicios mediante:
• NiFi1: http://localhost:8080/nifi
• NiFi2: http://localhost:9090/nifi
• NiFi Registry: http://localhost:18080/nifi-registry/
Una vez que tenemos todo levantado, nos conectamos a la
consola del NiFi Registry.
Ilustración 68 Consola inicial NiFi Registry.
Lo primero que vamos a hacer es crear un nuevo “Bucket”
que a efectos prácticos será un nuevo repositorio. Para crearlo
bastará con que pulsemos el menu de settings que aparece en
la parte superior derecha y nos aparecerá la pantalla para
crear el nuevo repositorio. Le daremos el original nombre de
“Prueba”.
Ilustración 69 Añadiendo nuevo Bucket en NiFi Registry.
Una vez creado uestro nuevo bucket poco más podemos
hacer, ya que para poder habilitar permisos deberíamos
conectar nuestro entorno a un ldap o algo simlar.
Ahora vamos a conectar nuestro primer NiFi al NiFi registry.
En la parte superior derecha, desplegamos el menu y
seleccionamos “controller settings”. En el nuevo menu que
nos aparece seleccionamos la pestaña de “Registry clients” y
le damos al “+” para añadir nuestra instacia de NiFi registry.
Name: Nifi registry
URL: http://Poc_registry_registry:18080
pág. 26
Si todo ha ido bien, ya tendríamos que tener configurado
nuestro entorno de pruebas. Vamos a comenzar creando un
nuevo “Process Group” con nombre Prueba.
Ilustración 71 Añadiendo Process Group Prueba.
Una vez creado vamos a ver como configuramos
principalmente dos cosas:
• Variables.
• Versionado.
Para configurar las variables generales de un Process Group
bastará con que accedamos a su configuración → Variables.
Ilustración 72 Configurando un Process Group.
La ventana que nos aparce nos permitirá crear variables que
se podrán usar en todos los flujos que están dentro. De esta
forma podremos cambiar todas las configuraciones de forma
ágil. En este caso he creado dos variables de prueba:
kafka_broker: localhost
kafka_port: 9092
Ilustración 73 Configurando variables del Process Group.
Cuando le damos a aplicar vemos como el mismo hace una
reconfiguración de todos los processors que tengamos dentro
del grupo.
Ilustración 74 Reconfiguración de variables.
Si exportamos este flujo de trabajo y revisaramos el template
xml que nos crea podemos podemos ver esas variables que
acabos de crear:
Antes de pasar a ver como se implementan estas variables
que hemos creado vamos a hailitar el versionado de nuestro
componente. Para ello accedemos a la configuración –A
versión y “Start verion control”. Nos saldrá una pantalla
donde podremos escoger el servidor y repositorio en el que
queremos que se guarde. En nuestro caso:
Registry: Nifi registry
Bucket: Prueba
Flow Name: Insercción Kafka-Mongo
Ilustración 70 Añadiendo NiFi registry a NiFi.
pág. 27
Ilustración 75 Iniciando control de versiones del componente.
Ahora si volvemos a la parte de Version veremos que el menu
nos ha cambiado.
Continuemos con nuestra pequeña prueba añadiendo un par
de processor, para ello entramos en el Process Group de
prueba que hemos creado con anterioridad. En la parte
inferior izquierda podemos ver de forma simple donde nos
encontramos.
Ya situados añadiremos dos procesadores básicos, PutKafka
y PutMongo18
. El flujo quedará de la siguiente forma:
Ilustración 76 Flujo simple de prueba.
18
En esta prueba sólo busco ver las funcionalidades del Kafka Regstry por
lo que he optado por crear el flujo sin la infraestructura. Usando los ejemplos
anteriores es sencillo comoner la prueba real completa.
Para usar las variables bastará con ir a properties del objeto y
en lugar de añadir los valores poner las variables de la
siguiente forma:
Known Brokers: ${kafka-broker}:${kafka-port}
Añadidos nuestros cambios sobre el grupo de proceso prueba
volvemos a la parte de version de la configuración. Veremos
que nos aparcen las opciones de ver los cambios locales,
revertir los cambios y subir los nuevos cambios al
repositorio.
Ilustración 77 Opciones de la gestión de versionado.
Podemos añadir algunos procesadores
mas como un GenerateFlowfile y
realizar varios commits. Una vez
realizado poderemos ir a la opción de
change e ir recuperando las diferentes
versiones.
Podemos ver el historial de cambios
desde Apache Regsitry:
Ilustración 78 Change log niFi Registry.
pág. 28
Para terminar esta sencilla prueba podemos conectar el
segundo nifi que tenemos levantado al NiFi registry y probar
a crear un Process Group nuevo. Cuando añadimos el
componente nuevo podemos ver que tenemos la opción de
importar
Y nos aparecera la verdadera magia de NiFi registry.
Si se sube alguna nueva version del componente, nos
aparecerá una flecha roja en la parte superior izquierda:
Ilustración 79 Alerta de nueva versión en componente.
Actualizaríamos la versión y el componente cogería todos los
nuevos cambios19
.
Con esto ya tenemos a nuestra disposión un gestor de flujos
que nos puede ayudar a controlar su creación y producción
de forma ágil y centralizada.
A. Arquitectura interna.20
Vamos a ver un poco como esta implementado este
componente. En principio el interfaz de usuario es una
aplicación web creada con angular que se comunica con el
19
En algunos casos nos puede dar error si todavía quedan pendientes
pensajes de procesar en las colas intermedias. Normalmente deberemos
esperar a que se vacien o forzar parando flujos anteriores.
20
https://bryanbende.com/development/2018/06/20/apache-nifi-registry-0-
2-0
servidor mediante el API REST del registro de NIFI21
. Detrás
de esta API REST encontramos la capa de servicio donde se
implementa la lógica principal, la capa de servicio que
interactua con la la base de metadatos y el proveedor de
persistencia de flujo.
La base de metadatos almacenará la información sobre
grupos y elementos versionados, como identificadores,
nombres, descripciones y comentarios de confirmación. En
una primera versión se uso la base de datos H2 de forma
embebida pero en las nuevas versiones permite usar bases de
datos externas como postgres. Para llevar a cabo esta
configuración deberemos modificar algunos parámetros del
fichero de configuración:
nifi.registry.db.url=
nifi.registry.db.driver.class=
nifi.registry.db.driver.directory=
nifi.registry.db.username=
nifi.registry.db.password=
El proveedor de persistencia de flujo almacena el contenido
de cada flujo versionado y se considera un punto de extensión
público. Esto significa que se pueden proporcionar
implementaciones personalizadas implementando la interfaz
FlowPersistenceProvider. En la versión inicial se
implemento esta funcionalidad usando el sistema de archivos
local para la persistencia pero en las nuevas versiones se ha
implementado en base a git mediante el uso de la biblioteca
JGit. Esto nos proporciona la posibilidad de almacenar el
repositorio en un repo git.
El proveedor de git se puede configurar en el fichero de
configuración suppliers.xml:
<flowPersistenceProvider>
<class>
org.apache.nifi.registry.provider.flow.git.GitFlowPersistenceP
rovider
</class>
<property name="Flow Storage
Directory">./flow_storage</property>
<property name="Remote To Push"></property>
<property name="Remote Access User"></property>
<property name="Remote Access Password"></property>
</flowPersistenceProvider>
Con la propiedad “Flow Starage Directory” especificaremos
el directorio local que se espera que sea un repositorio git.
La propiedad "Remote To Push" especifica el nombre del
repositorio remoto al que se enviará automáticamente. Esta
propiedad es opcional y, si no se especifica, las
confirmaciones permanecerán en el repositorio local, a
menos que la subida la hagamos manualmente.
Resumiendo un poco los pasos para conectar nuestro
repositorio a git serían:
1. Crear un nuevo repositorio de GitHub y clonarlo
localmente.
21
Podemos ver la documentación del API en
https://nifi.apache.org/docs/nifi-registry-docs/index.html.
pág. 29
2. Establecer el Flow storage directory en el directorio
que se clonó el repositorio.
3. Crear un nuevo “Personal Access Token” para
nuestra instancia de Nifi Registry.
4. Establecer el “ Remote Access User” en GitHub.
5. Establecer “Remote Access Password” en el token
de acceso.
Ilustración 80 Source:
https://bryanbende.com/development/2018/06/20/apache-nifi-
registry-0-2-0
Otra funcionalidad interesante que presenta la arquitectura de
Apache NiFi Registry es la posibilidad de los “Event
Hooks”. Nos permitirá ejecutar código personalizado cuando
ocurran eventos de aplicación. Para implementar los event
hook, deberá ser implementada la siguiente interfaz de Java:
public interface EventHookProvider extends Provider {
void handle(Event event) throws EventHookException;
}
Donde el objeto evento contendrá un tipo de evento, junto
con una lista de pares campo/valor que son específicos de
cada evento. Algunos posibles eventos son:
CREATE_BUCKET
CREATE_FLOW
CREATE_FLOW_VERSION
UPDATE_BUCKET
UPDATE_FLOW
DELETE_BUCKET
DELETE_FLOW
Si no queremos meternos a implementar la interfaz de Java
podríamos configurar el “ScriptedEventHookProvider” que
nos permitiría ejecutar scripts para cada evento. La
configuración para este tipo de event hook sería:
<eventHookProvider>
<class>
org.apache.nifi.registry.provider.hook.ScriptEventHookProvider
</class>
<property name="Script Path"></property>
<property name="Working Directory"></property>
</eventHookProvider>
Los argumentos del script serán los campos de eventos en el
orden en que se especifican para el tipo de evento dado.
Como ejemplo, digamos que creamos un script llamado
logging-hook.sh con el siguiente contenido:
#!/bin/bash
echo $@ >> /tmp/nifi-registry-event.log
Para cada evento, esto reflejaría los argumentos del script y
los agregaría a /tmp/nifi-registry-event.log. Después de crear
un grupo y comenzar el control de versión en un grupo de
procesos, el registro debería mostrar algo como lo siguiente:
CREATE_BUCKET feeb0fbe-5d7e-4363-b58b-142fa80775e1 anonymous
CREATE_FLOW feeb0fbe-5d7e-4363-b58b-142fa80775e1 1a0b614c-3d0f-
471a-b6b1-645e6091596d anonymous
CREATE_FLOW_VERSION feeb0fbe-5d7e-4363-b58b-142fa80775e1
1a0b614c-3d0f-471a-b6b1-645e6091596d 1 anonymous v1
VII. Cluster NiFi.
Como vimos anteriormente, Apache NiFi presenta la
capacidad de clasterización mediante el uso de ZooKeeper
como coordinador. El esquema general que nos proponen en
la configuración es el siguiente:
Ilustración 81 Esquema de cluster Apache NiFi
Usa el paradigma de Zero-Master, en el que cada nodo del
clúster realiza las mismas tareas sobre los datos, pero cada
uno opera en un conjunto de datos diferente. Uno de los
nodos será elegido automáticamente como el coordinador del
clúster que pasará a gestionar el estado de los nodos.
Deberemos entender algunos conceptos antes de realizar una
configuración base:
• NiFi Cluster Coordinator. Un coordinador de
agrupaciones de NiFi es el nodo responsable de llevar a
cabo las tareas para gestionar qué nodos se permiten en
la agrupación y proporcionar el flujo más actualizado a
los nodos recién incorporados.
• Nodes. Cada gruopo se compone de uno o más nodos.
Los nodos son los que llevan a cabo el procesamiento
real de los datos.
• Primary Node. En cada clúster existe un nodo primario.
En este nodo es posible ejecutar “Procesadores
aislados”. Este nodo será elegido automáticamente por
ZooKeeper, de modo que si se desconecta del clúster,
otro nodo será elegido en su lugar. Los adminsitradores
podrán determinar que nodos pueden elegirse para ser
primarios desde la consola de administración.
pág. 30
• Isolated Processors. En un cluster Nifi, el mismo flujo
de datos se ejecuta en todos los nodos. Como resultado,
cada componente en el flujo se ejecuta en cada nodo.
Sin embargo, pueden existir casos en los que queramos
que los procesos sólo se ejecuten en el nodo primario
para evitar problemas en la ingesta de datos. Para estos
casos podemos configurar los procesadores aislados.
• Heartbeats. El nodo principal recibe el estado de salud
del resto de nodos mediante el “hearbeat(latidos)”. De
forma predeterminada, los nodos emiten hearbeats cada
5 segundos. Si el coordinador no recibe esta señal
durante 40 segundos, desconectará el nodo. Si, después
de 40 segundos, el nodo envía de nuevo un latido, el
coordinador solicitará automáticamente que el nodo
vuelva a unirse al clúster. Estas configuraciones de
tiempo de hearbeat y tiempo de espera hasta
desconexión se pueden configurar en el fichero
“nifi.proprties”.
Entendidos algunos de los conceptos básicos vamos a probar
a levantar un pequeño clúster usando una funcionalidad muy
interesante de docker-compose. Usaremos el siguiente
docker-compose:
---
version: "3.1"
## Component: nifi
## Version: 0.2
## Author: Versia Tecnologías Emergentes
##
services:
zookeeper:
hostname: zookeeper
container_name: zookeeper
image: 'bitnami/zookeeper:latest'
environment:
- ALLOW_ANONYMOUS_LOGIN=yes
nifi:
image: apache/nifi
ports:
- 8080
environment:
- NIFI_WEB_HTTP_PORT=8080
- NIFI_CLUSTER_IS_NODE=true
- NIFI_CLUSTER_NODE_PROTOCOL_PORT=8082
- NIFI_ZK_CONNECT_STRING=zookeeper:2181
- NIFI_ELECTION_MAX_WAIT=1 min
Y lo levantaremos medainte:
$ docker-compose -f docker-compose-cluster.yml up --scale nifi=3
-d
$ docker-compose -f docker-compose-cluster.yml ps
Name Command State Ports
--------------------------------------------------------------
---------------------------------
nifi_nifi_1 ../scripts/start.sh Up 10000/tcp,
0.0.0.0:32775->8080/tcp, 8443/tcp
nifi_nifi_2 ../scripts/start.sh Up 10000/tcp,
0.0.0.0:32776->8080/tcp, 8443/tcp
nifi_nifi_3 ../scripts/start.sh Up 10000/tcp,
0.0.0.0:32777->8080/tcp, 8443/tcp
zookeeper /app-entrypoint.sh /run.sh Up 2181/tcp,
2888/tcp, 3888/tcp
Podremos acceder a nuestro nuevo cluster vía los puertos:
32775,32776 ó 32777. Estos puertos se generan de forma
semi-aleatoria así que hay que comprobarlos después de cada
arranque.
Una vez que tenemos todo levantado podemos acceder y
desde el menu lateral, entrar en las opciones del cluster. Nos
debería de aparecer algo parecido a esto:
Ilustración 82 Consola de administración del cluster.
En esta consola de administración tenemos varias pestañas
que nos proporcionan información sobre el estado del cluster:
• Nodes. Muestra información sobre el direccionamiento
de los nodos, tamaño de las colas y el estado. En la parte
de estado podemos ver que rol tiene cada nodo en el
clúster y los últimos datos de hearbeat. Desde esta vista
también podemos desconectar los nodos que queramos.
• System. Nos proporciona información sobre los
recursos que dispone la máquina sobre la que corre el
nodo. Se muestra número de cores, el load de los cores
y el número de Threads.
• JVM. Información destacada del uso de la máquina
virtual de java en cada nodo.
Ilustración 83 Administración clúster. JVM.
• Storage. Disponemos de tres pestañas destinadas a
mostrar los porcentajes de uso del FlowFile storage,
Content Storage y Provenance Storage.
• Versions. Nos permite ver de forma ágil, las versiones
de los productos de nuestro clúster.
Ilustración 84 Administración clúster. Versions.
No me voy a extender mucho más, aunque sería interesante
hacer pruebas de HA para ver como cambia el master y
analizar como se comportan los flujos. Sólo indicar que ahora
desde la pestaña de scheduling de los processors podremos
decidir si se va a ejectuar en todos los nodos o solo en el
primario.
pág. 31
Ilustración 85 Scheduling execution.
Con esta forma de levantar el cluster podemos probar a
escalar hacia arriba y hacia abajo el número de nodos a
nuestra voluntad.
$ docker-compose -f docker-compose-cluster.yml up --scale nifi=8
-d
Starting nifi_nifi_1 ...
Starting nifi_nifi_1 ... done
Starting nifi_nifi_2 ... done
Starting nifi_nifi_3 ... done
Creating nifi_nifi_4 ... done
Creating nifi_nifi_5 ... done
Creating nifi_nifi_6 ... done
Creating nifi_nifi_7 ... done
Creating nifi_nifi_8 ... done
$ docker-compose -f docker-compose-cluster.yml ps
Name Command State Ports
--------------------------------------------------------------
---------------------------------
nifi_nifi_1 ../scripts/start.sh Up 10000/tcp,
0.0.0.0:32775->8080/tcp, 8443/tcp
nifi_nifi_2 ../scripts/start.sh Up 10000/tcp,
0.0.0.0:32776->8080/tcp, 8443/tcp
nifi_nifi_3 ../scripts/start.sh Up 10000/tcp,
0.0.0.0:32777->8080/tcp, 8443/tcp
nifi_nifi_4 ../scripts/start.sh Up 10000/tcp,
0.0.0.0:32780->8080/tcp, 8443/tcp
nifi_nifi_5 ../scripts/start.sh Up 10000/tcp,
0.0.0.0:32781->8080/tcp, 8443/tcp
nifi_nifi_6 ../scripts/start.sh Up 10000/tcp,
0.0.0.0:32778->8080/tcp, 8443/tcp
nifi_nifi_7 ../scripts/start.sh Up 10000/tcp,
0.0.0.0:32782->8080/tcp, 8443/tcp
nifi_nifi_8 ../scripts/start.sh Up 10000/tcp,
0.0.0.0:32779->8080/tcp, 8443/tcp
zookeeper /app-entrypoint.sh /run.sh Up 2181/tcp,
2888/tcp, 3888/tcp
Y si tenemos un poco de paciencia, podremos ver algo como
esto:
VIII. MiNiFi.
MiNiFi, es un subproyecto de Apache NiFi, que nace con un
enfoque más orientado a la recopilación de datos en origen.
Esto le permitirá a NiFi aumentar el control sobre el flujo de
datos. Los objetivos específicos para el impulso inicial del
esfuerzo de MiNFi incluyen:
• Pequeño tamaño y bajo consumo de recursos.
• Gestión central de agentes.
• Generación de procedencia de datos (Cadena completa de
custodia de la información).
• Integración con NiFi para la gestión de flujo de datos de
seguimiento.
Siguiendo estos objetivos optaron por eliminar toda la parte
de la consola y reducir los procesadores a un número
reducido aunque siempres e pueden añadir si los
necesitamos. El esquema general de MiNiFi queda de la
sigueinte forma:
Figure 1 MiNiFi Java Processes. Source: HortonWorks.
Existen numerosas posibilidades para el binomio MiNiFi-
NiFi, pero una de las más interesantes es la de gateway de
IoT. No vamos a desarrollar los ejemplos en este documento,
pero pongo dos enlaces a proyectos muy interesantes y fáciles
de implementar.
Por un lado esta la centralización de datos recogidos
mediante protocolos MQQT. Podemos encontrar la
documentación del desarrollo en:
https://medium.freecodecamp.org/building-an-iiot-system-
using-apache-nifi-mqtt-and-raspberry-pi-ce1d6ed565bc
Y el esquema sería el siguiente:
Ilustración 86 Arquitectura IoT. Source:
https://medium.freecodecamp.org/building-an-iiot-system-using-
apache-nifi-mqtt-and-raspberry-pi-ce1d6ed565bc
Mosquitto se encargaría de recibir los datos mediante mqqt
desde los sensores y MiNiFi estaría enganchado a los
Apache nifi_introduccion_v1.0
Apache nifi_introduccion_v1.0
Apache nifi_introduccion_v1.0
Apache nifi_introduccion_v1.0

More Related Content

What's hot

BYOP: Custom Processor Development with Apache NiFi
BYOP: Custom Processor Development with Apache NiFiBYOP: Custom Processor Development with Apache NiFi
BYOP: Custom Processor Development with Apache NiFiDataWorks Summit
 
State of the Trino Project
State of the Trino ProjectState of the Trino Project
State of the Trino ProjectMartin Traverso
 
Planning your Next-Gen Change Data Capture (CDC) Architecture in 2019 - Strea...
Planning your Next-Gen Change Data Capture (CDC) Architecture in 2019 - Strea...Planning your Next-Gen Change Data Capture (CDC) Architecture in 2019 - Strea...
Planning your Next-Gen Change Data Capture (CDC) Architecture in 2019 - Strea...Impetus Technologies
 
Best Practice of Compression/Decompression Codes in Apache Spark with Sophia...
 Best Practice of Compression/Decompression Codes in Apache Spark with Sophia... Best Practice of Compression/Decompression Codes in Apache Spark with Sophia...
Best Practice of Compression/Decompression Codes in Apache Spark with Sophia...Databricks
 
Building Your Data Streams for all the IoT
Building Your Data Streams for all the IoTBuilding Your Data Streams for all the IoT
Building Your Data Streams for all the IoTDevOps.com
 
Data Models Breakout Session
Data Models Breakout SessionData Models Breakout Session
Data Models Breakout SessionSplunk
 
Spark and S3 with Ryan Blue
Spark and S3 with Ryan BlueSpark and S3 with Ryan Blue
Spark and S3 with Ryan BlueDatabricks
 
SF Big Analytics 20190612: Building highly efficient data lakes using Apache ...
SF Big Analytics 20190612: Building highly efficient data lakes using Apache ...SF Big Analytics 20190612: Building highly efficient data lakes using Apache ...
SF Big Analytics 20190612: Building highly efficient data lakes using Apache ...Chester Chen
 
How to use flash drives with Apache Hadoop 3.x: Real world use cases and proo...
How to use flash drives with Apache Hadoop 3.x: Real world use cases and proo...How to use flash drives with Apache Hadoop 3.x: Real world use cases and proo...
How to use flash drives with Apache Hadoop 3.x: Real world use cases and proo...DataWorks Summit
 
New Features in Apache Pinot
New Features in Apache PinotNew Features in Apache Pinot
New Features in Apache PinotSiddharth Teotia
 
Batch Processing at Scale with Flink & Iceberg
Batch Processing at Scale with Flink & IcebergBatch Processing at Scale with Flink & Iceberg
Batch Processing at Scale with Flink & IcebergFlink Forward
 
Table Partitioning in SQL Server: A Magic Solution for Better Performance? (P...
Table Partitioning in SQL Server: A Magic Solution for Better Performance? (P...Table Partitioning in SQL Server: A Magic Solution for Better Performance? (P...
Table Partitioning in SQL Server: A Magic Solution for Better Performance? (P...Cathrine Wilhelmsen
 
Airflow Best Practises & Roadmap to Airflow 2.0
Airflow Best Practises & Roadmap to Airflow 2.0Airflow Best Practises & Roadmap to Airflow 2.0
Airflow Best Practises & Roadmap to Airflow 2.0Kaxil Naik
 
Tanel Poder - Performance stories from Exadata Migrations
Tanel Poder - Performance stories from Exadata MigrationsTanel Poder - Performance stories from Exadata Migrations
Tanel Poder - Performance stories from Exadata MigrationsTanel Poder
 
Hudi architecture, fundamentals and capabilities
Hudi architecture, fundamentals and capabilitiesHudi architecture, fundamentals and capabilities
Hudi architecture, fundamentals and capabilitiesNishith Agarwal
 
Lessons learned processing 70 billion data points a day using the hybrid cloud
Lessons learned processing 70 billion data points a day using the hybrid cloudLessons learned processing 70 billion data points a day using the hybrid cloud
Lessons learned processing 70 billion data points a day using the hybrid cloudDataWorks Summit
 
The Rise of ZStandard: Apache Spark/Parquet/ORC/Avro
The Rise of ZStandard: Apache Spark/Parquet/ORC/AvroThe Rise of ZStandard: Apache Spark/Parquet/ORC/Avro
The Rise of ZStandard: Apache Spark/Parquet/ORC/AvroDatabricks
 
Best Practices for ETL with Apache NiFi on Kubernetes - Albert Lewandowski, G...
Best Practices for ETL with Apache NiFi on Kubernetes - Albert Lewandowski, G...Best Practices for ETL with Apache NiFi on Kubernetes - Albert Lewandowski, G...
Best Practices for ETL with Apache NiFi on Kubernetes - Albert Lewandowski, G...GetInData
 
Self-Service Data Ingestion Using NiFi, StreamSets & Kafka
Self-Service Data Ingestion Using NiFi, StreamSets & KafkaSelf-Service Data Ingestion Using NiFi, StreamSets & Kafka
Self-Service Data Ingestion Using NiFi, StreamSets & KafkaGuido Schmutz
 

What's hot (20)

BYOP: Custom Processor Development with Apache NiFi
BYOP: Custom Processor Development with Apache NiFiBYOP: Custom Processor Development with Apache NiFi
BYOP: Custom Processor Development with Apache NiFi
 
State of the Trino Project
State of the Trino ProjectState of the Trino Project
State of the Trino Project
 
Planning your Next-Gen Change Data Capture (CDC) Architecture in 2019 - Strea...
Planning your Next-Gen Change Data Capture (CDC) Architecture in 2019 - Strea...Planning your Next-Gen Change Data Capture (CDC) Architecture in 2019 - Strea...
Planning your Next-Gen Change Data Capture (CDC) Architecture in 2019 - Strea...
 
Best Practice of Compression/Decompression Codes in Apache Spark with Sophia...
 Best Practice of Compression/Decompression Codes in Apache Spark with Sophia... Best Practice of Compression/Decompression Codes in Apache Spark with Sophia...
Best Practice of Compression/Decompression Codes in Apache Spark with Sophia...
 
Building Your Data Streams for all the IoT
Building Your Data Streams for all the IoTBuilding Your Data Streams for all the IoT
Building Your Data Streams for all the IoT
 
Data Models Breakout Session
Data Models Breakout SessionData Models Breakout Session
Data Models Breakout Session
 
Spark and S3 with Ryan Blue
Spark and S3 with Ryan BlueSpark and S3 with Ryan Blue
Spark and S3 with Ryan Blue
 
SF Big Analytics 20190612: Building highly efficient data lakes using Apache ...
SF Big Analytics 20190612: Building highly efficient data lakes using Apache ...SF Big Analytics 20190612: Building highly efficient data lakes using Apache ...
SF Big Analytics 20190612: Building highly efficient data lakes using Apache ...
 
Nifi
NifiNifi
Nifi
 
How to use flash drives with Apache Hadoop 3.x: Real world use cases and proo...
How to use flash drives with Apache Hadoop 3.x: Real world use cases and proo...How to use flash drives with Apache Hadoop 3.x: Real world use cases and proo...
How to use flash drives with Apache Hadoop 3.x: Real world use cases and proo...
 
New Features in Apache Pinot
New Features in Apache PinotNew Features in Apache Pinot
New Features in Apache Pinot
 
Batch Processing at Scale with Flink & Iceberg
Batch Processing at Scale with Flink & IcebergBatch Processing at Scale with Flink & Iceberg
Batch Processing at Scale with Flink & Iceberg
 
Table Partitioning in SQL Server: A Magic Solution for Better Performance? (P...
Table Partitioning in SQL Server: A Magic Solution for Better Performance? (P...Table Partitioning in SQL Server: A Magic Solution for Better Performance? (P...
Table Partitioning in SQL Server: A Magic Solution for Better Performance? (P...
 
Airflow Best Practises & Roadmap to Airflow 2.0
Airflow Best Practises & Roadmap to Airflow 2.0Airflow Best Practises & Roadmap to Airflow 2.0
Airflow Best Practises & Roadmap to Airflow 2.0
 
Tanel Poder - Performance stories from Exadata Migrations
Tanel Poder - Performance stories from Exadata MigrationsTanel Poder - Performance stories from Exadata Migrations
Tanel Poder - Performance stories from Exadata Migrations
 
Hudi architecture, fundamentals and capabilities
Hudi architecture, fundamentals and capabilitiesHudi architecture, fundamentals and capabilities
Hudi architecture, fundamentals and capabilities
 
Lessons learned processing 70 billion data points a day using the hybrid cloud
Lessons learned processing 70 billion data points a day using the hybrid cloudLessons learned processing 70 billion data points a day using the hybrid cloud
Lessons learned processing 70 billion data points a day using the hybrid cloud
 
The Rise of ZStandard: Apache Spark/Parquet/ORC/Avro
The Rise of ZStandard: Apache Spark/Parquet/ORC/AvroThe Rise of ZStandard: Apache Spark/Parquet/ORC/Avro
The Rise of ZStandard: Apache Spark/Parquet/ORC/Avro
 
Best Practices for ETL with Apache NiFi on Kubernetes - Albert Lewandowski, G...
Best Practices for ETL with Apache NiFi on Kubernetes - Albert Lewandowski, G...Best Practices for ETL with Apache NiFi on Kubernetes - Albert Lewandowski, G...
Best Practices for ETL with Apache NiFi on Kubernetes - Albert Lewandowski, G...
 
Self-Service Data Ingestion Using NiFi, StreamSets & Kafka
Self-Service Data Ingestion Using NiFi, StreamSets & KafkaSelf-Service Data Ingestion Using NiFi, StreamSets & Kafka
Self-Service Data Ingestion Using NiFi, StreamSets & Kafka
 

Similar to Apache nifi_introduccion_v1.0 (20)

Recurrencia en procesos
Recurrencia en procesosRecurrencia en procesos
Recurrencia en procesos
 
Sistemas distribuidos
Sistemas distribuidosSistemas distribuidos
Sistemas distribuidos
 
Oracle
OracleOracle
Oracle
 
Diseño de Algoritmos Paralelos.pdf
Diseño de Algoritmos Paralelos.pdfDiseño de Algoritmos Paralelos.pdf
Diseño de Algoritmos Paralelos.pdf
 
Base de datos objeto
Base de datos objetoBase de datos objeto
Base de datos objeto
 
Hilo de ejecución
Hilo de ejecuciónHilo de ejecución
Hilo de ejecución
 
On-the-fly ETL con EFK: ElasticSearch, Flume, Kibana
On-the-fly ETL con EFK: ElasticSearch, Flume, KibanaOn-the-fly ETL con EFK: ElasticSearch, Flume, Kibana
On-the-fly ETL con EFK: ElasticSearch, Flume, Kibana
 
Base de datos no sql
Base de datos no sqlBase de datos no sql
Base de datos no sql
 
Basede datos nlsg
Basede datos nlsgBasede datos nlsg
Basede datos nlsg
 
Datos En La Web Clase 3
Datos En La Web   Clase 3Datos En La Web   Clase 3
Datos En La Web Clase 3
 
Base datos-romero
Base datos-romeroBase datos-romero
Base datos-romero
 
Presentación1
Presentación1Presentación1
Presentación1
 
Base de datos
Base de datosBase de datos
Base de datos
 
Bases de datos
Bases de datos Bases de datos
Bases de datos
 
Caracteristicas de oracle y my sql
Caracteristicas de oracle y my sqlCaracteristicas de oracle y my sql
Caracteristicas de oracle y my sql
 
Presentacion de power point
Presentacion de power pointPresentacion de power point
Presentacion de power point
 
Presentacion de power point
Presentacion de power pointPresentacion de power point
Presentacion de power point
 
BASES DE DATOS
BASES DE DATOSBASES DE DATOS
BASES DE DATOS
 
02 base de datos hernandez_luis
02 base de datos hernandez_luis02 base de datos hernandez_luis
02 base de datos hernandez_luis
 
Arquitectura de referencia corregido
Arquitectura de referencia corregidoArquitectura de referencia corregido
Arquitectura de referencia corregido
 

More from Victor Martinez

Addo 2019 ppt_the_dream_of_antifragile_systems- final
Addo 2019 ppt_the_dream_of_antifragile_systems- finalAddo 2019 ppt_the_dream_of_antifragile_systems- final
Addo 2019 ppt_the_dream_of_antifragile_systems- finalVictor Martinez
 
Meetup Málaga caos y kubernetes
Meetup Málaga caos y kubernetesMeetup Málaga caos y kubernetes
Meetup Málaga caos y kubernetesVictor Martinez
 
Futuro tecnologico.una vision_teorica__v1.1
Futuro tecnologico.una vision_teorica__v1.1Futuro tecnologico.una vision_teorica__v1.1
Futuro tecnologico.una vision_teorica__v1.1Victor Martinez
 
Malaga chaos-caminando hacia-sistemas_antifragiles-v0.1
Malaga chaos-caminando hacia-sistemas_antifragiles-v0.1Malaga chaos-caminando hacia-sistemas_antifragiles-v0.1
Malaga chaos-caminando hacia-sistemas_antifragiles-v0.1Victor Martinez
 
Introduccion a hyperledger meetup_vthot4
Introduccion a hyperledger meetup_vthot4Introduccion a hyperledger meetup_vthot4
Introduccion a hyperledger meetup_vthot4Victor Martinez
 
blockchain e industria 4.0 (Vitoria)
blockchain e industria 4.0  (Vitoria)blockchain e industria 4.0  (Vitoria)
blockchain e industria 4.0 (Vitoria)Victor Martinez
 
Dev opsconf una-vision_desde_sistemas-v1..0
Dev opsconf una-vision_desde_sistemas-v1..0Dev opsconf una-vision_desde_sistemas-v1..0
Dev opsconf una-vision_desde_sistemas-v1..0Victor Martinez
 

More from Victor Martinez (7)

Addo 2019 ppt_the_dream_of_antifragile_systems- final
Addo 2019 ppt_the_dream_of_antifragile_systems- finalAddo 2019 ppt_the_dream_of_antifragile_systems- final
Addo 2019 ppt_the_dream_of_antifragile_systems- final
 
Meetup Málaga caos y kubernetes
Meetup Málaga caos y kubernetesMeetup Málaga caos y kubernetes
Meetup Málaga caos y kubernetes
 
Futuro tecnologico.una vision_teorica__v1.1
Futuro tecnologico.una vision_teorica__v1.1Futuro tecnologico.una vision_teorica__v1.1
Futuro tecnologico.una vision_teorica__v1.1
 
Malaga chaos-caminando hacia-sistemas_antifragiles-v0.1
Malaga chaos-caminando hacia-sistemas_antifragiles-v0.1Malaga chaos-caminando hacia-sistemas_antifragiles-v0.1
Malaga chaos-caminando hacia-sistemas_antifragiles-v0.1
 
Introduccion a hyperledger meetup_vthot4
Introduccion a hyperledger meetup_vthot4Introduccion a hyperledger meetup_vthot4
Introduccion a hyperledger meetup_vthot4
 
blockchain e industria 4.0 (Vitoria)
blockchain e industria 4.0  (Vitoria)blockchain e industria 4.0  (Vitoria)
blockchain e industria 4.0 (Vitoria)
 
Dev opsconf una-vision_desde_sistemas-v1..0
Dev opsconf una-vision_desde_sistemas-v1..0Dev opsconf una-vision_desde_sistemas-v1..0
Dev opsconf una-vision_desde_sistemas-v1..0
 

Recently uploaded

CLASE DE TECNOLOGIA E INFORMATICA PRIMARIA
CLASE  DE TECNOLOGIA E INFORMATICA PRIMARIACLASE  DE TECNOLOGIA E INFORMATICA PRIMARIA
CLASE DE TECNOLOGIA E INFORMATICA PRIMARIAWilbisVega
 
Presentación guía sencilla en Microsoft Excel.pptx
Presentación guía sencilla en Microsoft Excel.pptxPresentación guía sencilla en Microsoft Excel.pptx
Presentación guía sencilla en Microsoft Excel.pptxLolaBunny11
 
POWER POINT YUCRAElabore una PRESENTACIÓN CORTA sobre el video película: La C...
POWER POINT YUCRAElabore una PRESENTACIÓN CORTA sobre el video película: La C...POWER POINT YUCRAElabore una PRESENTACIÓN CORTA sobre el video película: La C...
POWER POINT YUCRAElabore una PRESENTACIÓN CORTA sobre el video película: La C...silviayucra2
 
Herramientas de corte de alta velocidad.pptx
Herramientas de corte de alta velocidad.pptxHerramientas de corte de alta velocidad.pptx
Herramientas de corte de alta velocidad.pptxRogerPrieto3
 
Global Azure Lima 2024 - Integración de Datos con Microsoft Fabric
Global Azure Lima 2024 - Integración de Datos con Microsoft FabricGlobal Azure Lima 2024 - Integración de Datos con Microsoft Fabric
Global Azure Lima 2024 - Integración de Datos con Microsoft FabricKeyla Dolores Méndez
 
International Women's Day Sucre 2024 (IWD)
International Women's Day Sucre 2024 (IWD)International Women's Day Sucre 2024 (IWD)
International Women's Day Sucre 2024 (IWD)GDGSucre
 
KELA Presentacion Costa Rica 2024 - evento Protégeles
KELA Presentacion Costa Rica 2024 - evento ProtégelesKELA Presentacion Costa Rica 2024 - evento Protégeles
KELA Presentacion Costa Rica 2024 - evento ProtégelesFundación YOD YOD
 
EPA-pdf resultado da prova presencial Uninove
EPA-pdf resultado da prova presencial UninoveEPA-pdf resultado da prova presencial Uninove
EPA-pdf resultado da prova presencial UninoveFagnerLisboa3
 
Trabajo Mas Completo De Excel en clase tecnología
Trabajo Mas Completo De Excel en clase tecnologíaTrabajo Mas Completo De Excel en clase tecnología
Trabajo Mas Completo De Excel en clase tecnologíassuserf18419
 
guía de registro de slideshare por Brayan Joseph
guía de registro de slideshare por Brayan Josephguía de registro de slideshare por Brayan Joseph
guía de registro de slideshare por Brayan JosephBRAYANJOSEPHPEREZGOM
 
pruebas unitarias unitarias en java con JUNIT
pruebas unitarias unitarias en java con JUNITpruebas unitarias unitarias en java con JUNIT
pruebas unitarias unitarias en java con JUNITMaricarmen Sánchez Ruiz
 
Redes direccionamiento y subredes ipv4 2024 .pdf
Redes direccionamiento y subredes ipv4 2024 .pdfRedes direccionamiento y subredes ipv4 2024 .pdf
Redes direccionamiento y subredes ipv4 2024 .pdfsoporteupcology
 
Proyecto integrador. Las TIC en la sociedad S4.pptx
Proyecto integrador. Las TIC en la sociedad S4.pptxProyecto integrador. Las TIC en la sociedad S4.pptx
Proyecto integrador. Las TIC en la sociedad S4.pptx241521559
 
trabajotecologiaisabella-240424003133-8f126965.pdf
trabajotecologiaisabella-240424003133-8f126965.pdftrabajotecologiaisabella-240424003133-8f126965.pdf
trabajotecologiaisabella-240424003133-8f126965.pdfIsabellaMontaomurill
 
9egb-lengua y Literatura.pdf_texto del estudiante
9egb-lengua y Literatura.pdf_texto del estudiante9egb-lengua y Literatura.pdf_texto del estudiante
9egb-lengua y Literatura.pdf_texto del estudianteAndreaHuertas24
 

Recently uploaded (15)

CLASE DE TECNOLOGIA E INFORMATICA PRIMARIA
CLASE  DE TECNOLOGIA E INFORMATICA PRIMARIACLASE  DE TECNOLOGIA E INFORMATICA PRIMARIA
CLASE DE TECNOLOGIA E INFORMATICA PRIMARIA
 
Presentación guía sencilla en Microsoft Excel.pptx
Presentación guía sencilla en Microsoft Excel.pptxPresentación guía sencilla en Microsoft Excel.pptx
Presentación guía sencilla en Microsoft Excel.pptx
 
POWER POINT YUCRAElabore una PRESENTACIÓN CORTA sobre el video película: La C...
POWER POINT YUCRAElabore una PRESENTACIÓN CORTA sobre el video película: La C...POWER POINT YUCRAElabore una PRESENTACIÓN CORTA sobre el video película: La C...
POWER POINT YUCRAElabore una PRESENTACIÓN CORTA sobre el video película: La C...
 
Herramientas de corte de alta velocidad.pptx
Herramientas de corte de alta velocidad.pptxHerramientas de corte de alta velocidad.pptx
Herramientas de corte de alta velocidad.pptx
 
Global Azure Lima 2024 - Integración de Datos con Microsoft Fabric
Global Azure Lima 2024 - Integración de Datos con Microsoft FabricGlobal Azure Lima 2024 - Integración de Datos con Microsoft Fabric
Global Azure Lima 2024 - Integración de Datos con Microsoft Fabric
 
International Women's Day Sucre 2024 (IWD)
International Women's Day Sucre 2024 (IWD)International Women's Day Sucre 2024 (IWD)
International Women's Day Sucre 2024 (IWD)
 
KELA Presentacion Costa Rica 2024 - evento Protégeles
KELA Presentacion Costa Rica 2024 - evento ProtégelesKELA Presentacion Costa Rica 2024 - evento Protégeles
KELA Presentacion Costa Rica 2024 - evento Protégeles
 
EPA-pdf resultado da prova presencial Uninove
EPA-pdf resultado da prova presencial UninoveEPA-pdf resultado da prova presencial Uninove
EPA-pdf resultado da prova presencial Uninove
 
Trabajo Mas Completo De Excel en clase tecnología
Trabajo Mas Completo De Excel en clase tecnologíaTrabajo Mas Completo De Excel en clase tecnología
Trabajo Mas Completo De Excel en clase tecnología
 
guía de registro de slideshare por Brayan Joseph
guía de registro de slideshare por Brayan Josephguía de registro de slideshare por Brayan Joseph
guía de registro de slideshare por Brayan Joseph
 
pruebas unitarias unitarias en java con JUNIT
pruebas unitarias unitarias en java con JUNITpruebas unitarias unitarias en java con JUNIT
pruebas unitarias unitarias en java con JUNIT
 
Redes direccionamiento y subredes ipv4 2024 .pdf
Redes direccionamiento y subredes ipv4 2024 .pdfRedes direccionamiento y subredes ipv4 2024 .pdf
Redes direccionamiento y subredes ipv4 2024 .pdf
 
Proyecto integrador. Las TIC en la sociedad S4.pptx
Proyecto integrador. Las TIC en la sociedad S4.pptxProyecto integrador. Las TIC en la sociedad S4.pptx
Proyecto integrador. Las TIC en la sociedad S4.pptx
 
trabajotecologiaisabella-240424003133-8f126965.pdf
trabajotecologiaisabella-240424003133-8f126965.pdftrabajotecologiaisabella-240424003133-8f126965.pdf
trabajotecologiaisabella-240424003133-8f126965.pdf
 
9egb-lengua y Literatura.pdf_texto del estudiante
9egb-lengua y Literatura.pdf_texto del estudiante9egb-lengua y Literatura.pdf_texto del estudiante
9egb-lengua y Literatura.pdf_texto del estudiante
 

Apache nifi_introduccion_v1.0

  • 1. pág. 1 “An Open Source Data Distribution and Processing System” Resumen – La idea central de este pequeño monográfico1 sobre Apache NiFi será tratar de entender tanto sus bases teoricas como pragmáticas. En una primera parte desarrollaremos sus aspectos teóricos desde el punto de vista de la programación basada en flujos y describiremos sus diferentes componentes. En una segunda parte nos centraremos en una serie de ejemplos sencillos que nos permitirán hacernos una idea del funcionamiento de Apache NiFi. Y en la parte final veremos algunos proyectos como NiFi registry y MiNiFi que proporcionaran capacidades muy interesantes al ecosistema de NiFi. Resaltar la idea de que NiFi es una herramienta que quedaría englobada dentro de la familia de los controladores de flujo de información y como tal, nos puede ser de gran utilidad para mover información entre nuestros diferentes stacks tecnológicos. Su integración con sistemas como Apache kafka, HDFS, ElasticShearch y numerosas bases de datos le hace candidato para resolver gran número de problematicas que podemos encontrar en nuestras arquitecturas empresariales. I. INTRODUCCIÓN. Hoy en día, uno de los principales problemas que tenemos dentro de las organizaciones, es controlar los flujos de información dentro de nuestros procesos para conseguir que dicha información llegue a donde tiene que llegar, con el formato óptimo y aportando el máximo valor posible. Siguiendo esta idea vamos a presentar Apache NiFi, una herramienta pensada y diseñada para la automatización de flujos de datos entre los diferentes sistemas software. Esta herramienta está basada en el software “NiagaraFile” desarrollado por la NSA y paso a ser de código abierto en 2014, año en que paso a ser parte de la fundación Apache. Antes de continuar con la explicación de los conceptos y partes de NiFi, vamos a enumerar algunos posibles casos de 1 Interesante remarcar que es un monográfico al que le he aportado estructura, forma y tiempo. El conocimiento estaba en Internet :) 2 https://en.wikipedia.org/wiki/Flow-based_programming#Concepts uso de esta tecnología dentro de nuestras arquitecturas empresariales: • Modelado de flujos de trabajo mediante data flows. • Conexión sencilla de los flujos de datos entre nuestros diferentes grupos de tecnologías. • Procesamiento masivo de datos (enriquecimiento, filtrado, procesamiento…). • Centralización de flujos de datos complejos. • Control de flujos permisionado. • ETL’s tradicionales. Si tenemos alguna de estas necesidades, o simplemente nos interesa ver una posible solución a ellas, NiFi puede ser un buen aliado y este documento nos servira de ayuda para entenderlo. Los conceptos de diseño fundamentales de NiFi están estrechamente relacionados con las ideas principales de la programación basada en flujos ( fbp)2 . Este paradigma de la programación se basa en definir las aplicaciones como redes de procesos de “caja negra”, que intercambian datos a través de conexiones predefinidas mediante el paso de mensajes, donde las conexiones se especifican externamente a los procesos. Estos procesos pueden reconectarse sin fin para formar diferentes aplicaciones sin tener que cambiarlos internamente. Desde este punto de vista se ve a una aplicación no como un solo proceso secuencial, que comienza en un punto en el tiempo, y luego hace una cosa a la vez hasta que finaliza, sino como una red de procesos asíncronos que se comunican por medio de flujos de fragmentos de datos estructurados, llamados “paquetes de información”. Siguiendo esta idea, el enfoque de esta herramienta estará centrado en los datos y las transformaciones aplicadas para producir los resultados deseados. Este tipo de paradigma presenta un acoplamiento de datos del tipo “loosely coupled” o acoplamiento flexible en el que cada uno de los componentes tiene, o utiliza, poco o ningún conocimiento de las definiciones de otros componentes separados. Este tipo de acoplamiento nos será muy útil para los diseños de los flujos de datos. Sabiendo que Apache NiFi se basa en la programación de flujos, vamos a ver cómo trata los diferentes conceptos de este tipo de programación y cómo se acoplan en su contexto. Algunos de los binomios principales son3 : FlowFile (Information Packet)4 . Un FlowFile representa cada objeto que se mueve a través del sistema y, para cada 3 https://nifi.apache.org/docs.html 4 Binomio: Concepto (Termino de referencia FBP).
  • 2. pág. 2 uno, NiFi realiza un seguimiento de un mapa de las cadenas de atributos de pares clave/valor y su contenido asociado de cero o más bytes. Los FlowFiles pueden ser clonados, combinados, partidos, modificados, transferidos y borrados. Algunos de los atributos comunes que podemos encontrar en este componente son: • Filename. Un nombre de archivo que se puede utilizar al almacenar datos localmente o en un sistema remoto. • Path. Directorio que podemos usar para guardar los datos. • Uuid. Identificador universal que nos permitirá identificar de forma inequívoca a un FlowFile. • Entydate. Fecha y hora de entra del FlowFile en el sistema. • lineageStarDate. La fecha y hora en que el antecesor más antiguo del archivo de flujo ingresó al sistema. • fileSize. Representa el número de bytes ocupado por el contenido del archivo de flujo. Ilustración 1 Componentes básicos de un FlowFile. FlowFile Processor (Black Box). Este componente es el que realiza el trabajo. En términos de patrones de integración, un procesador realizaría una combinación de enrutamiento, transformación o mediación de datos entre sistemas. Los procesadores tienen acceso a los atributos de un FlowFile dado y a su flujo de contenido. Pueden operar en cero o más archivos de flujo en una unidad de trabajo determinada y pueden confirmar ese trabajo o revertirlo. Algunos ejemplos típicos de FlowFile Processor pueden ser los siguientes: • Ingestion. o GetFile. Extraer contenido del disco local y borrar el fichero original. o GetSFTP. Extraer contenido vía ftp de un servidor remoto y borrar el original. • Routing. o RouteOnAttribute. Redirigir los FlowFiles en base a algún atributo específico. • Data transformation. o CompressContent. Comprimir o descomprimir el contenido. o ReplaceText. Uso de expresiones regulares para modificar el texto del contenido. • Data Egress. o PutFile. Escribir contenido del FlowFile en un directorio local. o PutSFTP. Copiar contenido del FlowFile en un servidor remoto vía SFTP. • Attribute Extraction. o UpdateAttribute. Añadir o actualizar atrabutos usando valores definidos estáticamente o dinámicamente mediante del uso del Expression Lenguaje de NiFi’s. o ExtractText. Creación de atributos basados en las expresiones regulares definidas por los usuarios. • Splitting and Aggregation. o Unpackcontent. Descomprir archivos como TAR y ZIP y mandar cada uno de los ficheros por separado al flujo de datos. Cuando un procesador trata de procesar un FlowFile suele tener definidas tres posibles salidas o terminaciones: • Failure. Si un FlowFile no se puede procesar correctamente, el FlowFile original se enrutará a esta salida. • Original. Una vez que se ha procesado el FlowFile entrante, el FlowFile original se enruta a esta salida. • Success. Los FlowFiles que se procesan correctamente se enrutarán a esta relación. Connection (Bounded Buffer). Las conexiones proporcionarán el enlace real entre los procesadores. Estos actúan como las colas y permiten que varios procesos interactúen a diferentes velocidades. Estas colas se pueden priorizar dinámicamente y pueden tener límites superiores en la carga, lo que permite controlar el back pressure. Ilustración 2 Ejemplo de dos procesadores conectados por una conexión. Connection Processor Processor ATRIBUTOS • Mapa de pares key/value. • Muy utilizados para tomar decisiones de enrutado. • Estos valores pueden ser accedidos por el Expression lenguaje de NiFi. CONTENIDO • Los datos reales que se enrutan a través del flujo de datos. • Puede ser manipulado múltiples veces a lo largo del flujo de datos.
  • 3. pág. 3 Si el procesador anterior se vuelve lento o se bloquea por algún motivo, los archivos de flujo generados por el procesador anterior se irán acumulando en la cola hasta llegar al límite de back pressure configurado. En ese momento se pausará el procesador anterior hasta que el contenido de la cola este por debajo del umbral configurado. Flow Controller (Scheduler). El controlador de flujo mantiene el conocimiento de cómo se conectan los procesos y administra los subprocesos y las asignaciones de estos que utilizan todos los procesos. El controlador de flujo actúa como el agente que facilita el intercambio de archivos de flujo entre los procesadores. Process Group (Subnet). Un grupo de procesos es un conjunto específico de procesos y sus conexiones, que pueden recibir datos a través de puertos de entrada y enviar datos a través de puertos de salida. De esta manera, los grupos de procesos permiten la creación de componentes completamente nuevos simplemente por la composición de otros componentes. Este modelo de diseño es muy parecido a SEDA5 y ayuda a Apache NiFi a ser una plataforma muy eficaz para crear flujos de datos potentes y escalables. Algunos de estos beneficios incluyen: • Potente gestión visual de los grafos dirigidos de procesadores de flujo de datos. • Es inherentemente asíncrono, lo que permite un rendimiento muy alto y un buffer natural incluso cuando el procesamiento y los caudales fluctúan. • Proporciona un modelo altamente concurrente sin que un desarrollador tenga que preocuparse por las complejidades típicas de la concurrencia. • Promueve el desarrollo de componentes cohesivos y poco acoplados que luego pueden reutilizarse en otros contextos y promueve unidades comprobables. • Las conexiones de recursos limitados hacen que las funciones críticas como la contrapresión y la liberación de presión sean muy naturales e intuitivas. • El manejo de errores es sencillo y ágil. • Los puntos en los que los datos entran y salen del sistema, así como la forma en que fluyen a través de él, se entienden bien y se pueden rastrear fácilmente. Continuemos enumerando algunas de las principales características que presenta Apache NiFi son: • La filosofía central de Apache NiFi es garantizar la entrega en entornos de alto rendimiento. Esto lo logra mediante el uso efectivo de un registro de escritura anticipada persistente y un repositorio de contenido. • Modelado de flujos mediante una potente UI que nos ayudarán a identificar y reducir la complejidad inerente a los flujos de datos. Nos permitirá también realizar cambios parciales. 5 Matt Welsh. Berkeley. SEDA: An Architecture for Well-Conditioned, Scalable Internet Services [online]. Retrieved: 18 Jan 2018, from: http://www.mdw.la/papers/seda-sosp01.pdf • Alta trazabilidad de los datos mediante el repositorio de procedencia. • Baja latencia con un alto rendimiento en la ejecución de los procesados. • Gestión eficiente de colas con QoS (Data buffering and Backpressure). • Escalado horizontalmente y verticalmente simple. • Dispone de transaccionalidad. • Seguridad incorporada (Roles, SSL/TLS,etc..). • Integración con una gran cantidad de aplicativos: HDFS, Elastic, MongoDB, BD SQL, FTP, Kafka, Flume. • Ejecución paralela mediante Zookeeper. • Funcionalidad ampliable mediante plugins y templates. • Seguridad multi-tenant. A nivel de arquitectura, Apache NiFi es un sistema basado en JAVA que presenta los siguientes componentes estructurales: Ilustración 3 Arquitectura Apache NiFi. Esta sería la arquitectura más sencilla, pero tenemos la posibilidad de levantar un clúster de NiFi basado en ZooKeeper, presentando la siguiente arquitectura característica: Ilustración 4 Arquitectura Apache NiFi cluster. NiFi emplea un paradigma de clusterización Zero-Master. Cada nodo en el clúster realiza las mismas tareas en los datos, pero cada uno opera en un conjunto diferente de datos. Uno de los nodos se elige automáticamente (a través de Apache ZooKeeper) como el Coordinador de Clúster. Todos los nodos del clúster enviarán información de heartbeat, y este nodo es responsable de desconectar los nodos que no reportan ningún estado de heartbeat durante un período de tiempo. Además, cuando un nuevo nodo elige unirse al clúster, el nuevo nodo, primero debe conectarse al
  • 4. pág. 4 Coordinador de clúster elegido actualmente para obtener el flujo más actualizado. Si el Coordinador de clústeres determina que el nodo tiene permiso para unirse, el flujo actual se proporciona a ese nodo, y ese nodo puede unirse al clúster, suponiendo que la copia del flujo del nodo coincida con la copia proporcionada por el Coordinador de clústeres. Si la versión del nodo de la configuración de flujo difiere de la del Coordinador de Clúster, el nodo no se unirá al clúster. El protocolo de comunicación entre los nodos del clúster suele ser NiFi Site-to-Site (S2S)6 Protocol. Un protocolo que permite una transferencia de datos sencilla, eficiente y segura. Vamos a describir por encima algunos de los componentes principales. En primer lugar, encontramos el servidor web cuyo propósito principal es servir el UI y el API de Apache NiFi. Luego encontramos el Flow Controller que está considerado como el centro de operaciones de la aplicación. Nos proporciona subprocesos para que se ejecuten las extensiones y además gestiona la planificación de ejecución. Los FlowFiles que están siendo procesados por NiFi se guardan en un mapa has en la memoria de la JVM haciendo que sea muy eficiente su procesamiento, pero haciendo necesario un mecanismo secundario para asegurar los datos. Ante esta contingencia nace el Flow File Repository. Este será el lugar donde se persista el seguimiento del estado de lo que sabemos sobre un FlowFile dado que actualmente está en activo en el flujo de datos. Desde el punto de vista técnico el repositorio de FlowFile es un "Registro de escritura anticipada" (o registro de datos) de los metadatos de cada uno de los FlowFiles que existen actualmente en el sistema. Estos metadatos de FlowFile incluyen todos los atributos asociados con FlowFile, un puntero al contenido real del FlowFile (que existe en el Content Repo) y el estado del FlowFile, como a qué conexión/cola pertenece el FlowFile. Esta escritura Ahead Log proporciona a NiFi la resistencia que necesita para manejar reinicios y fallos inesperados del sistema. Al funcionar el Repositorio de FlowFile como un registro de escritura anticipada, va registrando todos los cambios en el repositorio antes de que suceda como una unidad de trabajo transaccional. Esto permite que el sistema sepa exactamente en qué paso se encuentra el nodo al procesar parte de los datos. Si el nodo se apagará mientras procesa los datos, puede restaurarse desde donde se detuvo7 . El Content Repository será donde se almacenan los bytes de contenido real de un FlowFile dado. El enfoque de diseño predeterminado de este componente es sencillo. Almacena los bloques de datos en el sistema de archivos. Debido a este modo de funcionamiento, este componente puede presentar una gran demanda de IO por lo tiene la posibilidad de dividirse en varios volúmenes. Este repositorio utiliza los paradigmas de inmutabilidad y de copia en escritura para maximizar la velocidad y la seguridad de subprocesos. La decisión de diseño central que influye en el Repo de 6 https://community.hortonworks.com/articles/88473/site-to-site- communication-between-secured-https-a.html 7 El sistema toma automáticamente una instantánea, que crea una nueva instantánea para cada FlowFile. El sistema calcula un nuevo punto de control base al serializar cada FlowFile en el mapa hash y escribirlo en el disco con el nombre de archivo ".partial". A medida que avanza el punto de control, las nuevas líneas de base de FlowFile se escriben en el archivo ".partial". Contenido es mantener el contenido del FlowFile en el disco y leerlo solo en la memoria JVM cuando sea necesario. Esto permite a NiFi manejar objetos de tamaño pequeño y masivo sin requerir que los procesadores productores y consumidores mantengan los objetos completos en la memoria. Como resultado, acciones como dividir, agregar y transformar objetos muy grandes son bastante fáciles de hacer sin dañar la memoria. Para terminar esta breve descripción encontramos el Provenance Repository que es donde se almacenan todos los datos de procedencia, de forma que nos permitirá analizar la trazabilidad de un Flowfile. La implementación de este componente es muy parecida a la del anterior, con la única diferencia de que se le añaden las facultades de indexación8 y búsqueda. Como curiosidad podemos decir que cada evento de procedencia tiene dos mapas, uno para los atributos antes del evento y otro para los valores de atributos actualizados. En general, los eventos de procedencia no almacenan los valores actualizados de los atributos como existían cuando se emitió el evento, sino los valores de los atributos cuando se confirma la sesión. Los elementos se almacenan en caché y se guardan hasta que la sesión se confirma. Una vez que se confirma se graban en disco de forma encriptada mediante AES G/CM. Por último, enumeramos algunos subproyectos de Apache NiFi que serán muy interesantes para las diferentes implementaciones: • Apache NiFi Registry. Una aplicación central complementaría que proporciona una ubicación central para el almacenamiento y la gestión de recursos compartidos en una o más instancias de NiFi, como las plantillas. http://nifi.apache.org/registry.html • MiNiFi. Un enfoque complementario de recopilación de datos que completa los principio básicos de NiFi en la gestión del flujo de datos, y se centra en la recopilación de datos en la fuente de su creación. http://nifi.apache.org/minifi/index.html • Flow Design System (FDS). Una plataforma atómica reutilizable para proporcionar un conjunto común de componentes UI/UX para Apache NiFi, Apache Registry, Apache NiFi minifi y cualquier otra aplicación web de código abierto para consumir. http://nifi.apache.org/fds.html Una vez que se realiza el punto de control, el archivo "snapshot" anterior se elimina y el archivo ".partial" cambia de nombre por "snapshot". 8 Tecnicamente el Provenance Repo es un índice de Lucene que se divide en varios fragmentos ya que el número máximo de documentos adminitdos por Lucene sin fragmentación es limitado.
  • 5. pág. 5 II. INSTALACIÓN. Podemos realizar la instalación de Apache NiFi de diferentes formas. Directamente desde las fuentes, descargándonos los binarios o mediante entornos dockerizados. Encuadrándonos con el propósito de este documento sólo me centraré en la instalación básica en un entorno Linux estándar y la ejecución mediante un entorno Docker. A. Instalación en sistemas Linux. Para llevar a cabo la instalación de Apache NiFi necesitamos cumplir como requisito inicial, la instalación de Java. En mi caso he optado por instalar esta paquetería: ~/nifi/$ sudo apt install default-jre ~/nifi/$ java --version openjdk 10.0.2 2018-07-17 OpenJDK Runtime Environment (build 10.0.2+13-Ubuntu- 1ubuntu0.18.04.4) OpenJDK 64-Bit Server VM (build 10.0.2+13-Ubuntu- 1ubuntu0.18.04.4, mixed mode) sudo apt install default-jdk ~/nifi$ java --version openjdk 10.0.2 2018-07-17 Una vez instalado este requisito nos descargaremos la versión de NiFi que queremos instalar desde la siguiente página: https://nifi.apache.org/download.html En mi caso: nifi-1.8.0 ~/nifi$ wget http://apache.rediris.es/nifi/1.8.0/nifi-1.8.0- bin.tar.gz ~/nifi$ tar xvf nifi-1.8.0-bin.tar.gz ~/nifi$ cd nifi-1.8.0/ Una vez dentro de la carpeta que acabamos de descomprimir, entramos en la carpeta bin y ejecutamos el script: ~/nifi/nifi-1.8.0/bin$ ./nifi.sh --help Usage nifi {start|stop|run|restart|status|dump|install} Para arrancar la instancia: ~/nifi/nifi-1.8.0/bin$ ./nifi.sh start Comprobamos el estado del arranque: ~/nifi/nifi-1.8.0/bin$ ./nifi.sh status nifi.sh: JAVA_HOME not set; results may vary Java home: NiFi home: /home/gauss/nifi/nifi-1.8.0 Bootstrap Config File: /home/gauss/nifi/nifi- 1.8.0/conf/bootstrap.conf 2019-01-07 16:56:33,519 INFO [main] org.apache.nifi.bootstrap.Command Apache NiFi is currently running, listening to Bootstrap on port 33979, PID=11172 También podemos comprobar que el proceso está en máquina mediante $ ps -ef|grep nifi 9 En este caso amplio los límites para todos los usuarios pero lo normal sería crear un usuario específico para levantar NiFi y aumentarle los límites sólo a él. Si todo está arrancado correctamente podemos comprobar que NiFi está ejecutándose mediante el navegador, accediendo a: http://${IP_SERVER}:8080/nifi/ Ilustración 5 Pantalla Inicial de Apache NiFi. De esta forma estamos levantando el servicio de forma manual, si queremos instalar NiFi en nuestro sistema de forma que nos implemente los servicios deberemos ejecutar la siguiente opción: ~/nifi/nifi-1.8.0/bin$ ./nifi.sh install Llegado a este punto tendríamos instalado NiFi, pero nos faltaría optimizar algunos parámetros del sistema operativo ya que no viene configurado para aplicaciones con un uso intensivo de I/O como es el caso de Apache NiFi. Algunos de los parámetros que debemos modificar son: • Maximum File Hadles. NiFi puede necesitar abrir un gran número de ficheros por los que necesitamos incrementar los límites establecidos para los usuarios9 . Para ello deberemos editar el “/etc/security/limits.conf” y añadirle las siguientes líneas: * hard nofile 50000 * soft nofile 50000 • Maximum Forked Processes. Tenemos que configurar NiFi para que pueda generar un número elevado de procesos. Para incrementar este límite, volvemos a modificamos el fichero: “/etc/security/limits.conf” * hard nproc 10000 * soft nproc 10000 En algunas distribuciones deberemos editar también el fichero: “/etc/security/limits.d/90-nproc.conf “ en el que deberemos añadir:
  • 6. pág. 6 * soft nproc 10000 • Increase the number of TCP socket ports available. Esto es particularmente importante si nuestro flujo de trabajo abre y cierra muchos sockets en periodos cortos de tiempo. Lo podemos modificar de la siguiente forma: $ sudo sysctl -w net.ipv4.ip_local_port_range=”10000 65000” O añadirlo de forma permanente en el /etc/sysctl.conf • Set how long sockets stay in a TIMED_WAIT state when closed. Si lo que queremos, es tener velocidad a la hora de abrir y cerrar los sockets debemos modificar el siguiente parámetro: $ sudo sysctl -w net.ipv4.netfilter.ip_conntrack_tcp_timeout_time_wait="1" O añadirlo de forma permanente en el /etc/sysctl.conf • Deshabilitar el uso de la swap. Para ello añadimos la siguiente línea en el ‘/etc/sysctl.conf’: vm.swappiness = 0 • Disable partition atime. En todas aquellas particiones en las que funcione Apache Nifi, debemos deshabilitar características como ‘atime10 ’. Para ello deberemos editar el fichero /etc/fstab y añadir ‘noatime’ en todas aquellas particiones que se vean afectadas. No me voy a extender más con los parámetros, pero en una instalación real seguramente deberíamos optimizar alguno más. B. Ejecución desde Docker. Para usar la imagen de Docker11 oficial bastará con ejecutar: $ docker pull apache/nifi Using default tag: latest latest: Pulling from apache/nifi Digest: sha256:7a7586766ab9848d6b91f061b081748c9519075c3e41bcab7f501b8 bf4367cdf Status: Image is up to date for apache/nifi:latest Esto nos descargará a nuestro repositorio local la imagen de apache NiFi. Lo podemos comprobar con: $ docker images|grep nifi apache/nifi latest 6c3cb8a4ae0e 2 months ago 1.83GB Podemos encontrar el Dockerfile original y la documentación en: https://hub.docker.com/r/apache/nifi 10 “atime” es una propiedad del sistema de ficheros por la cual guarda el “access time” cada vez que accedemos o leemos un fichero. Para evitar esto, lo deshabilitamos mediante el uso de “noatime” optimizando considerablemente el rendimiento del filesystem en determinados escenarios. Tenemos la opción de descargarnos el repo (https://github.com/apache/nifi/tree/master/nifi-docker) con el Dockerfile y crear la imagen mediante: $ docker build -t apache/nifi:latest . Esta imagen lleva incluido el toolkit de NiFi en la ruta /opt/nifi/nifi-toolkit-current y la instalación del producto se realiza en /opt/nifi/nifi-current . Podemos comprobar estas rutas mediante: $ docker run --rm --entrypoint /bin/bash apache/nifi -c 'env|grep NIFI' NIFI_HOME=/opt/nifi/nifi-current NIFI_LOG_DIR=/opt/nifi/nifi-current/logs NIFI_TOOLKIT_HOME=/opt/nifi/nifi-toolkit-current NIFI_PID_DIR=/opt/nifi/nifi-current/run NIFI_BASE_DIR=/opt/nifi Esta imagen la podemos ejecutar en modo standalone y mediante dos métodos de autenticación12 : • Two-Way SSL with Client Certificates. • Lightweight Directory Access Protocol (LDAP) Para levantar NiFi desde el docker bastará con ejecutar lo siguiente: $ docker run --name nifi -p 8080:8080 -d apache/nifi:latest $ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES b35fad6a1380 apache/nifi:latest "../scripts/start.sh" 51 seconds ago Up 50 seconds 8443/tcp, 0.0.0.0:8080- >8080/tcp, 10000/tcp nifi Comprobamos que todo esta funcionando correctamente en la url del producto: http://localhost:8080/nifi Si queremos modificar alguna de las variables de arranque podemos pasar variables a la imagen de la siguiente forma: $ docker run --name nifi -p 9090:9090 -d -e NIFI_WEB_HTTP_PORT='9090' apache/nifi:latest 39adbe525bdbed8ebc277e18910e31b3254758876c8a5c593940c55568cfb2 2f $ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 39adbe525bdb apache/nifi:latest "../scripts/start.sh" 4 seconds ago Up 3 seconds 8080/tcp, 8443/tcp, 10000/tcp, 0.0.0.0:9090->9090/tcp nifi Podemos ver las variables disponibles e incluso añadir o modificar en el fichero: https://github.com/apache/nifi/blob/master/nifi- docker/dockerhub/sh/start.sh Si queremos usar sólo la parte de las Toolkit lo podemos hacer mediante: $ docker run -d --name nifi apache/nifi $ docker exec -ti nifi /opt/nifi/nifi-toolkit- current/bin/cli.sh nifi current-user anonymous 11 Necesitamos tener instalado Docker en nuestra distribución. 12 https://hub.docker.com/r/apache/nifi
  • 7. pág. 7 $ docker exec -ti nifi /opt/nifi/nifi-toolkit-current/bin/cli.sh _ ___ _ Apache (_) .' ..](_) , _ .--. __ _| |_ __ ) [ `.-. | [ |'-| |-'[ | / | | | | | | | | | | ' ' [___||__][___][___] [___]', ,' `' CLI v1.8.0 Type 'help' to see a list of available commands, use tab to auto- complete. Session loaded from /home/nifi/.nifi-cli.config #> exit C. Archivos de configuración. Llegado este punto ya podríamos tener levantado un Apache NiFi así ahora nos vamos a centrar en examinar más detenidamente sus ficheros de configuración. Ilustración 6 Apache Nifi y sus ficheros de configuración. Basado en: https://www.slideshare.net/IsheetaSanghi/apache-nifi-minifi- meetup-slides?next_slideshow=1 1. conf/nifi.properties Este es el archivo principal de configuración y se encuentra dividido en diferentes secciones que contienen numerosas variables pre-configuradas por defecto. Se que es muy aburrido ver todas las variables de configuración, pero me ha parecido interesante poner la mayoría de las secciones para por lo menos verlas una vez. # Core Properties # nifi.flow.configuration.file=./conf/flow.xml.gz nifi.flow.configuration.archive.enabled=true nifi.flow.configuration.archive.dir=./conf/archive/ nifi.flow.configuration.archive.max.time=30 days nifi.flow.configuration.archive.max.storage=500 MB nifi.flow.configuration.archive.max.count= nifi.flowcontroller.autoResumeState=true nifi.flowcontroller.graceful.shutdown.period=10 sec nifi.flowservice.writedelay.interval=500 ms nifi.administrative.yield.duration=30 sec # If a component has no work to do (is "bored"), how long should we wait before checking again for work? nifi.bored.yield.duration=10 millis nifi.queue.backpressure.count=10000 nifi.queue.backpressure.size=1 GB nifi.authorizer.configuration.file=./conf/authorizers.xml nifi.login.identity.provider.configuration.file=./conf/login- identity-providers.xml nifi.templates.directory=./conf/templates nifi.ui.banner.text= nifi.ui.autorefresh.interval=30 sec nifi.nar.library.directory=./lib nifi.nar.working.directory=./work/nar/ nifi.documentation.working.directory=./work/docs/components En este primer bloque encontramos algunos parámetros interesantes como las configuraciones de las colas que soportan las conexiones entre los procesadores. El backpresure.count definir el número de mensajes capaz de soportar hasta parar el procesador. Lo mismo para el backpressure.size que definirá el tamaño máximo de la cola. Manejar estos parámetros adecuadamente nos puede ayudar a definir los intervalos de retención para nuestros flujos de información. nifi.queue.backpressure.count=10000 nifi.queue.backpressure.size=1 GB Un parámetro muy interesante que afecta directamente al rendimiento del funcionamiento de Apache NiFi es: nifi.bored.yield.duration=10 millis Este parámetro está diseñado para ayudar con el control de uso de la CPU. Evita que los procesadores, que utilizan la estrategia de programación controlada por temporizador, utilicen de forma excesiva la CPU cuando no tienen trabajo que realizar. El valor por defecto de 10 milisegundos ya tiene un gran impacto en la reducción de la utilización de CPU. Si nuestro flujo necesitará una menor latencia podremos bajar este parámetro incrementando el uso de la CPU. Por el contrario, si la latencia(controlada) no es un limitante podemos aumentar este parámetro para reducir el uso de CPU. Otro parámetro interesante en esta sección afecta al impacto del rendimiento del navegador: nifi.ui.autorefresh.interval=30 sec Esta propiedad establece el valor del tiempo de actualización del navegador del cliente conectado. Podemos disminuir este tiempo de actualización a costa de un mayor consumo de procesamiento y un mayor ancho de banda. Deberemos tener en cuenta el número de usuarios conectado ya que también incrementa las necesidades de la aplicación. Apache NiFi recomienda mantener el valor predeterminado y sólo cambiarlo en entornos donde se necesiten ver estadísticas en tiempo real. El usuario siempre tiene la opción de activar manualmente la actualización. # H2 Setting # En esta sección se definen parámetros relacionados con las bases de datos de uso interno. nifi.database.directory=./database_repository nifi.h2.url.append=;LOCK_TIMEOUT=25000;WRITE_DELAY=0;AUTO_SERV ER=FALSE NiFi usa dos bases de datos. Una para usuarios, donde realiza un seguimiento de los logins en la aplicación simpre y cuando estén habilitadas las opciones de login. Y una base de datos de histórico donde se guardan los datos de los gráficos. Normalmente no suelen ser bases de datos grandes. La ruta de instalación predeterminada de estas bases de datos suele ser <root-level-nifi-dir>/database_repository por lo
  • 8. pág. 8 que el directorio se crea en el nivel raíz de la instalación de NiFi (el mismo nivel que los directorios conf, bin, lib, etc.). Si bien hay poco o ningún aumento de rendimiento al mover esto a una nueva ubicación, se recomienda mover todos los repositorios a una ubicación fuera de los directorios de instalación de NiFi. Es poco probable que el usuario o las bases de datos de historial cambien entre las versiones de NiFi, por lo que moverlo fuera de la ruta de instalación básica puede simplificar la actualización; permitiéndonos conservar la información básica de usuario y el historial de componentes después de la actualización. # FlowFile Repository # Aquí se definen los parámetros de configuración más importantes del corazón de NiFi, el repositorio de FlowFiles. En este repositorio es donde se mantiene el estado de todos los FlowFiles actualmente ubicados en cualquier lugar de los flujos de datos en la interfaz de usuario de NiFi. Si se corrompe, existe la posibilidad de que podamos perder el acceso a algunos o todos los archivos que corren por NiFi. La causa más común de corrupción es el resultado de quedarse sin espacio en el disco. nifi.flowfile.repository.implementation=org.apache.nifi.contro ller.repository.WriteAheadFlowFileRepository nifi.flowfile.repository.wal.implementation=org.apache.nifi.wa li.SequentialAccessWriteAheadLog nifi.flowfile.repository.directory=./flowfile_repository nifi.flowfile.repository.partitions=256 nifi.flowfile.repository.checkpoint.interval=2 mins nifi.flowfile.repository.always.sync=false nifi.swap.manager.implementation=org.apache.nifi.controller.Fi leSystemSwapManager nifi.queue.swap.threshold=20000 nifi.swap.in.period=5 sec nifi.swap.in.threads=1 nifi.swap.out.period=5 sec nifi.swap.out.threads=4 Vemos que la ruta por defecto es <root-level-nifi-dir>/ flowfile_repository. Por temas de seguridad y rendimiento es recomendable que este directorio se saque fuera de la instalación base donde este soportado por un volumen con alto rendimiento de E/S. En los sistemas de alto rendimiento, este repositorio nunca debería estar con el repositorio de contenido que veremos en las próximas secciones. Otro parámetro a tener en cuenta de esta sección es el siguiente: nifi.queue.swap.threshold=20000 NiFi usa los FlowFiles como la unidad de transferencia de un procesador a otro. Para que esto sea lo más rápido posible, estos FlowFiles viven(felizmente) dentro de la RAM de la JVM. Esta técnica es muy buena, hasta que comenzamos a tener miles de FlowFiles y nuestra JVM comienza a sufrir por falta de memoria. Para reducir la probabilidad de que esto ocurra, NiFi define el umbral de FlowFiles que pueden vivir en la memoria en una sola cola de conexión antes de ser escritos en el disco. Una vez alcanzado el umbral se producirá el intercambio a disco. Dependiendo de la frecuencia de intercambio el rendimiento del sistema se puede ver afectado. Para evitar esto deberemos encontrar el equilibrio entre este umbral y la memoria disponible en la máquina virtual. Más adelante veremos que las características de la máquina virtual de java las configuraremos en el archivo bootstrap.conf. # Content Repository # Dado que el contenido para cada FlowFile que consume NiFi se coloca dentro del repositorio de contenido, este directorio soportará una gran demanda de I/O. Por esto, como en el caso anterior se recomienda sacar esta ruta del directorio de instalación básico. nifi.content.repository.implementation=org.apache.nifi.control ler.repository.FileSystemRepository nifi.content.claim.max.appendable.size=1 MB nifi.content.claim.max.flow.files=100 nifi.content.repository.directory.default=./content_repository nifi.content.repository.archive.max.retention.period=12 hours nifi.content.repository.archive.max.usage.percentage=50% nifi.content.repository.archive.enabled=true nifi.content.repository.always.sync=false nifi.content.viewer.url=../nifi-content-viewer/ En ocasiones este repositorio puede ser muy demandante de I/O por lo que un solo volumen puede ser escaso. Para prevenir esto NiFi nos permitirá configurar múltiples repositorios de contenido que puede usar de forma Road Robin. La configuración de estos repositorios de contenido adicional es relativamente sencilla. Deberemos comentar la línea del contenedor default y añadir una nueva línea para cada repositorio que queramos agregar, sustituyendo default por el identificador único que queramos. Un ejemplo: nifi.content.repository.directory.contS1R1=/cont- repo1/content_repository nifi.content.repository.directory.contS1R2=/cont- repo2/content_repository nifi.content.repository.directory.contS1R3=/cont- repo3/content_repository # Provenance Repository # Esta sección hace referencia al repositorio de provenance y será la última que trataremos. De forma similar al repositorio de contenido, el repositorio de provenance puede usar una gran cantidad de I/Os de disco para leer y escribir los eventos de procedencia. También deberemos de tener en cuenta que estas consultas de eventos se pueden hacer en paralelo por diferentes usuarios por lo que necesitaremos un mayor rendimiento de los discos. La configuración predeterminada nos creará el repositorio de provenance en la siguiente ruta: nifi.provenance.repository.directory.default=./provenance_repo sitory Desde Apache NiFi nos recomiendan que este repositorio este también es su propio volumen y que no lo comparta con ninguno de los otros repositorios. Al igual que el repositorio de contenido, se pueden definir múltiples repositorios de provenance al proporcionar nombres únicos en lugar de 'default' y rutas: nifi.provenance.repository.directory.provS1R1=/prov- repo1/provenance_repository
  • 9. pág. 9 nifi.provenance.repository.directory.provS1R2=/prov- repo2/provenance_repository La capacidad de consultar la información de procedencia de los archivos suele tener un gran valor para ciertos tipos de usuario. El número de subprocesos que están disponibles para realizar estas consultas de procedencia se define en: nifi.provenance.repository.query.threads = 2 En los sistemas en los que numerosos usuarios pueden realizar consultas simultáneas en el repositorio de procedencias, puede ser necesario aumentar el número de subprocesos asignados a este proceso. Si usamos a menudo esta característica puede ser interesante modificar la cantidad de subprocesos que se usaran para indexar los eventos de procedencia. El parámetro que deberemos editar será: nifi.provenance.repository.index.threads = 1 Para flujos que operan en un número muy alto de archivos de flujo, la indexación de eventos de procedencia podría convertirse en un cuello de botella. Si este es el caso, aparecerá una notificación indicando: "La velocidad del flujo de datos está excediendo la velocidad de registro de procedencia. Disminuyendo la velocidad del flujo para adaptarse". Si esto sucede, aumentar el valor de esta propiedad puede aumentar la velocidad a la que el repositorio de provenance puede procesar estos registros, lo que puede resultar en una mejora del rendimiento general. Otro parámetro que tenemos que tener en cuenta cuando consultamos la procedencia es el tamaño del bloque configurado ya que tiene impacto en la cantidad de almacenamiento dinámico que se utilizará en el proceso. Esta característica se configura en el siguiente parámetro: nifi.provenance.repository.index.shard.size = 500 MB Valores altos de este parámetro implicarán un mayor uso de la pila de java pero proporcionará un mejor rendimiento. Si aumentamos el tamaño del bloque, es posible que debamos aumentar el tamaño de la memoria asignada a java. Por regla general el tamaño de bloque debe ser más pequeño que el 50% del tamaño de almacenamiento configurado para el repositorio de provenance que se configura en el siguiente parámetro: nifi.provenance.repository.max.storage.size Para finalizar indicar que aunque este repositorio de provenance no se puede desactivar, si podemos cambiar su configuración de "PersistentProvenanceRepository" a "VolatileProvenanceRepository" Esto provocará que toda la información de referencia se almacenará en la memoria asignada a la máquina virtual de java. Para evitar saturarla podemos configurar el parámetro: nifi.provenance.repository.buffer.size = 100000 13 Basado en: https://www.digitalocean.com/community/tutorials/how-to- install-and-use-docker-on-ubuntu-18-04 Este valor se establece en bytes y mantendrá contenido el uso de la memoria. Esta es una buena opción, pero tendremos un historial de procedencia limitado. En las nuevas implementaciones de Apache NiFi se está implementando una nueva opción denominada WriteAheadProvenanceRepository. Esta opción parece mejorar los rendimientos para volúmenes altos de datos, pero parece que actualmente presenta algunos problemas con la reutilización de la memoria de la pila de java. 2. Archivo Bootstrap.conf Este archivo de configuración nos permite configurar las opciones de configuración inicial de NiFi. Esto incluye la parametrización de java como el tamaño de la heap. Este fichero también se divide en secciones. # JVM memory settings # java.arg.2=-Xms512m java.arg.3=-Xmx512m En esta sección controlamos la cantidad de memoria de almacenamiento dinámico que puede utilizar la JVM de Apache Nifi. Los parámetros básicos de configuración son los que usamos normalmente en la configuración de java, por un lado “Xms” definirá la asignación de memoria inicial y “Xmx” la memoria máxima que podrá alcanzar la JVM. Como podemos observar, los valores que vienen configurados por defecto no son óptimos para entornos de producción, por lo que los deberemos modificar en función de nuestros recursos y necesidades. Valores que pueden ser buenos para comenzar son de 4GB y 8GB respectivamente. Un buen indicativo de que necesitamos tocar estos valores es encontrar algún erro de “out of memory” en el log de la aplicación de NiFi. Al aumentar el tamaño de esta memoria tenemos que tener en cuenta los problemas de rendimiento que podemos sufrir por el garbage collector por lo que se recomienda realizar una configuración adecuada o utilizar un garbage collector más eficiente. III. EJEMPLO I. Treas a realizar: [1] Instalar docker y docker-compose. [2] Levantar apache NiFi. [3] Añadir y configurar los procesadores: GenerateFlowFile y Putfile. [4] Pruebas básicas de funcionamiento. Para este primer ejemplo no vamos a ser muy originales y vamos a ver un “hola mundo” en Apache Nifi. Para levantar el entorno de pruebas usaremos una máquina virtual Ubuntu (18.04) sobre la que levantaremos un Docker. La instalación y optimización de Docker no es objeto de este documento por lo que simplemente pondremos los comandos de instalación sin explicación alguna13 : $ sudo apt update
  • 10. pág. 10 $ sudo apt install apt-transport-https ca-certificates curl software-properties-common $ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add – $ sudo add-apt-repository "deb [arch=amd64] $ https://download.docker.com/linux/ubuntu bionic stable" $ sudo apt update $ sudo apt install docker-ce $ sudo systemctl status Docker $ sudo usermod -aG docker ${USER}14 Después de comprobar que docker funciona correctamente pasamos a levantar nuestro entorno NiFi de pruebas. Para ello simplemente ejecutaremos: $ docker run --name nifi -p 8080:8080 -d apache/nifi:latest Unable to find image 'apache/nifi:latest' locally latest: Pulling from apache/nifi bc9ab73e5b14: Pull complete 193a6306c92a: Pull complete e5c3f8c317dc: Pull complete d21441932c53: Pull complete fa76b0d25092: Pull complete 346fd8610875: Pull complete a77dac7d6f90: Pull complete 6907d655b86d: Pull complete 6b80dc86d1b8: Pull complete 2c6dbb557fc3: Pull complete 83ed9735618c: Pull complete 32697d3c6fd5: Pull complete 4ba9e676ab44: Pull complete Digest: sha256:7a7586766ab9848d6b91f061b081748c9519075c3e41bcab7f501b8 bf4367cdf Status: Downloaded newer image for apache/nifi:latest 4ff09c12dd7564898cd46cd7d8c9e04dcf7d98b827afcb15098f23b3c9b7c3 79 $ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 1bf29337005f apache/nifi:latest "../scripts/start.sh" 4 seconds ago Up 3 seconds 8443/tcp, 0.0.0.0:8080- >8080/tcp, 10000/tcp nifi Podemos comprobar que NiFi está funcionando mediante el navegador accediendo a localhost:8080/nifi ó ${IP_SERVER}:8080/nifi. También lo podemos comprobar con un simple curl. Ilustración 7 Consola inicial de Apache NiFi. No vamos a explicar todas las opciones de la consola ya que podemos encontrar toda la información necesaria en: https://nifi.apache.org/docs.html Una vez levantado nuestro bonito entorno de pruebas, vamos a centrar un poco lo que queremos hacer. Crearemos un par 14 Esta parte es opcional y hace referencia a dar permisos de ejecución a un usuario para ejecutar dockers. Normalmente funciona mejor poniendo directamente el usuario y reiniciando la sesión. de procesador, uno que nos generará FlowFiles a demanda y otro que los recogerá y los escribirá en un fichero. Es un ejemplo muy sencillo pero que nos servirá de base para explicar algunos conceptos básicos. Comenzaremos añadiendo nuestro primer procesador, para ello debemos seleccionar el icono de procesador y arrastrarlo hasta el panel principal. En este momento nos aparecerá una ventana emergente donde nos aparecerán todos los procesadores que NiFi nos ofrece por defecto (268). Podemos ampliar esta lista con procesadores creados a medida mediante los ficheros .nar. Ilustración 8 Ventana para añadir procesadores. Para nuestro ejemplo, vamos a usar un procesador denominado “GenerateFlowFile”. Para buscarlo podemos usar el filtro de la parte superior derecha. Ilustración 9 Ejempo1. selección de procesador. Una vez seleccionado nos aparecerá nuestro primer procesador. Indicar que el triángulo amarillo que nos aparece es un indicador de que el procesador no está configurado correctamente. Ilustración 10 Ejemplo 1. Primer procesador añadido.
  • 11. pág. 11 Para ver las operatorios que podemos realizar sobre el procesador bastará con pulsar con botón derecho sobre el mismo: Ilustración 11 Ejemplo 1. Menu configuración procesador. Seleccionamos la opción de configure y accederemos a la parte de configuración del procesador. Vamos a ir explicando un poco las diferentes secciones y a la vez configurando nuestro nuevo procesador: • Configuración (Settings). Esta pestaña nos permitirá renombrar el procesador y cambiar las configuraciones de las relaciones de terminación automática. Si un procesador permite que se creen relaciones definidas por el usuario (como RouteOnAttribute), también nos aparecerían aquí después de crearse. Otras configuraciones que podremos hacer hacen referencia al rendimiento, duración y el manejo de reintentos. Ilustración 12 Configure Processor. Settings. En este parte sólo marcaremos el check de success para definir la terminación de la relación. • Planificación (Scheduling). NiFi proporciona varias posibilidades de planificación para los procesadores. Para la mayoría de los casos, el temporizador suele ser la estrategia más apropiada, aunque podremos utilizar otras como la basada en eventos. Deberemos tener en cuenta los problemas de rendimiento de las diferentes configuraciones. En esta misma pestaña también podremos configurar el número de procesos adicionales que puede usar el procesador. Ilustración 13 Configure Processor. Scheduling. Dejamos todo por defecto menos el tiempo de planificación que lo pasamos a 5 segundos. • Propiedades (Properties). En este apartado configuramos las propiedades del procesador. En muchos casos tendremos numerosas variables por defecto que podremos configurar a las que les podemos añadir aquellas que creamos necesarias. En este caso vamos a modificar el tamaño del FlowFile generado a 5kb y le vamos a añadir un texto customizado, “Hola Mundo!!!!!!!!!”. Ilustración 14 Configure Processor. Properties. Podemos observar que una vez configurado el procesador el icono del triángulo pasa a un cuadrado rojo indicando que el procesador está parado. • Comentarios (Comments). Nos permite añadir comentarios sobre los procesadores para documentar un poco el sentido del procesador en el flujo que ejecutamos. Una vez configurado nuestro primer procesador pasamos al segundo que será “PutFile” que nos permitirá escribir los FlowFiles generados con anterioridad a fichero. Como en el caso anterior accedemos a la configuración y modificamos el apartado de settings en el que marcaremos los checkbox de failure y success. Luego pasaremos a las Property y simplemente añadiremos el directorio de destino (tmp).
  • 12. pág. 12 Ilustración 15 ejemplo 1. PutFile processor. Propiedades. Una vez configurado vamos a crear nuestra primera conexión. Para ello nos ponemos encima del primer procesador creado y nos aparecerá una flecha que seleccionamos y arrastramos hasta el segundo procesador. En ese momento nos aparecerá un cuadro de configuración donde podremos definir cómo se va a gestionar la asociación que acabamos de crear. Dejando de lado en la pestaña de ‘Details’ pasamos a ‘settings’ que es la realmente interesante. Ilustración 16 Ejemplo 1. Propiedades conexión. En este apartado encontraremos los siguientes parámetros de configuración: • Name. Nombre de la conexión. • FlowFile Expiration. El tiempo máximo que el FlowFile puede permanecer en la cola antes de ser eliminado. • Back Pressure. Número máximo de objetos que pueden ser almacenados en la cola antes de que el back pressure comience a aplicarse. • Size Threshold. Tamaño máximo de la cola. • Load Balance Strategy. Como balancear los datos de esta conexión en los nodos del clúster de NiFi. Las opciones pueden ser: o Do not load balance. o Partition by attribute. o Round robin. o Single node. • Prioritizers. Definimos el modo de selección de los FlowFile de esta cola. Las opciones son las siguientes: Este es nuestro primer ejemplo así que lo dejaremos todo por defecto. Aunque en desarrollos más complejos puede ser interesante estudiar estas configuraciones. Después de esta sencilla configuración ya tenemos nuestro primer flujo de datos implementado. Ahora podremos ejecutarlo de forma secuencial o total desde el panel de operación. Ilustración 17 Panel de operación. Ilustración 18 Ejemplo I. Para esta primera prueba recomiendo lanzarlo de forma secuencial para poder ir viendo lo que pasa en cada punto de nuestro flujo. Comenzaremos lanzando el primer procesador(GenerateFlowFile). El refresh está configura a 30 segundos así que si queremos ver como se están generando los ficheros lo podremos hacer con botón derecho actualizar. Veremos cómo los mensajes se nos están acumulando en la cola de la conexión y no sólo eso, con botón derecho vemos que nos aparecen opciones interesantes sobre esta cola:
  • 13. pág. 13 Ilustración 19 Opciones de la cola. Tendremos la opción de vaciar la cola, ver los históricos de utilización de esta e incluso listar y ver los mensajes de la misma. Para ello seleccionamos lo opción de “List queque”. Ilustración 20 Listando el contenido de la cola. Aunque en la imagen no se ve correctamente tenemos dos botones muy interesantes. Uno al inicio que nos dará acceso a los datos del FlowFile: Ilustración 21 Visualización de contenido de una cola. Esta es una funcionalidad muy interesante y nos puede ayudar mucho a saber que está pasando en nuestro flujo de datos. El otro icono interesante lo encontramos al final y nos dará acceso a los datos de procedencia. En este caso es muy simple: Ilustración 22 Esquema de procedencia. Vamos a continuar con el ejemplo, arrancando todos los procesadores y comprobando que los ficheros se están creando en el tmp. Ilustración 23 Ejemplo en ejecución. Para comprobar si se están creando los ficheros, deberemos entrar en la consola del Docker: gauss@gauss-virtual-machine:~/NIFI/EJEMPLOS/Hola_mundo/tmp$ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 1bf29337005f apache/nifi:latest "../scripts/start.sh" About an hour ago Up About an hour 8443/tcp, 0.0.0.0:8080- >8080/tcp, 10000/tcp nifi gauss@gauss-virtual-machine:~/NIFI/EJEMPLOS/Hola_mundo/tmp$ docker exec -i -t 1bf29337005f /bin/bash nifi@1bf29337005f:/opt/nifi/nifi-current$
  • 14. pág. 14 Una vez dentro nos vamos al directorio tmp y hacemos la comprobación. nifi@1bf29337005f:~$ cd /tmp/ nifi@1bf29337005f:/tmp$ ls 06cf354e-e067-4662-805b-e28627110b9d 2566dc4f-d19a-4ee7-9af1- 818f019b7641 551cbc7f-942a-4c1a-91db-98acb58aa97f 91fa4985- b009-48ca-9716-c29ccd21b137 d46eebe1-c6ae-44e1-b569- ea96848128d9 0754dfb5-d5a6-4c8c-8547-3ed5b9d70116 269f0d91-57f0-46ba-8e46- c0084761e49b 5f44c5b2-c61f-4f52-b541-4f6dce0b16fd 95ffa794- fc21-4937-8583-cd23c9e81a98 dbac411a-4825-47e9-89e5- 6f3a10f0a387 088e4f25-6536-40d7-9781-c6e40caabfa0 27e7702a-aecf-46a2-aee0- d02c19f6b711 6ee250c2-7e9e-4570-a858-932a1eed3de0 ……………………………………………. nifi@1bf29337005f:/tmp$ cat 06cf354e-e067-4662-805b- e28627110b9d Hola Mundo!!!!!!!!nifi@1bf29337005f:/tmp$ Viendo que todo funciona correctamente podemos parar los procesadores. Antes de terminar este ejemplo vamos a ver cómo podemos exportar estos flujos e importarlos. Para ello bastará con que en la sección de operación seleccionemos el icono que contiene un disco (Create template). Nos aparecerá un pequeño cuadro en el que sólo nos piden el nombre y una pequeña descripción. Con eso creamos nuestro primer template. Si lo queremos descargar deberemos ir al menú de configuración general y seleccionar la opción de templates. Ilustración 24 Opciones generales. Ilustración 25 NiFi Templates. El botón de la derecha nos permitirá descargarnos el template en formato xml. Este fichero podría/debería ser guardado en el repositorio de código correspondiente. Para volverlo a cargar bastará con que seleccionemos la opción de upload template de la consola de operate. Finalmente desplegar un template se realiza desde el menú de los procesadores. Este ha sido un ejemplo sencillo, pero nos ha valido para explicar algunos de los modos de funcionamiento de NiFi y sobre todo familiarizarnos con en el entorno. Este ejemplo y todos los demas estan disponibles en el sigueinte repositorio de githup: https://github.com/vthot4/poc_nifi IV. EJEMPLO II. Treas a realizar: [1] Levantar infraestructura necesaria medainte el docker- compose. [2] Añadir y configurar los procesadores necesarios [3] Pruebas básicas de funcionamiento. En este ejemplo vamos a ver una integración sencilla compuesta de los siguientes componentes: Ilustración 26 Integración Twitter, Apache Kafka, MongoDB.
  • 15. pág. 15 La prueba constará de una simple ingesta de datos desde Twitter mediante un procesador de NiFi que nos permitirá tratar e insertar esos datos en una cola de Kafka para que finalmente sean escritos en MongoDB o en raw en un filesystem. La idea es ver de forma general cómo funcionan los diferentes componentes de NiFi y sobre todo probar el control que nos ofrece sobre los flujos de datos de la prueba. Primeramente, necesitamos levantar los diferentes componentes, para ello hemos creado un simple Docker- compose que nos permita levantar el entorno de forma ágil y sencilla. Si no tenemos instalado docker-compose en nuestro sistema lo podemos hacer de la siguiente forma: $ sudo curl -L "https://github.com/docker/compose/releases/download/1.23.2/do cker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose $ sudo chmod +x /usr/local/bin/docker-compose $ docker-compose --version docker-compose version 1.23.2, build 1110ad01 El docker-compose que hemos creado para la prueba es el siguiente: --- version: '3.1' ## Component: PoC Nifi Ejemplo: Twitter-Kafka-MongoDB ## Version: 0.2 ## Author: Versia Tecnologías Emergentes ## networks: labnet: driver: bridge services: mongo: image: mongo container_name: Poc_nifi_mongodb restart: always ports: - "27017:27017" #environment: #MONGO_INITDB_ROOT_USERNAME: root #MONGO_INITDB_ROOT_PASSWORD: networks: - labnet mongo-express: image: mongo-express container_name: Poc_nifi_mongo_express restart: always ports: - "8081:8081" environment: #ME_CONFIG_MONGODB_ADMINUSERNAME: root #ME_CINFIG_MONGODB_ADMINPASSWORD: ME_CONFIG_BASICAUTH_USERNAME: admin ME_CONFIG_BASICAUTH_PASSWORD: admin depends_on: - mongo networks: - labnet zookeeper: image: confluentinc/cp-zookeeper:latest container_name: Poc_nifi_zookeeper environment: ZOOKEEPER_CLIENT_PORT: 2181 ZOOKEEPER_TICK_TIME: 2000 networks: - labnet kafka: image: confluentinc/cp-kafka:latest container_name: Poc_nifi_kafka depends_on: - zookeeper ports: - "9092:9092" environment: KAFKA_BROKER_ID: 1 KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:29092,PLAINTEXT_HOST://kafka:9092 KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 networks: - labnet nifi: image: apache/nifi container_name: Poc_nifi_nifi ports: - "8080:8080" environment: - NIFI_WEB_HTTP_PORT=8080 networks: - labnet Para levantar el entorno de pruebas bastará con ejecutar: $ docker-compose up -d Creating network "twitter_kafka_mongodb_labnet" with driver "bridge" Creating Poc_nifi_mongodb ... done Creating Poc_nifi_zookeeper ... done Creating Poc_nifi_nifi ... done Creating Poc_nifi_mongo_express ... done Creating Poc_nifi_kafka ... done Podemos comprobar que todo esta levantado correctamente mediante: $ docker-compose -f docker-compose.yml ps Name Command State Ports -------------------------------------------------------------- ----------------------------------------------- Poc_nifi_kafka /etc/confluent/docker/run Up 0.0.0.0:9092->9092/tcp Poc_nifi_mongo_express tini -- /docker-entrypoint ... Up 0.0.0.0:8081->8081/tcp Poc_nifi_mongodb docker-entrypoint.sh mongod Up 0.0.0.0:27017->27017/tcp Poc_nifi_nifi ../scripts/start.sh Up 10000/tcp, 0.0.0.0:8080->8080/tcp, 8443/tcp Poc_nifi_zookeeper /etc/confluent/docker/run Up 2181/tcp, 2888/tcp, 3888/tcp Si quisiéramos ver más información de los procesos levantados podríamos usar $ Docker-compose top . En caso de que nos fallara alguno de los Dockers veríamos los logs mediante: $ docker-compose logs $ docker-compose logs -f $Service Una vez que tenemos levantado el entorno, accedemos a nuestro Apache NiFi, mediante: http://localhost:8080 Para cargar nuestro ejemplo, usaremos lo aprendido en el ejemplo anterior e importaremos el template y luego lo desplegaremos: Twitter-kafka-MongoDB.xml Una vez importado tendremos algo parecido a esto:
  • 16. pág. 16 Vamos a ir poco a poco viendo como funciona cada uno de los componentes. Comenzaremos con el procesador de Twitter que nos permitirá realizar una recogida selectiva de datos desde Twitter. Lo hemos seleccionado porque lo hemos considerado una fuente rápida y sencilla de datos. Para configurar este procesador necesitaremos dar de alta una aplicación en Twitter para conseguir los tokens de acceso necesarios. Deberemos ir a: https://developer.twitter.com Y loguearnos con nuestro usuario de Twitter y crear una nueva app15 . Una vez creada tendremos algo como esto: La parte que necesitamos la encontraremos en la pestaña de “Keys and tokens”. 15 No voy a explicar como crear la app porque no es objeto de este documento. Un ejemplo de guía puede ser: https://iag.me/socialmedia/how- to-create-a-twitter-app-in-8-easy-steps/ Ilustración 28 Sección "Key and tokens" de Twitter app. Teniendo estos datos, la configuración quedaría de la siguiente forma: Ilustración 29 Twitter Processor. Settings. Ilustración 30 Twitter Processor. Scheduling. Ilustración 31 Twitter Processor. Properties. Ilustración 27 Flujo general Twitter-Kafka-MongoDB.
  • 17. pág. 17 Las propiedades a configurar son: • Twitter Endpoint. Podemos recoger todos los datos o filtrados por termino o ID de usuario. En mi caso seleccionamos “Filter Endpoint” para poder filtrar por un termino en concreto. • Datos proporcionados por la App de Twitter. o Cosumer key. o Consumer Secret. o Access Token. o Access Token Secret. • Languages. Idoma de los tweets que vamos a recoger. En mi caso “en”. • Terms to Filter On. Enumeración separada por comas de los términos que deseamos filtrar. En mi caso “blockchain”. Una vez configurado podemos comprobar que recoge datos de forma correcta, seleccionando el procesador, botón derecho y “Strart”. Ilustración 32 Twitter Processor funcionando. Vemos como el procesador se ha conectado correctamente y ha traído 90 mensajes y los ha enrutado a sus dos salidas. Una que simplemente nos escribirá los tweets en fichero y otra más compleja que tratará los datos los colocará en Kafka y luego los escribirá en MongoDB. Podemos comprobar el contenido de los flowfiles en las conexiones. Nos aparecerá toda la lista de flowfiles y podremos ver el contenido de alguno de ellos mediante la “i” de la izquierda. Comprobamos que tenemos todo el contenido y que ha filtrado correctamente por blockchain. Ilustración 33 Ejemplo de tweet incrustado en un flowfile. Vamos a comenzar con el flujo más sencillo y vamos a ver como escribe estos FlowFiles en ficheros. Para ello vamos al procesador “Put Raw File” y vemos un poco su configuración. Ilustración 34 Put Raw File processor. Settings. Ilustración 35 Put Raw File. Scheduling. Ilustración 36 Put Raw File. Properties Para comprobar que toda ha ido bien, tendremos que comprobarlo en el Docker de NiFi. $ docker exec -i -t f9396945d85b /bin/bash nifi@f9396945d85b:/opt/nifi/nifi-current$ cd /tmp/ejemplo_raw/
  • 18. pág. 18 nifi@f9396945d85b:/tmp/ejemplo_raw$ ls 051a7cd6-8494-4b54-b23a-fccdee7c6ca7.json 471730f4-b9d3-41ac- ad10-2f480be4e361.json 82c75310-9bc5-4ee1-8331- 52d83ad78c19.json be41f09b-ee5e-4a4a-9160-3f08b0601c0b.json nifi@f9396945d85b:/tmp/ejemplo_raw$ cat 051a7cd6-8494-4b54- b23a-fccdee7c6ca7.json {"created_at":"Tue Jan 22 12:46:41 +0000 2019","id":1087693030004613120,"id_str":"1087693030004613120", "text":"RT @aoife_keady: Advice on buying Blockchain from John Biggs. ud83dude48 He bought some. Then with all the hype they were worth more money and thenu2026","source":"u003ca href="http://twitter.com" rel="nofollow"u003eTwitter Web Clientu003c/au003e","truncated":false,"in_reply_to_status_i d":null,"in_reply_to_status_id_str":null,"in_reply_to_user_id" :null,"in_reply_to_user_id_str":null,"in_reply_to_screen_name" :null,"user":{"id":3574988954,"id_str":"3574988954","name":"Em ily ………….. Ahora vamos a ver la segunda parte del flujo en la llevaremos los datos hasta kafka y luego los insertaremos en MongoDB. Ilustración 37 Flujo de inserción en Kafka y MongoDB. El primer procesador que nos encontramos en este flujo será el EvaluateJsonPath Ilustración 38 EvaluateJsonPath Processor. Añadiremos dos nuevas propiedades relacionadas con los campos text y lang del JSON. En la parte superior derecha pulsaremos el botón “New property”, asignando el nombre “twitter.lang” y su valor “$.lang” a la nueva propiedad. Y, de nuevo, los mismo pero para “twitter.text” con el valor “$.text”. En la pestaña “Settings” activaremos dos de los tres flasg que se encuentran en la derecha: “failure” y “unmatched”. Ilustración 39 EvaluateJsonPath Processor. Settings. Ilustración 40 EvaluateJsonPath Processor. Scheduling. Ilustración 41. EvaluateJsonPath Processor. Properties. Ilustración 42 RouteOnAttribute Processor. No hemos terminado todavía, nos falta añadir la relación “matched” para el procesador “EvaluateJsonPath” para ello añadiremos un nuevo procesador. Aunque en esta ocasión filtraremos por “route” y seleccionando la opción “RouteOnAttribute”. Añadiremos (Add). Una vez creado el procesador, vamos a configurarlo (como los anteriores). Le asignaremos un nombre si queremos y activamos el flag “unmatched” de la parte derecha. Ya en “Properties” añadimos una “New property”, le ponemos un nombre y añadimos el valor:
  • 19. pág. 19 “${twitter.text:isEmpty():not():and(${twitter.lang:equals(“e s”)})}“ Con esto conseguimos filtrar aquellos tweets que estén vacíos y cuyo idioma no haya sido marcado como español. Añadimos (Add) y Aplicamos (Apply). Si bien es cierto, este último paso también lo hubiésemos podido realizar al principio, en el momento de configurar el procesador “getTweets”. Ya casi como último paso, procederemos a conectar el procesador “EvaluateJsonPath” con el de “RouteOnAttribute”. Ya en la nueva ventana, en la pestaña “Details” tendremos la opción “For relationships”. Activaremos el flag “matched”. En la pestaña “Settings” volveremos a indicar la política que queremos aplicar, será la misma que en el caso anterior: “FirstInFirstOutPrioritizer” y Añadiremos (Add). Ilustración 43 RouteOnAttribute Processor. Settings. Ilustración 44 RouteOnAttribute Processor. Scheduling. Ilustración 45 RouteOnAttribute Processor. Properties. ${twitter.text:isEmpty():not():and(${twitter.lang:equals("en ")})} Una vez que tenemos enrutados los FlowFiles solo nos falta configurar la inserción de los mensajes en una topic de Kafka y de ahí lo persistiremos en la base de datos Mongo. Para ello usaremos los procesadores: PutKafka y PutMongo, que consifuramos como mostramos a continuación: Ilustración 46 Inserción en kafka y en MongoDB. Las variables a configurar en el procesador de PutKafka son bastante sencillas: Known Brokers: kafka:9092 Topic Name: TopicTweets Client Name: PoC Ilustración 47 PutKafka Processor. Properties. Después de configurar este procesador pasamos a configurar PutMongo, cuya configuración es bastante sencilla también. Mongo URI: mongodb://mongo:27017 Mongo Database Name: Poc_Twitter Mongo Collection Name: Messages
  • 20. pág. 20 Ilustración 48 PutMongo Processor. Settings. Ilustración 49 PutMongo Processor. Properties. Una vez que hemos resuelto todas las conexiones podremos probar nuestro flujo. Para comprobar que todo esta funcionando correctamente a la hora de insertar los datos en la base de datos hemos añadadido mongo_express a nuestro docker-compose. Podemos dirigirnos a nuestro navegador y acceder a la url: http://localhost:8081 (admin/admin) Nos aparecerá el explorador de la base de datos MongoDB. Ilustración 50 MongoDB Express. Comprobamos que los datos se están guardando correctamente. Ilustración 51 Ejemplo de tweet insertado en MongoDB. Para terminar nuestra prueba vamos a añadir una segunda rama que colgara desde el procesador de “RuteOnAttribute” donde haremos un pequeño procesado de los datos y los volveremos a insertar en el circuito Kafka-MongoDB. La nueva rama presentará esta forma: Ilustración 52 Flojo de inserción de tweets procesados. Una vez enrutados los FlowFiles pasan al procesador JoltTransformJSON que nos permitirá aplica una lista de especificaciones Jolt a la carga útil JSON del archivo de flujo. Se crea un nuevo FlowFile con contenido transformado y se enruta a la relación de "éxito". Si la transformación JSON falla, el FlowFile original se enruta a la relación 'falla'. Para configurar este procesador bastará con introducir las especificaciones Jolt. Ilustración 53 JoltTransformJSON Processor. Properties. Jolt Specification: [{ "operation": "shift", "spec": { "created_at": "created_date_time", "id": "tweet_id", "text": "tweet_text", "user": { "id": "user_id" } } }, { "operation": "default", "spec":{
  • 21. pág. 21 "chainr-rating" : 4 } } ] Este procesador nos proporciona acceso al uso de Jolt16 . Esta librería nos ofrece un enfoque declarativo para definir la salida JSON. Jolt proporciona proporciona un conjunto de tipos de transformación, cada uno con su propio DSL, que define la nueva estructura para los datos JSON salientes. Una vez transformados los FlowFiles pasan a entrar de nuevo al circuito Kafka-MongoDB. En las imágenes podemos ver que las configuraciones son muy parecidas que en la caso anterior. Simplemente cambiamos el nombre de la Topic Name a “TopoicTweets_Pro” y el nombre de la colección en la que insertaremos los datos a “Message_Pro”. Ilustración 54 PutKafka processor. Properties. Ilustración 55 PutMongo Processor. Properties. Si comprobamos de nuevo el formato del json introdocido en la base de datos, comprobamos que presentan el formato especificado en las especificaciones de Jolt. 16 https://github.com/bazaarvoice/jolt Ilustración 56 Ejemplo de tweet procesado insertado en MongoDB. V. EJEMPLO III. En este ejemplo cogeremos la base del ejemplo anterior e insertaremos los datos en Elasticsearch. Como, ya deberíamos haber cogido un poco de soltura con el entorno vamos a poner sólo los esquemas fundamentales. Ilustración 57 Esquema general EJEMPLO III. Treas a realizar: [1] Levantar infraestructura necesaria medainte el docker- compose. [2] Configurar el JSON obtenido de Twitter y enrutarlo. [3] Guardar los JSON en Elasticsearch. [4] Ver los resultados en Kibana. Primeramente deberemos levantar nuestro entorno de pruebas mediante el dockerfile disponible en el repositorio17 . Antes de poder lanzar este docker-file deberemos asegurarnos de que en nuestra máquina tenemos configurado el siguiente parámetro: $ sudo sysctl -w vm.max_map_count=262144 17 En el ejemplo se levanta con un nginx que nor redirige al Kibana. En nuestro entorno lo podríamos omitir y simplemente atacar directamente al kibana.
  • 22. pág. 22 Sin este parámetro el clúster de elasticsearch no levanta correctamente. El docker-file que usaremos para la prueba es el siguiente: --- version: '3.1' ## Component: Elasticsearch-kibana ## Version: 0.1 ## Author: Versia Tecnologías Emergentes ## networks: labnet: services: elasticsearch: image: docker.elastic.co/elasticsearch/elasticsearch:6.5.4 container_name: elasticsearch environment: - cluster.name=docker-cluster - bootstrap.memory_lock=true - "ES_JAVA_OPTS=-Xms512m -Xmx512m" ulimits: memlock: soft: -1 hard: -1 volumes: - esdata1:/usr/share/elasticsearch/data ports: - 9200:9200 networks: - labnet elasticsearch2: image: docker.elastic.co/elasticsearch/elasticsearch:6.5.4 container_name: elasticsearch2 environment: - cluster.name=docker-cluster - bootstrap.memory_lock=true - "ES_JAVA_OPTS=-Xms512m -Xmx512m" - "discovery.zen.ping.unicast.hosts=elasticsearch" ulimits: memlock: soft: -1 hard: -1 volumes: - esdata2:/usr/share/elasticsearch/data networks: - labnet elasticsearch3: image: docker.elastic.co/elasticsearch/elasticsearch:6.5.4 container_name: elasticsearch3 environment: - cluster.name=docker-cluster - bootstrap.memory_lock=true - "ES_JAVA_OPTS=-Xms512m -Xmx512m" - "discovery.zen.ping.unicast.hosts=elasticsearch" ulimits: memlock: soft: -1 hard: -1 volumes: - esdata3:/usr/share/elasticsearch/data networks: - labnet kibana: image: docker.elastic.co/kibana/kibana-oss:6.5.4 container_name: kibana environment: SERVER_NAME: localhost ELASTICSEARCH_URL: http://elasticsearch:9200/ ports: - 5601:5601 ulimits: nproc: 65535 memlock: soft: -1 hard: -1 networks: - labnet nginx: image: nginx:latest ports: - 8090:80 volumes: - ${PWD}/nginx-conf/:/etc/nginx/conf.d/ command: /bin/bash -c "nginx -g 'daemon off;'" ulimits: nproc: 65535 networks: - labnet nifi: image: apache/nifi container_name: Poc_nifi_nifi ports: - "8080:8080" environment: - NIFI_WEB_HTTP_PORT=8080 networks: - labnet volumes: esdata1: driver: local esdata2: driver: local esdata3: driver: local Nota: No sería necesario levantar el cluster de elasticsearch, para la prueba valdía con un entorno simple. Lo podríamos levantar de la siguiente forma: $ docker run -d --name elastic -p 9200:9200 -p 9300:9300 elasticsearch Ó $ docker run -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" docker.elastic.co/elasticsearch/elasticsearch:6.5.4 $ docker run -d --name kibana -p 5601:5601 -e ELASTICSEARCH_URL=http://IP-HOST-DOCKER-ELASTIC:9200 kibana $ sudo docker run -d --name nifi -p 8080:8080 apache/nifi Para levantar la infraestructura necesaria bastará con ejecutar $ docker-compose up -d Creating network "twitter_elasticsearch_labnet" with the default driver Creating volume "twitter_elasticsearch_esdata1" with local driver Creating volume "twitter_elasticsearch_esdata2" with local driver Creating volume "twitter_elasticsearch_esdata3" with local driver Creating twitter_elasticsearch_nginx_1 ... done Creating elasticsearch ... done Creating Poc_nifi_nifi ... done Creating elasticsearch3 ... done Creating kibana ... done Creating elasticsearch2 ... done Comprobamos que todo esta levantado correctamente de la siguiente forma: $ docker-compose ps Name Command State Ports -------------------------------------------------------------- ------------------------------------------------------ Poc_nifi_nifi ../scripts/start.sh Up 10000/tcp, 0.0.0.0:8080->8080/tcp, 8443/tcp elasticsearch /usr/local/bin/docker-entr ... Up 0.0.0.0:9200->9200/tcp, 9300/tcp elasticsearch2 /usr/local/bin/docker-entr ... Up 9200/tcp, 9300/tcp elasticsearch3 /usr/local/bin/docker-entr ... Up 9200/tcp, 9300/tcp kibana /usr/local/bin/kibana-docker Up 0.0.0.0:5601->5601/tcp twitter_elasticsearch_nginx_1 /bin/bash -c nginx -g 'dae ... Up 0.0.0.0:8090->80/tcp
  • 23. pág. 23 Podemos comprobar que Elasticsearch esta levantado con una simple prueba: $ curl localhost:9200 { "name" : "B931ITV", "cluster_name" : "docker-cluster", "cluster_uuid" : "oqR1Y2uXRxichyUoLx9m_A", "version" : { "number" : "6.5.4", "build_flavor" : "default", "build_type" : "tar", "build_hash" : "d2ef93d", "build_date" : "2018-12-17T21:17:40.758843Z", "build_snapshot" : false, "lucene_version" : "7.5.0", "minimum_wire_compatibility_version" : "5.6.0", "minimum_index_compatibility_version" : "5.0.0" }, "tagline" : "You Know, for Search" } Y comprobamos que Kibana esta levantado mediante: http://localhost:5601 Ilustración 58 Pantalla incial de Kibana. Finalmente nos conectamos a la consola de Apache Nifi e importamos el template “Twitter-Elasticsearch.xml”. Una vez importado, lo desplegamos de forma que nos deberían de aparecer todos los procesadores ya configurados. Lo único que nos quedará por establecer serán las claves de acceso a Twitter. Ilustración 59 template Ejemplo III. Respecto a los ejemplos anteriores el único procesador nuevo que aparece es “PutElasticsearchHttp” que nos permitirá insertar los datos en Elasticsearch de forma sencilla. Ilustración 60 PutElasticsearchHttp processor. Deberemos establecer las siguientes propiedades: • Elasticsearch URL: http://elasticsearch:9200 • Identifier Attribute: uuid • Index: twitter • Type: default Ilustración 61PutElasticsearchHttp processor.Settings. Ilustración 62 PutElasticsearchHttp processor. Properties. Una vez que tenemos todo configura y los diferentes temas de conexión solucionados pasamos a ejecutar la prueba. Para poder ver los datos en Kibana deberemos crearnos un patron de indice nuevo “twitter*”
  • 24. pág. 24 Ilustración 63 Creando patron de indice nuevo en kibana. Una vez creado ya podemos ver todos los datos en kibana, donde podríamos crear nuestros cuadros de mando. Ilustración 64 Visión de datos en Kibana. Podríamos seguir desarrollando ejemplos interesantes, pero creo que con los expuestos nos hacemos una ligera idea de las capacidades de Apache NiFi. Entre las pruebas que hemos realizado estarían las conexiones a bases de datos Oracle/postgres. Recogida de ficheros vía ftp, llamadas a api rest, ejecución de scripts,……. Según vaya teniendo tiempo ire colgando los ejemplos en el repositorio de githup. https://github.com/vthot4/poc_nifi VI. Flow Development Life cycle con NiFi y NiFi registry. Una de las principales caracaterísticas de Apache NiFi es la capacidad de permitirnos diseñar flujos de datos complejos desde una interfaz de usuario sencilla. Esta sencillez es muy buena para probar flujos de forma ágil pero se puede convertir en un problema cuando queremos abordar un ciclo de desarrollo completo. Para solventar este problema nace, entre otras cosas, Apache NiFi Registry que nos permitirá gestionar el “Flow Development Life Cycle with NiFi registries(FDLC)” dentro de nuestros entornos. Ilustración 65 Flow Development Life Cycle. Fuente: Hortonworks. Cuando hablamos de implementar un FDLC nos refereimos a implementar un desarrollo ágil que nos permita la reutilización de componentes y un control de versiones centralizado equivalente al de cualquier otro lenguaje de programación. Los componentes reutilizables de Apache NiFi se centran en las plantillas y las configuraciones. El esquema general sería el siguiente: Ilustración 66 Componentes reutilizables niFi. Source: https://community.hortonworks.com/articles/60868/enterprise-nifi- implementing-reusable-components-a.html. Los templates y las configuracones son los componentes principales que tenemos que tener en cuenta. Cuando exportamos un flujo podemos crear un template que se traduce un fichero xml que podemos almacenar en nuestros repositorios de código. Gestionando este fichero de forma correcta nos puede servir para gestionar los ciclos de despliegue en nuestros entornos. El siguiente flujo describe de forma muy clara el flujo de FDLC que deberíamos seguir: Ilustración 67 FDLC mediante templates.Source: https://community.hortonworks.com/articles/60868/enterprise-nifi- implementing-reusable-components-a.html
  • 25. pág. 25 Aunque esta opción puede ser válida, desde Apache NiFi decidieron añadir nuevas herramientas que ayudasen a abordar este tipo de problemáticas. Cuando los desarrolladores de NiFi se enfrentaron al problema de gestionar el FDLC optaron por dotar a NiFi de dos funcionalidades separadas: • Flow Registry. Es un subproyecto de Apache NiFi que nos provee de un almacenamiento centralizado donde compartir los recursos entre diferentes instancias de NiFi o MiNiFi. Admite el almacenamiento, la recuperación y la actualización de flujos versionados. • Variable Registry. Nos proporcionara flexibilidad para crear variables dinámicamente y consultarlas en las propiedades de los componentes. No solo simplifica la configuración mediante la reutilización de valores, sino que también mejora la portabilidad de los flujos a nuevos entornos. La gestión de estas variables se realiza a través de la interfaz de usuario de NiFi a nivel de grupo de proceso. Estas variables se pueden actualizar en tiempo de ejecución sin reiniciar NiFi. Vamos a ver como hacer una configuración básica y alguna prueba de funcionaiento, para ello usaremos el siguiente docker-compose.yml: --- version: '3.1' ## Component: nifi ## Version: 0.1 ## Author: Versia Tecnologías Emergentes ## networks: labnet: services: nifi: image: apache/nifi container_name: Poc_registry_nifi ports: - "8080:8080" environment: - NIFI_WEB_HTTP_PORT=8080 networks: - labnet nifi2: image: apache/nifi container_name: Poc_registry_nifi2 ports: - "9090:9090" environment: - NIFI_WEB_HTTP_PORT=9090 networks: - labnet registry-nifi: image: apache/nifi-registry:latest container_name: Poc_registry_registry ports: - 18080:18080 environment: - NIFI_WEB_HTTP_PORT=18080 networks: - labnet El entorno esta copuesto de dos Apache NiFi y un NiFi registry que nos permitirán explorar la carácterísticas de esta integración. Para levantar el entorno bastara con: ~/nifi/poc_nifi/examples/Nifi_registry$ docker-compose -f docker-compose.yml up -d ~/nifi/poc_nifi/examples/Nifi_registry$ docker-compose -f docker-compose.yml ps Name Command State Ports -------------------------------------------------------------- -------------------------------------------------------- Poc_registry_nifi ../scripts/start.sh Up 10000/tcp, 0.0.0.0:8080->8080/tcp, 8443/tcp Poc_registry_nifi2 ../scripts/start.sh Up 10000/tcp, 8080/tcp, 8443/tcp, 0.0.0.0:9090->9090/tcp Poc_registry_registry /bin/sh -c ${NIFI_REGISTRY ... Up 0.0.0.0:18080->18080/tcp, 18443/tcp Podremos acceder a los diferentes servicios mediante: • NiFi1: http://localhost:8080/nifi • NiFi2: http://localhost:9090/nifi • NiFi Registry: http://localhost:18080/nifi-registry/ Una vez que tenemos todo levantado, nos conectamos a la consola del NiFi Registry. Ilustración 68 Consola inicial NiFi Registry. Lo primero que vamos a hacer es crear un nuevo “Bucket” que a efectos prácticos será un nuevo repositorio. Para crearlo bastará con que pulsemos el menu de settings que aparece en la parte superior derecha y nos aparecerá la pantalla para crear el nuevo repositorio. Le daremos el original nombre de “Prueba”. Ilustración 69 Añadiendo nuevo Bucket en NiFi Registry. Una vez creado uestro nuevo bucket poco más podemos hacer, ya que para poder habilitar permisos deberíamos conectar nuestro entorno a un ldap o algo simlar. Ahora vamos a conectar nuestro primer NiFi al NiFi registry. En la parte superior derecha, desplegamos el menu y seleccionamos “controller settings”. En el nuevo menu que nos aparece seleccionamos la pestaña de “Registry clients” y le damos al “+” para añadir nuestra instacia de NiFi registry. Name: Nifi registry URL: http://Poc_registry_registry:18080
  • 26. pág. 26 Si todo ha ido bien, ya tendríamos que tener configurado nuestro entorno de pruebas. Vamos a comenzar creando un nuevo “Process Group” con nombre Prueba. Ilustración 71 Añadiendo Process Group Prueba. Una vez creado vamos a ver como configuramos principalmente dos cosas: • Variables. • Versionado. Para configurar las variables generales de un Process Group bastará con que accedamos a su configuración → Variables. Ilustración 72 Configurando un Process Group. La ventana que nos aparce nos permitirá crear variables que se podrán usar en todos los flujos que están dentro. De esta forma podremos cambiar todas las configuraciones de forma ágil. En este caso he creado dos variables de prueba: kafka_broker: localhost kafka_port: 9092 Ilustración 73 Configurando variables del Process Group. Cuando le damos a aplicar vemos como el mismo hace una reconfiguración de todos los processors que tengamos dentro del grupo. Ilustración 74 Reconfiguración de variables. Si exportamos este flujo de trabajo y revisaramos el template xml que nos crea podemos podemos ver esas variables que acabos de crear: Antes de pasar a ver como se implementan estas variables que hemos creado vamos a hailitar el versionado de nuestro componente. Para ello accedemos a la configuración –A versión y “Start verion control”. Nos saldrá una pantalla donde podremos escoger el servidor y repositorio en el que queremos que se guarde. En nuestro caso: Registry: Nifi registry Bucket: Prueba Flow Name: Insercción Kafka-Mongo Ilustración 70 Añadiendo NiFi registry a NiFi.
  • 27. pág. 27 Ilustración 75 Iniciando control de versiones del componente. Ahora si volvemos a la parte de Version veremos que el menu nos ha cambiado. Continuemos con nuestra pequeña prueba añadiendo un par de processor, para ello entramos en el Process Group de prueba que hemos creado con anterioridad. En la parte inferior izquierda podemos ver de forma simple donde nos encontramos. Ya situados añadiremos dos procesadores básicos, PutKafka y PutMongo18 . El flujo quedará de la siguiente forma: Ilustración 76 Flujo simple de prueba. 18 En esta prueba sólo busco ver las funcionalidades del Kafka Regstry por lo que he optado por crear el flujo sin la infraestructura. Usando los ejemplos anteriores es sencillo comoner la prueba real completa. Para usar las variables bastará con ir a properties del objeto y en lugar de añadir los valores poner las variables de la siguiente forma: Known Brokers: ${kafka-broker}:${kafka-port} Añadidos nuestros cambios sobre el grupo de proceso prueba volvemos a la parte de version de la configuración. Veremos que nos aparcen las opciones de ver los cambios locales, revertir los cambios y subir los nuevos cambios al repositorio. Ilustración 77 Opciones de la gestión de versionado. Podemos añadir algunos procesadores mas como un GenerateFlowfile y realizar varios commits. Una vez realizado poderemos ir a la opción de change e ir recuperando las diferentes versiones. Podemos ver el historial de cambios desde Apache Regsitry: Ilustración 78 Change log niFi Registry.
  • 28. pág. 28 Para terminar esta sencilla prueba podemos conectar el segundo nifi que tenemos levantado al NiFi registry y probar a crear un Process Group nuevo. Cuando añadimos el componente nuevo podemos ver que tenemos la opción de importar Y nos aparecera la verdadera magia de NiFi registry. Si se sube alguna nueva version del componente, nos aparecerá una flecha roja en la parte superior izquierda: Ilustración 79 Alerta de nueva versión en componente. Actualizaríamos la versión y el componente cogería todos los nuevos cambios19 . Con esto ya tenemos a nuestra disposión un gestor de flujos que nos puede ayudar a controlar su creación y producción de forma ágil y centralizada. A. Arquitectura interna.20 Vamos a ver un poco como esta implementado este componente. En principio el interfaz de usuario es una aplicación web creada con angular que se comunica con el 19 En algunos casos nos puede dar error si todavía quedan pendientes pensajes de procesar en las colas intermedias. Normalmente deberemos esperar a que se vacien o forzar parando flujos anteriores. 20 https://bryanbende.com/development/2018/06/20/apache-nifi-registry-0- 2-0 servidor mediante el API REST del registro de NIFI21 . Detrás de esta API REST encontramos la capa de servicio donde se implementa la lógica principal, la capa de servicio que interactua con la la base de metadatos y el proveedor de persistencia de flujo. La base de metadatos almacenará la información sobre grupos y elementos versionados, como identificadores, nombres, descripciones y comentarios de confirmación. En una primera versión se uso la base de datos H2 de forma embebida pero en las nuevas versiones permite usar bases de datos externas como postgres. Para llevar a cabo esta configuración deberemos modificar algunos parámetros del fichero de configuración: nifi.registry.db.url= nifi.registry.db.driver.class= nifi.registry.db.driver.directory= nifi.registry.db.username= nifi.registry.db.password= El proveedor de persistencia de flujo almacena el contenido de cada flujo versionado y se considera un punto de extensión público. Esto significa que se pueden proporcionar implementaciones personalizadas implementando la interfaz FlowPersistenceProvider. En la versión inicial se implemento esta funcionalidad usando el sistema de archivos local para la persistencia pero en las nuevas versiones se ha implementado en base a git mediante el uso de la biblioteca JGit. Esto nos proporciona la posibilidad de almacenar el repositorio en un repo git. El proveedor de git se puede configurar en el fichero de configuración suppliers.xml: <flowPersistenceProvider> <class> org.apache.nifi.registry.provider.flow.git.GitFlowPersistenceP rovider </class> <property name="Flow Storage Directory">./flow_storage</property> <property name="Remote To Push"></property> <property name="Remote Access User"></property> <property name="Remote Access Password"></property> </flowPersistenceProvider> Con la propiedad “Flow Starage Directory” especificaremos el directorio local que se espera que sea un repositorio git. La propiedad "Remote To Push" especifica el nombre del repositorio remoto al que se enviará automáticamente. Esta propiedad es opcional y, si no se especifica, las confirmaciones permanecerán en el repositorio local, a menos que la subida la hagamos manualmente. Resumiendo un poco los pasos para conectar nuestro repositorio a git serían: 1. Crear un nuevo repositorio de GitHub y clonarlo localmente. 21 Podemos ver la documentación del API en https://nifi.apache.org/docs/nifi-registry-docs/index.html.
  • 29. pág. 29 2. Establecer el Flow storage directory en el directorio que se clonó el repositorio. 3. Crear un nuevo “Personal Access Token” para nuestra instancia de Nifi Registry. 4. Establecer el “ Remote Access User” en GitHub. 5. Establecer “Remote Access Password” en el token de acceso. Ilustración 80 Source: https://bryanbende.com/development/2018/06/20/apache-nifi- registry-0-2-0 Otra funcionalidad interesante que presenta la arquitectura de Apache NiFi Registry es la posibilidad de los “Event Hooks”. Nos permitirá ejecutar código personalizado cuando ocurran eventos de aplicación. Para implementar los event hook, deberá ser implementada la siguiente interfaz de Java: public interface EventHookProvider extends Provider { void handle(Event event) throws EventHookException; } Donde el objeto evento contendrá un tipo de evento, junto con una lista de pares campo/valor que son específicos de cada evento. Algunos posibles eventos son: CREATE_BUCKET CREATE_FLOW CREATE_FLOW_VERSION UPDATE_BUCKET UPDATE_FLOW DELETE_BUCKET DELETE_FLOW Si no queremos meternos a implementar la interfaz de Java podríamos configurar el “ScriptedEventHookProvider” que nos permitiría ejecutar scripts para cada evento. La configuración para este tipo de event hook sería: <eventHookProvider> <class> org.apache.nifi.registry.provider.hook.ScriptEventHookProvider </class> <property name="Script Path"></property> <property name="Working Directory"></property> </eventHookProvider> Los argumentos del script serán los campos de eventos en el orden en que se especifican para el tipo de evento dado. Como ejemplo, digamos que creamos un script llamado logging-hook.sh con el siguiente contenido: #!/bin/bash echo $@ >> /tmp/nifi-registry-event.log Para cada evento, esto reflejaría los argumentos del script y los agregaría a /tmp/nifi-registry-event.log. Después de crear un grupo y comenzar el control de versión en un grupo de procesos, el registro debería mostrar algo como lo siguiente: CREATE_BUCKET feeb0fbe-5d7e-4363-b58b-142fa80775e1 anonymous CREATE_FLOW feeb0fbe-5d7e-4363-b58b-142fa80775e1 1a0b614c-3d0f- 471a-b6b1-645e6091596d anonymous CREATE_FLOW_VERSION feeb0fbe-5d7e-4363-b58b-142fa80775e1 1a0b614c-3d0f-471a-b6b1-645e6091596d 1 anonymous v1 VII. Cluster NiFi. Como vimos anteriormente, Apache NiFi presenta la capacidad de clasterización mediante el uso de ZooKeeper como coordinador. El esquema general que nos proponen en la configuración es el siguiente: Ilustración 81 Esquema de cluster Apache NiFi Usa el paradigma de Zero-Master, en el que cada nodo del clúster realiza las mismas tareas sobre los datos, pero cada uno opera en un conjunto de datos diferente. Uno de los nodos será elegido automáticamente como el coordinador del clúster que pasará a gestionar el estado de los nodos. Deberemos entender algunos conceptos antes de realizar una configuración base: • NiFi Cluster Coordinator. Un coordinador de agrupaciones de NiFi es el nodo responsable de llevar a cabo las tareas para gestionar qué nodos se permiten en la agrupación y proporcionar el flujo más actualizado a los nodos recién incorporados. • Nodes. Cada gruopo se compone de uno o más nodos. Los nodos son los que llevan a cabo el procesamiento real de los datos. • Primary Node. En cada clúster existe un nodo primario. En este nodo es posible ejecutar “Procesadores aislados”. Este nodo será elegido automáticamente por ZooKeeper, de modo que si se desconecta del clúster, otro nodo será elegido en su lugar. Los adminsitradores podrán determinar que nodos pueden elegirse para ser primarios desde la consola de administración.
  • 30. pág. 30 • Isolated Processors. En un cluster Nifi, el mismo flujo de datos se ejecuta en todos los nodos. Como resultado, cada componente en el flujo se ejecuta en cada nodo. Sin embargo, pueden existir casos en los que queramos que los procesos sólo se ejecuten en el nodo primario para evitar problemas en la ingesta de datos. Para estos casos podemos configurar los procesadores aislados. • Heartbeats. El nodo principal recibe el estado de salud del resto de nodos mediante el “hearbeat(latidos)”. De forma predeterminada, los nodos emiten hearbeats cada 5 segundos. Si el coordinador no recibe esta señal durante 40 segundos, desconectará el nodo. Si, después de 40 segundos, el nodo envía de nuevo un latido, el coordinador solicitará automáticamente que el nodo vuelva a unirse al clúster. Estas configuraciones de tiempo de hearbeat y tiempo de espera hasta desconexión se pueden configurar en el fichero “nifi.proprties”. Entendidos algunos de los conceptos básicos vamos a probar a levantar un pequeño clúster usando una funcionalidad muy interesante de docker-compose. Usaremos el siguiente docker-compose: --- version: "3.1" ## Component: nifi ## Version: 0.2 ## Author: Versia Tecnologías Emergentes ## services: zookeeper: hostname: zookeeper container_name: zookeeper image: 'bitnami/zookeeper:latest' environment: - ALLOW_ANONYMOUS_LOGIN=yes nifi: image: apache/nifi ports: - 8080 environment: - NIFI_WEB_HTTP_PORT=8080 - NIFI_CLUSTER_IS_NODE=true - NIFI_CLUSTER_NODE_PROTOCOL_PORT=8082 - NIFI_ZK_CONNECT_STRING=zookeeper:2181 - NIFI_ELECTION_MAX_WAIT=1 min Y lo levantaremos medainte: $ docker-compose -f docker-compose-cluster.yml up --scale nifi=3 -d $ docker-compose -f docker-compose-cluster.yml ps Name Command State Ports -------------------------------------------------------------- --------------------------------- nifi_nifi_1 ../scripts/start.sh Up 10000/tcp, 0.0.0.0:32775->8080/tcp, 8443/tcp nifi_nifi_2 ../scripts/start.sh Up 10000/tcp, 0.0.0.0:32776->8080/tcp, 8443/tcp nifi_nifi_3 ../scripts/start.sh Up 10000/tcp, 0.0.0.0:32777->8080/tcp, 8443/tcp zookeeper /app-entrypoint.sh /run.sh Up 2181/tcp, 2888/tcp, 3888/tcp Podremos acceder a nuestro nuevo cluster vía los puertos: 32775,32776 ó 32777. Estos puertos se generan de forma semi-aleatoria así que hay que comprobarlos después de cada arranque. Una vez que tenemos todo levantado podemos acceder y desde el menu lateral, entrar en las opciones del cluster. Nos debería de aparecer algo parecido a esto: Ilustración 82 Consola de administración del cluster. En esta consola de administración tenemos varias pestañas que nos proporcionan información sobre el estado del cluster: • Nodes. Muestra información sobre el direccionamiento de los nodos, tamaño de las colas y el estado. En la parte de estado podemos ver que rol tiene cada nodo en el clúster y los últimos datos de hearbeat. Desde esta vista también podemos desconectar los nodos que queramos. • System. Nos proporciona información sobre los recursos que dispone la máquina sobre la que corre el nodo. Se muestra número de cores, el load de los cores y el número de Threads. • JVM. Información destacada del uso de la máquina virtual de java en cada nodo. Ilustración 83 Administración clúster. JVM. • Storage. Disponemos de tres pestañas destinadas a mostrar los porcentajes de uso del FlowFile storage, Content Storage y Provenance Storage. • Versions. Nos permite ver de forma ágil, las versiones de los productos de nuestro clúster. Ilustración 84 Administración clúster. Versions. No me voy a extender mucho más, aunque sería interesante hacer pruebas de HA para ver como cambia el master y analizar como se comportan los flujos. Sólo indicar que ahora desde la pestaña de scheduling de los processors podremos decidir si se va a ejectuar en todos los nodos o solo en el primario.
  • 31. pág. 31 Ilustración 85 Scheduling execution. Con esta forma de levantar el cluster podemos probar a escalar hacia arriba y hacia abajo el número de nodos a nuestra voluntad. $ docker-compose -f docker-compose-cluster.yml up --scale nifi=8 -d Starting nifi_nifi_1 ... Starting nifi_nifi_1 ... done Starting nifi_nifi_2 ... done Starting nifi_nifi_3 ... done Creating nifi_nifi_4 ... done Creating nifi_nifi_5 ... done Creating nifi_nifi_6 ... done Creating nifi_nifi_7 ... done Creating nifi_nifi_8 ... done $ docker-compose -f docker-compose-cluster.yml ps Name Command State Ports -------------------------------------------------------------- --------------------------------- nifi_nifi_1 ../scripts/start.sh Up 10000/tcp, 0.0.0.0:32775->8080/tcp, 8443/tcp nifi_nifi_2 ../scripts/start.sh Up 10000/tcp, 0.0.0.0:32776->8080/tcp, 8443/tcp nifi_nifi_3 ../scripts/start.sh Up 10000/tcp, 0.0.0.0:32777->8080/tcp, 8443/tcp nifi_nifi_4 ../scripts/start.sh Up 10000/tcp, 0.0.0.0:32780->8080/tcp, 8443/tcp nifi_nifi_5 ../scripts/start.sh Up 10000/tcp, 0.0.0.0:32781->8080/tcp, 8443/tcp nifi_nifi_6 ../scripts/start.sh Up 10000/tcp, 0.0.0.0:32778->8080/tcp, 8443/tcp nifi_nifi_7 ../scripts/start.sh Up 10000/tcp, 0.0.0.0:32782->8080/tcp, 8443/tcp nifi_nifi_8 ../scripts/start.sh Up 10000/tcp, 0.0.0.0:32779->8080/tcp, 8443/tcp zookeeper /app-entrypoint.sh /run.sh Up 2181/tcp, 2888/tcp, 3888/tcp Y si tenemos un poco de paciencia, podremos ver algo como esto: VIII. MiNiFi. MiNiFi, es un subproyecto de Apache NiFi, que nace con un enfoque más orientado a la recopilación de datos en origen. Esto le permitirá a NiFi aumentar el control sobre el flujo de datos. Los objetivos específicos para el impulso inicial del esfuerzo de MiNFi incluyen: • Pequeño tamaño y bajo consumo de recursos. • Gestión central de agentes. • Generación de procedencia de datos (Cadena completa de custodia de la información). • Integración con NiFi para la gestión de flujo de datos de seguimiento. Siguiendo estos objetivos optaron por eliminar toda la parte de la consola y reducir los procesadores a un número reducido aunque siempres e pueden añadir si los necesitamos. El esquema general de MiNiFi queda de la sigueinte forma: Figure 1 MiNiFi Java Processes. Source: HortonWorks. Existen numerosas posibilidades para el binomio MiNiFi- NiFi, pero una de las más interesantes es la de gateway de IoT. No vamos a desarrollar los ejemplos en este documento, pero pongo dos enlaces a proyectos muy interesantes y fáciles de implementar. Por un lado esta la centralización de datos recogidos mediante protocolos MQQT. Podemos encontrar la documentación del desarrollo en: https://medium.freecodecamp.org/building-an-iiot-system- using-apache-nifi-mqtt-and-raspberry-pi-ce1d6ed565bc Y el esquema sería el siguiente: Ilustración 86 Arquitectura IoT. Source: https://medium.freecodecamp.org/building-an-iiot-system-using- apache-nifi-mqtt-and-raspberry-pi-ce1d6ed565bc Mosquitto se encargaría de recibir los datos mediante mqqt desde los sensores y MiNiFi estaría enganchado a los