Introducción al proyecto del curso y su arquitectura

1

Creación de Backend Complejo con Microservicios y Arquitectura Escalable

2

Modelado de Datos para una Red Social Básica en SQL

Creando la estructura principal

3

Configuración de un Servidor API con Express y Node.js

4

Estructuración de API y Gestión de Datos en JavaScript

5

Controladores con Inyección de Dependencias en Node.js

6

Documentación de APIs con Swagger en Node.js

Autenticación basada en tokens

7

Autenticación y Seguridad con Tokens JWT en Aplicaciones Web

8

Autenticación de Usuarios con JWT y Gestión de Contraseñas Seguras

9

Implementación de Login Seguro con JWT y Cifrado de Contraseñas

10

Cifrado de Contraseñas con Bcrypt en Aplicaciones Node.js

11

Autenticación y Autorización con JWT en Node.js

12

Implementación de Autenticación y Autorización en Aplicaciones Web

13

Manejo de Errores y Seguridad en Aplicaciones Node.js

Almacenando datos: MySql

14

Almacenamiento de Datos con MySQL en Node.js

15

Funciones CRUD en Base de Datos con Node.js

16

Creación de Tabla Intermedia para Relaciones de Seguimiento de Usuarios

17

Gestión de Seguidores y Publicaciones en Redes Sociales

Microservicios en Node

18

Arquitectura de Microservicios: Separación y Gestión Eficiente

19

Creación de Microservicios para Bases de Datos con Node.js

20

Conexión y Configuración de Microservicios de Bases de Datos Remotas

21

Separación Horizontal de Microservicios: Implementación y Beneficios

22

Gestión de Microservicios en Producción con PM2

Puesta en producción serverless

23

Despliegue de Aplicaciones Serverless con Vercel y AWS

24

Variables de Entorno y Despliegue Local con Node.js

Cacheando nuestra aplicación

25

Implementación de Caché con Redis para Microservicios

26

Conexión de Microservicios a Redis y Gestión de Caché

27

Cacheo y Optimización de Consultas en Microservicios

Puesta en producción en virtual machine

28

Instalación y Configuración de Microservicios en Máquinas Virtuales

29

Configuración de Nginx como proxy para microservicios en producción

No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Conexión y Configuración de Microservicios de Bases de Datos Remotas

20/29
Recursos

¿Cómo crear un archivo para una base de datos remota?

Para empezar, es crucial crear un sistema que sea lo más genérico y reutilizable posible para poder conectar diferentes bases de datos a través de microservicios. Esto nos permitirá no exponer la base de datos directamente, manteniendo así la seguridad y modularidad del sistema.

¿Qué es un constructor de base de datos remotas?

La clave está en desarrollar un "constructor de base de datos remotas" que nos permita generar nuestra base de datos de manera remota y utilizarla con las mismas funciones, sin necesidad de modificar nuestro código continuamente. Este patrón es escalable y nos permite trabajar con múltiples bases de datos o microservicios.

¿Cómo configurar la base de datos remota?

Primero, debemos asegurarnos de que tenemos nuestra base de datos bien configurada y abierta para seguir trabajando con ella. Seguidamente:

  1. Crear un archivo, por ejemplo, Remote.js, para gestionar la conexión remota.
  2. Importar un módulo llamado request para simplificar las peticiones HTTP.
    const request = require('request');
    
  3. Definir la URL base que usaremos para hacer las peticiones HTTP al microservicio:
    const baseURL = `${host}:${port}`;
    

¿Cómo implementar las funciones de acceso remoto?

Implementar funciones que manejen las operaciones comunes de la base de datos, como listar, agregar, modificar, y eliminar datos.

  • Función para listar datos:

    function list(table) {
        return requestPromise('GET', table);
    }
    
  • Función para manejar peticiones:

    function requestPromise(method, table) {
        const url = `${baseURL}/${table}`;
        return new Promise((resolve, reject) => {
            request({ method: method, url: url, json: true },
            (error, response, body) => {
                if (error) {
                    console.error('Error:', error);
                    return reject(error);
                }
                resolve(body);
            });
        });
    }
    

¿Cómo conectar y probar nuestra API?

