Lista de comprobación de la arquitectura de software backend: cómo crear un producto desde cero

Te despiertas una mañana para tomar tu taza de café y listo, el momento Eureka está aquí. Finalmente descubrió su modelo de negocio y todo encaja. Sabes que a los inversores les encantará y no puedes esperar a empezar a desarrollar el producto. La ventaja de ser el primero en moverse es suya.

Estos momentos son raros, pero cuando suceden, debe comenzar en el momento adecuado. Todo lo que necesita es la guía adecuada que lo ayude a determinar lo que debe y no debe hacer. Este no es el momento de experimentar, es el momento de ejecutar. ¡Es TU momento ahora!

NOTA - Lo siguiente está relacionado con la construcción de arquitecturas de software desde cero. Entonces, si está interesado en conocer el meollo de las tecnologías involucradas, continúe. De lo contrario, comparta con aquellos a quienes definitivamente les encantará esto: P

De donde vino esta guía

Yo mismo he trabajado en un puñado de productos en fase inicial y, para ser honesto, cometí errores. Siempre deseé que hubiera una lista de verificación a seguir mientras construía un producto desde cero.

Hay tantas cosas involucradas en la construcción de una arquitectura desde cero que olvidarás por completo ciertas piezas. Y volverán a morderlo en etapas posteriores del ciclo del producto.

Finalmente decidí crear esta lista de verificación de cosas que debe considerar antes de presionar el botón de implementación por primera vez.

Entonces, sin más preparación, aquí está la lista de verificación que debe seguir al crear una arquitectura de backend para un producto desde cero.

Elija el lenguaje y el marco CORRECTOS (para su proyecto)

Elegir el lenguaje y el marco correctos para su producto es complicado, y no existe una fórmula mágica para ello. Mi consejo es que elijas un idioma con el que te sientas más cómodo y conozcas las complejidades de entrar y salir.

Habiendo dicho esto, es raro, porque hay muy pocas personas que sean Javascript Ninjas, Python Panthers o cualquier otro nombre original.

Así que elija un lenguaje que tenga un buen soporte en la industria, como Javascript, Python, Java o Go, por nombrar algunos. Puede elegir cualquier idioma, solo elija el que le resulte más cómodo.

Y recuerde: está creando un MVP (Producto mínimo viable) y estará en el proceso de crear un POC (Prueba de concepto). Así que saque su producto lo antes posible. No es necesario que se atasque en problemas que puedan surgir del nuevo idioma en la ciudad. Para evitar esos problemas, elija un lenguaje mejor documentado y más utilizado.

Por último, puede escalar en un momento posterior. Si está en la fase de hacer POC, simplemente compile y hágalo. Pero si está construyendo algo realmente específico, y hay un lenguaje y un framework especialmente para eso, entonces definitivamente debería elegir esa tecnología.

Pero la mayoría de las veces, los problemas que estamos tratando de resolver se pueden solucionar fácilmente con cualquiera de los lenguajes mencionados anteriormente y sus respectivos marcos. Así que elija uno y ponga en marcha su producto.

Un buen recurso para ayudarlo a decidir:

//content.techgig.com/top-5-programming-languages-for-backend-web-development/articleshow/67337449.cms

Implementar microservicios de autenticación y autorización

Hay muchas formas de autenticar y autorizar a un usuario. Puede probar Session Tokens, JWT (JSON Web Tokens) u OAuth, por nombrar algunos. Cada opción tiene sus pros y sus contras. Veamos algunos de ellos más de cerca.

Tokens web JSON

Los JWT son rápidos y fáciles de implementar. Esto se debe a que los tokens nunca se almacenan en ningún lugar de su sistema. Simplemente se codifican, se cifran y se envían al usuario. Por lo tanto, validar un JWT es más rápido que cualquier otro método.

Pero, dado que no están almacenados en el sistema, no puede hacer que un token caduque antes de su fecha de caducidad real, y esto puede ser un problema en ciertos casos.

Así que averigüe los pros y los contras de cada sistema de autenticación y elija el que mejor se adapte a sus necesidades. Personalmente prefiero los JWT (pero esa es mi propia elección).

Autorización

Nunca olvide implementar la autorización de los usuarios. No desea que Usuario1 conectado para cambiar los detalles de Usuario2. Esto puede causar un caos puro en su sistema.

Identifique los puntos finales que necesitan autorización e impleméntelos de inmediato. No desea que el estado de su base de datos se corrompa de esta manera. Recuerde la diferencia entre 401 y 403.

