¿Por qué podría necesitar emular la infraestructura de servicios web de Amazon?
En primer lugar, está ahorrando, ahorrando tiempo para el desarrollo y la depuración, y lo que es igualmente importante, ahorrando dinero del presupuesto del proyecto. Está claro que el emulador no será 100% idéntico al entorno original que estamos tratando de emular. Pero con el propósito de acelerar el desarrollo y la automatización del proceso, las similitudes existentes deberían ser suficientes. Lo más actual que sucedió en 2018 con AWS fue el bloqueo por parte de los proveedores de IP de las direcciones IP de las subredes de AWS en la Federación de Rusia. Y estos bloqueos afectaron nuestra infraestructura ubicada en la nube de Amazon. Si planea usar la tecnología AWS y colocar el proyecto en esta nube, entonces para el desarrollo y la prueba de emulación más que vale la pena.

En la publicación, le contaré cómo logramos realizar un truco con los servicios S3, SQS, RDS PostgreSQL y Redshift al migrar un almacén de datos existente a AWS durante muchos años.
Esto es solo una parte de mi
reunión del año pasado en el
mapa , que corresponde a los temas de los centros de AWS y Java. La segunda parte se refiere a PostgreSQL, Redshift y las bases de datos de columnas, y su versión de texto puede publicarse en los centros correspondientes, los videos y las diapositivas están en
el sitio web de la conferencia .
Al desarrollar una aplicación para AWS durante el bloqueo de subredes de AWS, el equipo prácticamente no los notó en el proceso diario de desarrollo de nuevas funcionalidades. Las pruebas también funcionaron y puede depurar la aplicación. Y solo cuando intentamos ver los registros de la aplicación en las logias, las métricas en SignalFX o el análisis de datos en Redshift / PostgreSQL RDS se decepcionaron: los servicios no estaban disponibles a través de la red del proveedor ruso. La emulación de AWS nos ayudó a no notar esto y evitar retrasos mucho mayores al trabajar con la nube de Amazon a través de una red VPN.
Cada proveedor de la nube "bajo el capó" tiene muchos dragones y no debe ceder a la publicidad. Debe comprender por qué todo esto es necesario para el proveedor de servicios. Por supuesto, la infraestructura existente de Amazon, Microsoft y Google tiene ventajas. Y cuando le dicen que todo se hace solo para que sea conveniente para su desarrollo, lo más probable es que estén tratando de ponerle la aguja y darle la primera dosis de forma gratuita. Para que luego no se salgan de la infraestructura y la tecnología específica. Por lo tanto, intentaremos evitar el bloqueo del proveedor. Está claro que no siempre es posible abstraerse por completo de decisiones específicas y creo que a menudo es posible abstraer casi el 90% en un proyecto. Pero el 10% restante del proyecto, vinculado a un proveedor de tecnologías que son muy importantes, está optimizando el rendimiento de la aplicación o las características únicas de las cuales no se encuentran en ningún otro lado. Siempre deben recordar las ventajas y desventajas de las tecnologías y protegerse lo más posible, no "sentarse" en una API específica de un proveedor de infraestructura en la nube.
Amazon escribe sobre el
procesamiento de mensajes en su sitio web. La esencia y la abstracción de las tecnologías de intercambio de mensajes son las mismas en todas partes, aunque hay matices: mensajes que pasan por colas o por temas. Por lo tanto, AWS recomienda utilizar el Apache ActiveMQ proporcionado y administrado para migrar aplicaciones de un agente de mensajería existente y para nuevas aplicaciones de Amazon SQS / SNS. Este es un ejemplo de enlace a su propia API, en lugar de la API JMS estandarizada y los protocolos AMQP, MMQT, STOMP. Está claro que este proveedor con su solución puede tener un mayor rendimiento, admite escalabilidad, etc. Desde mi punto de vista, si usa sus bibliotecas, y no API estandarizadas, habrá muchos más problemas.
AWS tiene una base de datos Redshift. Es una base de datos distribuida con una arquitectura paralela masiva. Puede cargar una gran cantidad de sus datos en tablas en múltiples sitios Redshft en Amazon y realizar consultas analíticas en grandes conjuntos de datos. Este no es un sistema OLTP en el que es importante que realice pequeñas solicitudes en un pequeño número de registros con la suficiente frecuencia con garantías de ACID. Al trabajar con Redshift, se supone que no tiene una gran cantidad de consultas por unidad de tiempo, pero pueden leer agregados en una gran cantidad de datos. El proveedor coloca este sistema para
actualizar su almacén de datos (almacén) en AWS y promete una carga de datos simple. Lo cual no es del todo cierto.
Un extracto de la documentación sobre qué
tipos admite Amazon Redshift. Es un conjunto bastante escaso, y si necesita algo para almacenar y procesar datos que no figuran en esta lista, será difícil para usted trabajar. Por ejemplo un GUID.
Pregunta de la sala, "¿Y JSON?"
- JSON solo se puede escribir como VARCHAR y hay varias funciones para trabajar con JSON.
Comentario de la audiencia: "Postgres tiene soporte JSON normal".
- Sí, tiene soporte para este tipo de datos y funciones. Pero
Redshift se basa en PostgreSQL 8.0.2. Hubo un proyecto ParAccel, si no me equivoco, esta tecnología de 2005 es una bifurcación de postgres que tiene un programador para solicitudes distribuidas basadas en una arquitectura paralela masiva. Pasaron 5-6 años y este proyecto fue licenciado para la plataforma Amazon Web Servces y se llamó Redshift. Se ha eliminado algo del Postgres original, se ha agregado mucho. Agregaron que relacionado con la autenticación / autorización en AWS, con roles, la seguridad en Amazon funciona bien. Pero si necesita, por ejemplo, conectarse desde Redshift a otra base de datos utilizando Fuente de datos externa, entonces no encontrará esto. No hay funciones para trabajar con XML, funciones para trabajar con JSON dos veces y se calcularon mal.
Al desarrollar una aplicación, intente
no depender de implementaciones específicas, y el código de la aplicación depende solo de abstracciones. Puede crear estas fachadas y abstracciones usted mismo, pero en este caso hay muchas bibliotecas listas para usar: fachadas. Que resumen el código de implementaciones específicas, de marcos específicos. Está claro que pueden no admitir toda la funcionalidad como un "denominador común" para las tecnologías. Es mejor desarrollar software basado en abstracciones para simplificar las pruebas.
Para emular AWS, mencionaré dos opciones. El primero es más honesto y correcto, pero funciona más lentamente. El segundo es sucio y rápido. Le contaré sobre la opción de pirateo: estamos tratando de crear toda la infraestructura en un solo proceso; las pruebas y la opción multiplataforma funcionarán más rápido con el trabajo en Windows (donde Docker no siempre puede ganar dinero con usted).
El primer método es perfecto si está desarrollando en linux / macos y tiene docker, sería mejor usar
atlassian localstack . Es conveniente utilizar
contenedores de
prueba para integrar localstack en la JVM.
Lo que me impidió usar lockalstack en Docker en el proyecto fue que el desarrollo estaba bajo Windows y nadie confirmó la versión alfa de Docker cuando comenzó este proyecto ... También es posible que no se les permita instalar una máquina virtual con Linux y Docker en ninguna compañía que se tome en serio a la seguridad de la información. No estoy hablando de trabajar en un entorno seguro en bancos de inversión y de prohibir casi todos los firewalls de tráfico allí.
Consideremos las opciones para emular el almacenamiento simple S3. Este no es un sistema de archivos ordinario de Amazon, sino más bien un almacén de objetos distribuidos. En el que coloca sus datos como un BLOB, sin la posibilidad de modificación y adición de datos. Hay almacenamientos distribuidos similares de todos los fabricantes. Por ejemplo, el almacenamiento de objetos distribuidos de Ceph le permite trabajar con su funcionalidad utilizando el
protocolo S3 REST y el cliente existente con una modificación mínima. Pero esta es una solución bastante pesada para el desarrollo y prueba de aplicaciones Java.
Un proyecto más rápido y más adecuado es la biblioteca
s3proxy java. Emula el protocolo S3 REST y lo traduce a las llamadas API
jcloud correspondientes y le permite utilizar muchas implementaciones para la lectura real y el almacenamiento de datos. Puede transmitir llamadas a la API de Google App Engine, la API de Microsoft Azure, pero para las pruebas es más conveniente usar el almacenamiento transitorio jcloud en RAM. También es necesario configurar la versión del protocolo de autenticación AWS S3 y especificar la clave y los valores secretos, también configurar el punto final: el puerto y la interfaz en la que escuchará este Proxy S3. En consecuencia, su código que utiliza el cliente AWS SDK debe conectarse en pruebas al punto final S3 AWS, no a la región AWS. Una vez más, recuerde que s3proxy no es compatible con todas las características de la API S3, ¡pero todos nuestros escenarios de uso emulan perfectamente! Incluso la carga multiparte para archivos grandes es compatible con s3proxy.
Amazon Simple Queue Service es un servicio de colas. Hay un
servicio de cola
elasticmq que está escrito en scala y se puede presentar a su aplicación utilizando el protocolo Amazon SQS. No lo utilicé en el proyecto, así que daré el código de inicialización, confiando en la información de sus desarrolladores.
En el proyecto, fui por el otro lado y el código depende de las abstracciones spring-jms de JmsTemplate y JmsListener y las dependencias del proyecto especifican el controlador JMS para SQS com.amazonaws: amazon-sqs-java-messaging-lib. Esto es lo que concierne al código de la aplicación principal.