Finalmente, integrémoslo al componente de usuarios para verificar su correcto funcionamiento:

  1. En el index del componente, importa y utiliza Remote.js:

    const remote = require('./remote');
    // Verificar funcionalidad de listar usuarios
    remote.list('users').then(data => console.log(data));
    
  2. Ejecutar los servicios con nodemon para facilitar el desarrollo en ambos terminales:

    nodemon mysql/index.js
    nodemon api/index.js
    

¿Notas cómo la abstracción nos permite trabajar a nivel de API sin preocuparnos por detalles de implementación de base de datos? Este modelo no solo simplifica el manejo de bases de datos múltiples, sino que también mejora la escalabilidad y seguridad de tu aplicación al encapsular y aislar cada servicio individualmente.

Recuerda, la modularidad y reutilización son principios fundamentales cuando trabajamos en proyectos de software a gran escala. ¡Aprende, experimenta y sigue creciendo en el mundo del desarrollo!

Aportes 24

Preguntas 8

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

Excelente, lo que quiere decir que nuestra API se convierte en cliente con respecto al server que sirve el servicio de nuestra BD.

La verdad creo que esta clase deberia añadir el hacer la comunicación con HTTP2 con gRPC o un message broker (Apache Kafka); que es la manera en que se maneja la comunicación entre microservicios en lo laboral

Si usamos typescript podemos definir una interfaz para la definición de métodos en los archivos dentro del store 😃

Excelente clase muchas gracias a toda la gente de platzi !!
remote.js

const axios = require('axios');

function CreateRemoteDataBaseApi (host, port) {
  const remoteDataBaseCall = axios.create({
    baseURL: `${host}:${port}`,
    headers: {
      'Content-Type': 'application/json',
      'Accept': 'application/json'
    }
  })

  async function request({method, url, data}) {
    const reponse = await remoteDataBaseCall({
      method: method,
      url: url,
      data: data
    });
    return reponse.data.body;
  }

  function list(table) {
    return request({
      method: 'GET',
      url: `/${table}`,
    })
  }

  function get(tabla, id) {
    return request({
      method: 'GET',
      url: `/${tabla}/${id}`,
    })
  }

  function query(tabla, query, join = '') {
    return request({
      method: 'GET',
      url: `/query/${tabla}`,
      data: {
        "query": query,
        "join": join
      }
    })
  }

  function create(table, data) {
    return request({
      method: 'POST',
      url: `/${table}`,
      data
    })
  }

  function update(table, data_id, data) {
    throw new Error('Not implemented');
  }

  async function upsert(tabla, data) {
    return request({
      method: 'PUT',
      url: `upsert/${tabla}`,
      data
    })
  }

  async function remove(tabla, id) {
    return request({
      method: 'DELETE',
      url: `/${tabla}/${id}`
    })
  }

  return {
    list,
    get,
    query,
    create,
    update,
    upsert,
    remove,
  };
}

module.exports = CreateRemoteDataBaseApi;

Reto resuelto:

const request = require('request');

let urlRemote;

function req(method, table, data = null) {
    let url = `${urlRemote}/${table}`;
    let body = '';

    if(data && method === 'GET') {
        url += `/${id}`;
    } else if(data) {
        body = JSON.stringify(data);
    }
    
    return new Promise((resolve, reject) => {
        request({
            url,
            method,
            body,
            headers: {
                'content-type': 'application/json'
            }
        },(error, req, result) => {
            if(error) {
                console.error('Error en la base de datos', error);
                return reject(error.message);
            }

            const res = JSON.parse(result);
            return resolve(res.body);
        });
    });
}

function insert(table, data) {
    return req('POST', table, data);
}

function update(table, data) {
    return req('PUT', table, data);
}

module.exports = class RemoteStore {

    constructor(host, port) {
        urlRemote = `http://${host}:${port}`
    }

    list(table) {
        return req('GET', table);
    }

    get(table, id) {
        return req('GET', table, id);
    }

    upsert(table, data) {
        if(data.id) {
            return update(table, data);
        }
        return insert(table, data);
    }
}

Ok, sera necesario volverlo a ver

Ayuda, en el archivo remote-mysql porque se utiliza la palabra new para utilizar a remote?