Los siguientes son ciertos puntos finales que definitivamente debe considerar al crear su sistema de autenticación (creé uno en Django usando JWT). Puede haber ciertas adiciones / eliminaciones para su caso de uso, pero estas son las que debe considerar compilar.

Muchos marcos los proporcionan de fábrica, pero considérelos antes de crearlos por su cuenta. Verifique authentication_classes y allow_classes en Django Rest Framework para obtener más referencias.

Eche un vistazo a este recurso de Django REST Framework:

//www.django-rest-framework.org/tutorial/4-authentication-and-permissions/

Cree un modelo base abstracto para que lo hereden todos los demás modelos de su base de datos

Recuerde el principio DRY - ¿No se repita? Debe seguirse hasta el núcleo en Ingeniería de Software.

Sobre la base del proceso de pensamiento anterior, habrá ciertas columnas en su base de datos que estarán presentes en cada tabla. Por lo tanto, es mejor crear una clase abstracta para ellos para que otras clases de modelo puedan heredar de ellos.

Repasemos este código y lo que significa:

  • id : aunque no está escrito aquí, el marco de Django lo crea automáticamente. Pero si no está en el suyo, escríbalo en esta clase. Es solo un campo incrementado automáticamente que se puede usar como clave principal en la relación de su base de datos.
  • created_at : esto implica cuándo se insertó el campo / fila en su tabla y el marco en sí lo llena. No es necesario configurarlo explícitamente.
  • updated_at : esto implica cuándo el campo / fila se modificó / actualizó por última vez en su tabla, y nuevamente se llena con el marco en sí.
  • delete_at + is_deleted : este es un campo controvertido. No tengo una respuesta exacta sobre si debería estar allí o no, porque para ser honesto, nunca se elimina nada en Internet. Este campo, si se completa, indica que la fila se elimina del sistema (aunque los datos permanecen en el sistema para futuras referencias y se pueden quitar de la base de datos y almacenar en copias de seguridad)
  • uuid : depende de si desea poner esto en su tabla o no. Si necesita exponer la clave principal de su tabla a un sistema externo, es mejor exponer esta en lugar del campo entero incrementado automáticamente. Quizás te preguntes por qué ... Bueno, ¿por qué querría decirle a un sistema externo que tiene 10378 pedidos en su mesa? Pero nuevamente es una elección personal.

Configurar un microservicio de notificación

Cada producto debe enviar recordatorios y notificaciones al usuario con fines transaccionales y de participación. Así que todos los productos necesitarán esto.

Definitivamente debería considerar la posibilidad de crear un microservicio que proporcione servicios de notificación (como notificaciones push, correos electrónicos y SMS) a sus usuarios finales.

Este debería ser un Microservicio completamente separado. No cree esto dentro de su microservicio de autenticación o su servicio de aplicación (la lógica empresarial real).

Hay muchas bibliotecas / servicios de terceros que se pueden usar para construirlo para su aplicación. Aprovecha y construye sobre eso.

Recuerde construir las 3 funcionalidades:

  • Notificaciones push (APNS + FCM),
  • Correos electrónicos (solo integre un cliente SMTP para comenzar)
  • y SMS

NOTA - Disponga de dos canales para enviar SMS, transaccional y promocional. Nunca envíe un SMS promocional en un canal transaccional, ya que existe la posibilidad de que sea demandado por un usuario bien informado y motivado.

Una manera fácil de configurar su cliente SMTP en su aplicación es usar esto en su configuración:

Hice esto en Django, pero puedes hacer lo mismo en el lenguaje y marco que elijas.

Configurar el registro de errores

Utilice un middleware para registrar los errores que ocurren en su sistema de producción. Su sistema de producción no será monitoreado por humanos sentados allí para ver los registros de la aplicación 24/7. Por lo tanto, necesitará un sistema que registre esos errores internos del servidor en un lugar central. Luego, puede ir y revisarlos a diario o crear un webhook para que pueda recibir alertas en el momento adecuado y ocuparse de ellos.

Hay muchas herramientas de registro de errores de terceros en el mercado. Simplemente elija el que se adapte a sus necesidades. Yo uso principalmente Sentry / Airbrake.

Considere configurar webhooks, como mencioné anteriormente. Ellos informarán a sus usuarios sobre errores y, por ejemplo, puede publicar esos errores cuando ocurran en ciertos canales de holgura. Luego, puede verificar esos canales de manera regular y rectificarlos en función de su gravedad.