En las pruebas, conectamos Artemis-jms-server como un servidor JMS incorporado para las pruebas, y en el contexto de Spring de prueba, en lugar de la fábrica de conexiones SQS, usamos la fábrica de conexiones Artemis. Artemis es la próxima versión de Apache ActiveMQ, un Middleware orientado a mensajes moderno y completo, no solo una solución de prueba. Quizás pasemos a su uso en el futuro, no solo en las pruebas automáticas. Por lo tanto, utilizando las abstracciones JMS junto con Spring, hemos simplificado tanto el código de la aplicación como la capacidad de probarlo fácilmente. Solo necesita agregar las dependencias org.springframework.boot: spring-boot-starter-artemis y org.apache.activemq: artemis-jms-server.
En algunas pruebas, PostgreSQL se puede emular reemplazándolo con
H2Database . Esto funcionará si las pruebas no son aceptadas y no utilizan funciones PG específicas. Al mismo tiempo, H2 puede emular un subconjunto del protocolo de conexión PostgreSQL sin soporte para tipos de datos y funciones. En nuestro proyecto, utilizamos Foreing Data Wrapper, por lo que este método no funciona para nosotros.
Puede ejecutar PostgreSQL real.
postgresql-embedded descarga la distribución real, o más bien el archivo con archivos binarios para la plataforma con la que corremos, lo descomprime. En Linux en tempfs en RAM, en Windows en% TEMP%, se inicia el proceso del servidor postgresql, configura los ajustes del servidor y los parámetros de la base de datos. Debido a las características de distribución de distribución, las versiones anteriores a PG 11 no funcionan en Linux. Para mí, hice una
biblioteca de contenedor que le permite obtener ensamblados binarios de PostgreSQL no solo desde un servidor HTTP sino también desde el repositorio maven. Lo cual puede ser muy útil cuando se trabaja en redes aisladas y se construye en un servidor CI sin acceso a Internet. Otra conveniencia de trabajar con mi contenedor es la anotación del componente CDI, que facilita el uso del componente en el contexto Spring, por ejemplo. La implementación de la interfaz del servidor AutoClosable apareció antes que en el proyecto original. No es necesario recordar detener el servidor, se detendrá cuando el contexto Spring se cierre automáticamente.
Al inicio, puede crear una base de datos basada en scripts, complementando el contexto de Spring con las propiedades apropiadas. Ahora estamos creando un esquema de base de datos usando scripts de
ruta para migrar el esquema de la base de datos, que se inician cada vez que la base de datos se crea en pruebas.
Para verificar los datos después de ejecutar las pruebas, utilizamos la biblioteca spring-test-dbunit. En las anotaciones a los métodos de prueba, indicamos con qué cargas comparar el estado de la base de datos. Esto elimina la necesidad de escribir código para trabajar con dbunit, solo necesita agregar el oyente de la biblioteca al código de prueba. Puede especificar en qué orden se eliminan los datos de las tablas después de completar el método de prueba, si el contexto de la base de datos se reutiliza entre las pruebas. En 2019, hay un enfoque más moderno implementado en la
base de datos que funciona con junit5. Puede ver un ejemplo de uso, por ejemplo
aquí .
Lo más difícil fue emular Amazon Redshift. Existe un proyecto de
controlador falso de desplazamiento al rojo . El proyecto se centra en emular la carga de datos por lotes en la base de datos analítica de AWS. En el emulador de protocolo jdbc: postgresqlredshift, se implementan los comandos COPY, UNLOAD, todos los demás comandos se delegan al controlador JDBC PostgreSQL normal.
Por lo tanto, las pruebas no funcionarán de la misma manera que en Redshift, la operación de actualización, que utiliza una tabla diferente como fuente de datos para la actualización (la sintaxis difiere en Redshift y PostgreSQL 9+. También noté una interpretación diferente de las citas entre líneas en comandos SQL entre estas bases de datos.
Debido a la arquitectura de una base de datos real de Redshift, las operaciones de inserción, actualización y eliminación de datos son bastante lentas y "costosas" en términos de E / S. Es posible insertar datos con un rendimiento aceptable solo en "paquetes" grandes y el comando COPIAR solo le permite descargar datos de un sistema de archivos S3 distribuido. Este comando en la base de datos admite varios formatos de datos AVRO, CSV, JSON, Parquet, ORC y TXT. Y el proyecto del emulador se centra en CSV, TXT, JSON.
Entonces, para emular Redshift en las pruebas, deberá iniciar la base de datos PostgreSQL como se describió anteriormente y ejecutar la emulación del repositorio S3, y al crear una conexión a los postgres, solo necesita agregar redshift-fake-driver en el classpath y especificar la clase de controlador jp.ne.opt.redshiftfake.postgres. FakePostgresqlDriver. Después de eso, puede usar la misma ruta migratoria para migrar el esquema de la base de datos, y dbunit ya está familiarizado para comparar datos después de ejecutar las pruebas.
Me pregunto cuántos lectores usan AWS y Redshift en su trabajo. Escriba en los comentarios sobre su experiencia.
Utilizando solo proyectos de código abierto, el equipo pudo acelerar el desarrollo en el entorno de AWS, ahorrar dinero del presupuesto del proyecto y no detener el trabajo del equipo cuando Roskomnadzor bloqueó las subredes de AWS.