Podria alguien explicarme porque al profesor si le corrio el codigo? Utilizando el new sin usar la clase? jaja no entiendo

les comparto mi archivo de peticiones con axios

const axios = require('axios');

class AxiosInstance {
    constructor(config = {}) {
        this.axios = axios.create(config);
    }

    send(url, method, data) {
        return new Promise((resolve, reject) => {
            this.axios({
                method,
                url,
                data
            })
                .then(response => resolve(response.data))
                .catch(error => reject(error))
        })
    }
}

module.exports = AxiosInstance;

y el mysqlRemote

const AxiosInstance = require('./../utils/axios-instance');
const config = require('./../config');

class MysqlRemote {
    constructor() {
        this.request = new AxiosInstance({
            baseURL: config.mysql.mysqlService.host,
            timeout: 5000,
            headers: {'Content-Type': 'application/json'},
        })
    }

    list(table) {
        return this.request.send(`/${table}`, 'GET');
    }
}

module.exports = new MysqlRemote();

a ver en “resumidas” palabras está haciendo peticiones desde un microservicio hacía otro desde http, lo anterior también se puede hacer con axios, está chévere este mundillo de los microservicios 😁

Si tenemos multiples instancias de un micro servicio, como balanceamos las cargas de solicitudes de cada una de ellas?

Si es que tienen problemas con errores internos, vayan al código de error.js
en

response.error(req,res,err,status)

Pongan err para ver el tipo de error. Ahora después de aquello si tienen este error.

[error]: connect ECONNREFUSED 127.0.0.1:80

Deben arrancar los dos servicios de api/index.js y el de mysql/index.js en 2 terminales.

AYUDA cuando hago leer users en insomnia me devuelve
un 500 en en consola me da este error

[error]: connect ECONNREFUSED 127.0.0.1:80
error en la DB remota Error: connect ECONNREFUSED 127.0.0.1:80
at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1134:16) {
errno: ‘ECONNREFUSED’,
code: ‘ECONNREFUSED’,
syscall: ‘connect’,
address: ‘127.0.0.1’,
port: 80

Hola! pregunto si alguien subió el repositorio de este curso y me lo puede facilitar, le agradecería bastante :)
¿Cómo es que sucede la conexión y autorización hacia la base de datos? Esta parte me dejo confundido, pues se cambia el archivo y ya no estamos manejando la conexión desde el remote-mysql

Todo perfecto, lo único que no entendí es que ¿se puede crear una new Instance de una función? ¿O por lo menos se podía?
A mi me dio error, asi que solo la invoqué como función.

Usando la orientación del profe a funciones como clases y axios me salió esto:

const axios = require("axios");

function createRemoteDB(host, port) {
  const URL = `htt://${host}:${port}`;

  function handleRequest(method, table, data) {
    const config = {
      method,
      url: `${URL}/${table}`,
      data: data || null,
    };
    return new Promise((resolve, reject) => {
      axios(config)
        .then((response) => {
          resolve(response.data.response);
        })
        .catch((error) => {
          reject(error);
        });
    });
  }


  function list(table) {
    return handleRequest("GET", table);
  }

  return {
    list
  };
}

module.exports = createRemoteDB;

Luego en el remote-mysql.js

const remote = require("./remote");
const config = require("../config");

module.exports = new remote(
  config.microservice.db.host,
  config.microservice.db.port
);

Es más parecido a lo que hizo el profe, pero usando Axios que es la misma librería que se suele usar en el frontend, aunque para esto toca instalar axios

npm i axios

levantamos los dos servicios

al principio me confundia, pero ya poco a poco me esta quedando claro… me parece muy bien aplicar esto de servicios remote, para la api


Al cambiar la base de datos a remote-mysql en index de la carpeta de usuario me manda el error que la tabla no ha sido identificada o no existe. Alguien sabe a que se puede deber esto?

Interesante dado que es tener cada servicio en un backend aparte (incluso en express con un app para cada uno) y comunicarse mediante peticiones HTTP (Se pueden hacer también con fetch o con la librería axios que a muchos le gusta)

Es impresionante esto de microservicios.
Entonces al crear microservicios estamos refactorizando y modularizando a un nivel mucho más abstracto nuestra arquitectura del servidor?