Página de inicio oficial de Airbrake - //airbrake.io/

Página de inicio oficial de Sentry: //sentry.io/welcome/

Solicitud de implementación: registro de respuesta y aplicación

Escenario : un usuario viene a su soporte y dice que no ha recibido el recibo de transacción por la compra que realizó en su sitio web. ¿Qué harás?

Si ha puesto el registro de aplicaciones en su sistema, no se preocupe. Ahora, ¿qué quiero decir con eso? Siempre es mejor dar un ejemplo que tratar de explicar con palabras. Asi que aqui esta:

He registrado que estoy a punto de enviar el correo electrónico al email_id mencionado. Puedo verificar los registros de la aplicación para ver si el correo electrónico se envió realmente al cliente al verificar si dicho registro existe en el sistema. Asegúrese de incluir registros completos en su sistema para que pueda rastrear el viaje de la solicitud.

Además, es una buena idea poner en marcha un sistema asíncrono que seleccionará los registros de solicitudes y respuestas y de aplicaciones de su sistema y los guardará en un lugar central. Allí se pueden procesar para que sean más fáciles de interpretar.

La pila ELK es una buena opción para esto: ElasticSearch - Logstash - Kibana.

Más sobre la pila ELK - //www.elastic.co/what-is/elk-stack

NOTA : al registrar solicitudes y respuestas, tenga en cuenta lo siguiente:

  • No registre contraseñas.
  • No registre tokens (los tokens de acceso que se utilizan para la autenticación)
  • No registre OTP

Introduzca la limitación en sus API y la limitación de velocidad en sus servidores de aplicaciones.

Escenario : acaba de lanzar su servicio y ha comercializado el producto en plataformas de redes sociales. Un hacker de sombrero negro se enteró y solo quería jugar con su sistema. Entonces planearon un ataque DOS (Denial of Service) en su sistema.

Para combatir esto, puede establecer una limitación de velocidad basada en varios factores además de sus balanceadores de carga para sus servidores de aplicaciones. Esto se encargará de los ataques de DOS y evitará que el usuario malintencionado ataque sus servidores.

Escenario : el punto final de la API / otp / validate que toma OTP de 4 dígitos para autenticar al usuario y devuelve tokens para usar con las API autenticadas. Un usuario malintencionado obtiene el número de móvil de uno de sus clientes y comienza a llegar al punto final de la API con un ataque de fuerza bruta que cambia las IP, un ataque DDOS (denegación de servicio distribuida). El limitador de velocidad no puede detener al usuario, porque la IP sigue cambiando con cada solicitud realizada.

Para detener esto, también puede limitar las API en función del usuario. Puede configurar cuántas solicitudes puede realizar un usuario en particular a un punto final de API. Para la validación de OTP, un buen número es de 5 solicitudes cada 10 minutos. Esto evitará que el usuario malintencionado realice un ataque DDOS de fuerza bruta en la API anterior.

Limitación en el marco REST de Django -

//www.django-rest-framework.org/api-guide/throttling/

Establezca y configure la comunicación asincrónica desde el primer día

Escenario: debe enviar un correo electrónico de bienvenida al usuario cuando se registre en su aplicación. El cliente frontal accede a la API de registro, usted crea el usuario en el backend después de las validaciones y esto inicia el proceso de envío de un correo electrónico de bienvenida.

Enviar este correo electrónico de bienvenida llevará tiempo, quizás unos segundos. Pero, ¿por qué querría que el cliente móvil se quedara atascado en ese proceso? Esto puede suceder en segundo plano sin que el usuario se quede atascado sin ningún motivo en particular en la página de registro. Cada segundo es precioso y no quiere que el usuario pierda esos preciosos segundos.

Así que envíe el correo electrónico a través de una tarea asincrónica. Utilice trabajadores, tareas, agentes de mensajes y back-end de resultados para realizar esto.

Un buen ejemplo de esto en el mundo de Python es Celery worker. Simplemente coloque la tarea que debe realizarse en un intermediario de mensajes (Rabbit MQ / SQS, etc.). Apio escuchará esto y enviará la tarea al trabajador designado. Ese trabajador procesará la solicitud y pondrá el resultado en un backend de resultados que puede ser un sistema de caché / sistema de base de datos. (Redis / PostgreSQL por ejemplo).

Puede monitorear estas tareas y colas con muchas bibliotecas de terceros. Un buen ejemplo de esto es Celery Flower que monitorea todo esto.

Puede leer más sobre RabbitMQ aquí: //www.rabbitmq.com/

Y apio - //docs.celeryproject.org/en/stable/django/first-steps-with-django.html

Y finalmente, Flor de apio - //flower.readthedocs.io/en/latest/

Configurar trabajos cron

Escenario: acaba de lanzar su producto y necesita enviar recomendaciones a sus usuarios sobre nuevos productos en su plataforma. Los enviará en función de su historial de compras cada fin de semana.

La tarea anterior se puede realizar fácilmente utilizando un trabajo cron. Es fácilmente configurable en cualquier marco. Lo importante a tener en cuenta es que no debe poner los trabajos cron directamente en el archivo crontab de su servidor. Debe dejar que el marco lo maneje.

Esto se debe a que el ingeniero de implementación / ingeniero de Devops debe ser la única persona que tenga acceso al sistema de esta manera por razones de seguridad. Aunque no tiene que implementarlo de esta manera, es bueno tenerlo desde el principio.

En el mundo de Django, puedes usar celerybeat para configurar tus crons usando trabajadores de apio.

Obtenga más información sobre Celery Beat aquí: // docs.celeryproject.org/en/latest/userguide/periodic-tasks.html

Administre sus secretos correctamente (archivo de parámetros)

Hay muchas formas de administrar los secretos de los parámetros en sus servidores de producción. Algunos de ellos son:

  • Crear un archivo de secretos y almacenarlo en un depósito s3 privado y extraerlo durante la implementación de su aplicación.
  • Establecer los parámetros en las variables de entorno durante la implementación de su aplicación (almacenarlos en s3 nuevamente)
  • Poner los secretos en algún servicio de administración de secretos (por ejemplo, //aws.amazon.com/secrets-manager/) y usarlos para obtener los secretos en su aplicación.

Puede elegir cualquiera de estos métodos según su comodidad y su caso de uso. (También puede optar por mantener diferentes archivos secretos para entornos locales, de ensayo y de producción).

Versión de sus API desde el primer día

Esto es algo que definitivamente debe considerar desde el primer día. Nunca sabrá con qué frecuencia pueden cambiar sus modelos de negocios, y debe tener compatibilidad hacia adelante y hacia atrás en su aplicación. Por lo tanto, debe versionar sus API para asegurarse de que todo funcione sin problemas para todos.

Puede tener diferentes aplicaciones para diferentes versiones y dejar que nginx lo maneje para su aplicación. O puede tener el control de versiones en la propia aplicación y dejar que las rutas en su servidor de aplicaciones lo manejen. Puede elegir cualquier método para implementarlo; el punto principal es tener habilitado el control de versiones desde el principio.

Decidir sobre las comprobaciones de la versión de actualización dura y suave para sus clientes frontales

Entonces, ¿cuál es la diferencia entre actualizaciones duras y suaves?

Las actualizaciones duras se refieren a cuando el usuario se ve obligado a actualizar la versión del cliente a un número de versión superior al que está instalado en su móvil.

Las actualizaciones suaves se refieren a cuando se le muestra al usuario un mensaje de que hay una nueva versión disponible y puede actualizar su aplicación a la nueva versión si así lo desea.

No se recomiendan las actualizaciones duras, pero hay ocasiones en las que es necesario hacerlas cumplir. Cualquiera que sea el caso, definitivamente debe considerar cómo va a implementar esto para sus aplicaciones.

Puede hacer esto implementándolo o configurándolo en Play Store o App Store. Otra forma es crear una API en su aplicación de backend que se activará cada vez que se inicie la aplicación móvil. Esto enviará dos claves: hard_update -> true / false y soft_update -> true / false, dependiendo de la versión del usuario y las versiones de actualización dura y suave configuradas en su sistema backend.

Un buen lugar para almacenar estas versiones es en su caché (Redis / Memcache), que puede cambiar sobre la marcha sin necesidad de implementar su aplicación.

Introducir la integración continua (CI) desde el primer día

Escenario: uno de los pasantes que trabaja en su proyecto no es lo suficientemente competente para escribir código de nivel de producción. Es posible que hayan cambiado algo que podría romper algún componente crítico en su proyecto. ¿Cómo puede asegurarse de que todo esté bien en tales casos?

Introducir la integración continua. Ejecutará linters y casos de prueba en cada confirmación y se romperá si se viola alguna regla. Esto, a su vez, impedirá que la solicitud de extracción se fusione hasta que se aprueben todas las reglas y los casos de prueba. Es bueno tener algo y, de hecho, también ayuda a largo plazo, así que téngalo en cuenta.

Hay muchas opciones disponibles en el mercado. Puede optar por implementar uno por su cuenta (Jenkins CI / CD), o puede usar TravisCI, CircleCI, etc. para lo mismo.

Lea sobre TravisCI aquí: //travis-ci.org/

Y CircleCI - //circleci.com/

Habilitar la compatibilidad con Docker (preferencia personal)

Cree un Dockerfile y docker-compose.yml para su aplicación para que todos ejecuten la aplicación usando Docker desde el principio. Una de las principales razones para utilizar este enfoque es tener coherencia en su entorno local / de ensayo / producción, de modo que ningún desarrollador pueda volver a decir esto:

Pero funcionó en mi máquina.

No es difícil emplearlo desde el primer día. Al principio, utilice Docker para su entorno local para que la configuración de su aplicación sea realmente sencilla. Pero tenga en cuenta cómo puede ejecutarlo con y sin Docker en producción.

Aquí hay más información sobre Docker Hub: //hub.docker.com/

Utilice una herramienta APM

Una herramienta de monitoreo de aplicaciones es imprescindible si desea monitorear las API, transacciones, conexiones de base de datos, etc.

Escenario : el disco duro de su servidor cron está casi lleno y no puede ejecutar trabajos cron. Dado que no puede encontrar espacio en el disco, sus padres no se están ejecutando. Entonces, ¿cómo puede recibir una notificación cuando esto sucede?

Hay muchas herramientas APM que puede usar para monitorear esto. Puede configurarlos de acuerdo con cuando necesite ser notificado. Recibirá notificaciones en el medio que elija cuando ocurra tal caos en su sistema, y ​​créame, sucede todo el tiempo. Así que mejor prepárate para ello. New Relic es una buena opción.

Lea más sobre New Relic aquí - //newrelic.com/

Use ElasticSearch para impulsar búsquedas en toda la aplicación en sus aplicaciones cliente

Según wikipedia,

Elasticsearch es un motor de búsqueda basado en la biblioteca Lucene. Proporciona un motor de búsqueda de texto completo distribuido y con capacidad para múltiples inquilinos con una interfaz web HTTP y documentos JSON sin esquema. Elasticsearch está desarrollado en Java.

Al principio, tendrá la tentación de utilizar consultas de bases de datos tradicionales para obtener resultados en esa barra de búsqueda para la aplicación cliente. ¿Por qué? Porque es facil.

Pero las bases de datos tradicionales no están pensadas para consultas tan eficaces. Encuentre un buen momento para migrar su búsqueda a ElasticSearch e introducir una canalización de datos en su sistema. Alimenta la búsqueda elástica con datos y luego conecta la búsqueda de ElasticSearch al servidor de aplicaciones.

Aquí hay una buena descripción general de Elasticsearch para comenzar.

Y ElasticSearch Docs: //www.elastic.co/guide/index.html

Ponga un firewall en su servidor de producción

Definitivamente deberías hacer esto, es imprescindible. Coloque un firewall en su servidor de producción y cierre todos los puertos excepto los que se usarán para las API (conexiones https). Enrute los puntos finales de la API mediante un servidor web proxy inverso, como NGiNX o Apache. Ningún puerto debe ser accesible para el mundo exterior que no sean los permitidos por NGiNX.

Por qué debería usar NGiNX:

  • //www.nginx.com/resources/wiki/community/why_use_it/
  • //blog.serverdensity.com/why-we-use-nginx/
  • //www.freecodecamp.org/news/an-introduction-to-nginx-for-developers-62179b6a458f/

Terminando

Los puntos mencionados anteriormente se basan en mis propias preferencias y los he desarrollado a lo largo de los años. Habrá ligeras diferencias aquí y allá, pero los conceptos siguen siendo los mismos.

Y al final, hacemos todo esto para tener un sistema fluido construido desde cero que se ejecute en producción lo antes posible después de que se le haya ocurrido la idea.

Intenté anotar todos los conocimientos que había adquirido a lo largo de los años y es posible que me equivoque en algunos lugares .Me f que creo que se pueda ofrecer una mejor información , no dude en hacer comentarios. Y como siempre, comparta si cree que esto es útil.