none
Es buena práctica que un API llame a otra API como arquitectura de aplativo RRS feed

  • Pregunta

  • Hola

    Estoy creando un listado de Apis, hasta el momento tengo 4 APIs creadas y agregadas a una solución, algo similar a esto:

    Solución

    • Api.Posts (project)
    • Api.Users (project)
    • Api Common (project)
    • Api Images (project) 
    • Shared (project) --utilidades
    • Entities (project)

    Internamente cada proyecto API consta de la siguiente estructura de carpetas ya que debe seguir cierta arquitectura.

    • DAL
    • BL
    • Facade

    Actualmente desarrollé los métodos POST y DELETE de las APIs. Cada API debe tener su lógica y estar especializada en su negocio, sin embargo me surge la siguiente duda especialmente con los métodos GET.

    Ej. Uno de los métodos del Api Post es la obtención de una Publicación, a su vez esta debe tener también la información del Usuario que publicó. El Api.Users cuenta con un UserBL el se encarga de la obtención de la información del usuario.
    Basado en una arquitectura y tomando en cuenta que no puedo agregar referencias (dlls) de un proyecto API a otro, desde el API.Posts debo:

    • ¿Hacer una invocación del API.Users para obtener la data del usuario?
    • ¿Disponer del UsersBL en un proyecto aparte para poder accederlo desde cualquier API?
    • ¿Otra opción...?

    La primera opción me causa un poco de molestia porque hay casos donde debo Obtener un Listado de Publicaciones y si por cada item encontrado debo consultar un API va afectar el performance notablemente y más cuando las listas sean grande.
    Sin embargo la 2da opción me desagrada que si realizó un cambio en una de las APIS no se verán reflejado en las otras.

    Que recomendaciones me dan? Obviamente la idea es que el proyecto sea lo mas escalable posible y fomentar el desarrollo de componentes.

    Las APIS la estoy desarrollando con ASP .Net Core y Visual Studio 2017.

    Gracias 

    viernes, 23 de noviembre de 2018 4:21

Respuestas

  • hola

    Me perdi en el codigo que DAL es usada desde que Api, pero entiendo que la ultima UserDAL esta en Api.Posts, si es asi es correcto

    ojo que la UserBL deberia estar expuesta desde la Api.Users, porque entiendo que la BL por si sola es una dll que no genera una url

    Un tema mas, recuerda usar IoC con librerias como ser Unity,Ninject, etc para poder crear una UserDALMock en Api.post y asi cuando tengas que definir test poder mockear esta clase y no tener que llamar al servicio real de usuario, tambien es bueno tener un mock para poder probar local si tener todos los servicio ejecutando

    >>Pero mi pregunta es si a nivel de performance no perjudica mucho el rendimiento,

    No deberia si estas en una misma red o si los servicios estan hosteados en la misma pc, si podrias tener problemas de performance si cada api esta en equipos separados y se comunica por la red, un ancho de banda lento puede traer problemas ,pero bueno esto ya seria un sistema distribuido

    pero si esta todo local deberia ser instantaneo

    la idea de usar esta tecnica no es traerte miles de registros, la idea es traer lo que necesites asignando filtros, a ver si tienes registrados mil usuario no te traigas los mil siempre, ve de recuperar los que necesitas

    la tecnica de cache que comenta Sergio, es util, pero hay que ver si el dato es muy cambiante, digo si los los datos del usuario no cambian mucho se podria aplicar cache sin problemas

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    • Propuesto como respuesta Pablo RubioModerator lunes, 26 de noviembre de 2018 17:27
    • Marcado como respuesta AdyIr martes, 27 de noviembre de 2018 14:03
    sábado, 24 de noviembre de 2018 11:44
  • hola

    >>Hacer una invocación del API.Users para obtener la data del usuario

    a ver, la arquitectura de microservicio contempla esta opcion, porque aunque no lo mencionas la separacion de responsabilidad que planteas tiende a ser la de microservice

    Microservicios de .NET: arquitectura para aplicaciones .NET en contenedor

    Ahora bien si vas a comunicar a nivel de API deberas desacoplar, o sea no pudes hacer referencia a las dll entre estas, sino que usarias una llamada HTTP a la url del otro servicio que expone el listado, la idea es que sea todo asincrono

    Comunicación en una arquitectura de microservicio

    Puede ser un poco mas complicado pero asi es como funciona esta arquitectura

    >>Disponer del UsersBL en un proyecto aparte para poder accederlo desde cualquier API

    a nivel de BL se podria referenciar las dll, pero deberias llevar esto a una capa de negocio comun, nuevamente si vas a invocar algo de negocio de otro servicio deberias hacerlo por su api

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    • Propuesto como respuesta Sergio ParraModerator viernes, 23 de noviembre de 2018 7:34
    • Marcado como respuesta AdyIr martes, 27 de noviembre de 2018 14:03
    viernes, 23 de noviembre de 2018 5:05

Todas las respuestas

  • hola

    >>Hacer una invocación del API.Users para obtener la data del usuario

    a ver, la arquitectura de microservicio contempla esta opcion, porque aunque no lo mencionas la separacion de responsabilidad que planteas tiende a ser la de microservice

    Microservicios de .NET: arquitectura para aplicaciones .NET en contenedor

    Ahora bien si vas a comunicar a nivel de API deberas desacoplar, o sea no pudes hacer referencia a las dll entre estas, sino que usarias una llamada HTTP a la url del otro servicio que expone el listado, la idea es que sea todo asincrono

    Comunicación en una arquitectura de microservicio

    Puede ser un poco mas complicado pero asi es como funciona esta arquitectura

    >>Disponer del UsersBL en un proyecto aparte para poder accederlo desde cualquier API

    a nivel de BL se podria referenciar las dll, pero deberias llevar esto a una capa de negocio comun, nuevamente si vas a invocar algo de negocio de otro servicio deberias hacerlo por su api

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    • Propuesto como respuesta Sergio ParraModerator viernes, 23 de noviembre de 2018 7:34
    • Marcado como respuesta AdyIr martes, 27 de noviembre de 2018 14:03
    viernes, 23 de noviembre de 2018 5:05
  • hola

    >>Hacer una invocación del API.Users para obtener la data del usuario

    a ver, la arquitectura de microservicio contempla esta opcion, porque aunque no lo mencionas la separacion de responsabilidad que planteas tiende a ser la de microservice

    Microservicios de .NET: arquitectura para aplicaciones .NET en contenedor

    Ahora bien si vas a comunicar a nivel de API deberas desacoplar, o sea no pudes hacer referencia a las dll entre estas, sino que usarias una llamada HTTP a la url del otro servicio que expone el listado, la idea es que sea todo asincrono

    Comunicación en una arquitectura de microservicio

    Puede ser un poco mas complicado pero asi es como funciona esta arquitectura

    >>Disponer del UsersBL en un proyecto aparte para poder accederlo desde cualquier API

    a nivel de BL se podria referenciar las dll, pero deberias llevar esto a una capa de negocio comun, nuevamente si vas a invocar algo de negocio de otro servicio deberias hacerlo por su api

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    Hola Leandro, gracias por tu respuesta

    Entiendo lo que dices, la verdad no he trabajado con microservicios pero se más o menos de que se trata. Según entiendo propones algo asi? 

    class Post
    {
    	public long PostID { get; set; }
    	public string Name { get; set; }
    	public DateTime Birthdate { get; set; }
    }
    class Post
    {
    	public long PostID { get; set; }
    	public string Title { get; set; }
    	public DateTime Date { get; set; }
    	public Post Post { get; set; }
    }
    // API UserS
    class UserBL
    {
    		public User GetUser(long userID)
    		{
    			UserDAL dal = new UserDAL();
    			var resultado = dal.GetUser(userID);
    			return ConverToEntity(resultado);
    		}
    }
    // API PostS
    class PostBL
    {
    		public List<Post> GetPostList(long PostID)
    		{
    			PostDAL dal = new PostDAL();
    			UserDAL userDAL = new UserDAL();
    			List<Post> resultado = new List<Post>();
    			var posts = dal.GetPost(PostID);
    			foreach(item in posts)
    			{
    				Post post = ConverToEntity(resultado);
    				//Llamo a un API para obtener el usuario
    				post.User = userDAL.GetUser(item.UserID);
    			}
    			return resultado;
    		}
    }
    class UserDAL
    {	
    		public User GetUser(long userID)
    		{
    			HttpClient client = new HttpClient();
    			HttpResponseMessage response = await client.GetAsync("<url>");
    			response.EnsureSuccessStatusCode();
    			string responseBody = await response.Content.ReadAsStringAsync();
    			return Mapper.Map<User>(responseBody);
    		}
    }

    Pero mi pregunta es si a nivel de performance no perjudica mucho el rendimiento, tener que por cada item de la lista ejecutar un api y peor aun que pasa cuando sean multiples datos, es decir, en el ejemplo solo busco data del User pero que pasa cuando necesite mucha más data de otras APIS. 

    ¿Exista una mejor manera de trabajar esto manteniendo la indepencia de cada api o microservicio? Quiza lo estoy viendo de una manera equivocada.

    Saludos

    viernes, 23 de noviembre de 2018 21:27
  • Hola. Para aumentar rendimiento en Microservicios yo propongo usar un sistema de caché distribuida como Redis o NCache. Puede mejorar rendimiento hasta un 80% en consultas a base de datos  

    Si se solucionó tu consulta no olvides marcar la respuesta. Si te ayudó, vótala como útil. Saludos

    viernes, 23 de noviembre de 2018 21:57
    Moderador
  • hola

    Me perdi en el codigo que DAL es usada desde que Api, pero entiendo que la ultima UserDAL esta en Api.Posts, si es asi es correcto

    ojo que la UserBL deberia estar expuesta desde la Api.Users, porque entiendo que la BL por si sola es una dll que no genera una url

    Un tema mas, recuerda usar IoC con librerias como ser Unity,Ninject, etc para poder crear una UserDALMock en Api.post y asi cuando tengas que definir test poder mockear esta clase y no tener que llamar al servicio real de usuario, tambien es bueno tener un mock para poder probar local si tener todos los servicio ejecutando

    >>Pero mi pregunta es si a nivel de performance no perjudica mucho el rendimiento,

    No deberia si estas en una misma red o si los servicios estan hosteados en la misma pc, si podrias tener problemas de performance si cada api esta en equipos separados y se comunica por la red, un ancho de banda lento puede traer problemas ,pero bueno esto ya seria un sistema distribuido

    pero si esta todo local deberia ser instantaneo

    la idea de usar esta tecnica no es traerte miles de registros, la idea es traer lo que necesites asignando filtros, a ver si tienes registrados mil usuario no te traigas los mil siempre, ve de recuperar los que necesitas

    la tecnica de cache que comenta Sergio, es util, pero hay que ver si el dato es muy cambiante, digo si los los datos del usuario no cambian mucho se podria aplicar cache sin problemas

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    • Propuesto como respuesta Pablo RubioModerator lunes, 26 de noviembre de 2018 17:27
    • Marcado como respuesta AdyIr martes, 27 de noviembre de 2018 14:03
    sábado, 24 de noviembre de 2018 11:44
  • hola

    Me perdi en el codigo que DAL es usada desde que Api, pero entiendo que la ultima UserDAL esta en Api.Posts, si es asi es correcto

    ojo que la UserBL deberia estar expuesta desde la Api.Users, porque entiendo que la BL por si sola es una dll que no genera una url

    Un tema mas, recuerda usar IoC con librerias como ser Unity,Ninject, etc para poder crear una UserDALMock en Api.post y asi cuando tengas que definir test poder mockear esta clase y no tener que llamar al servicio real de usuario, tambien es bueno tener un mock para poder probar local si tener todos los servicio ejecutando

    >>Pero mi pregunta es si a nivel de performance no perjudica mucho el rendimiento,

    No deberia si estas en una misma red o si los servicios estan hosteados en la misma pc, si podrias tener problemas de performance si cada api esta en equipos separados y se comunica por la red, un ancho de banda lento puede traer problemas ,pero bueno esto ya seria un sistema distribuido

    pero si esta todo local deberia ser instantaneo

    la idea de usar esta tecnica no es traerte miles de registros, la idea es traer lo que necesites asignando filtros, a ver si tienes registrados mil usuario no te traigas los mil siempre, ve de recuperar los que necesitas

    la tecnica de cache que comenta Sergio, es util, pero hay que ver si el dato es muy cambiante, digo si los los datos del usuario no cambian mucho se podria aplicar cache sin problemas

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    Hola Leandro, gracias por tu ayuda.

    Aún no me quedo del todo claro esta parte pero es porque no he manejado mucho Unit tests, voy a ver si leo algo al respecto:

    "Un tema mas, recuerda usar IoC con librerias como ser Unity,Ninject, etc para poder crear una UserDALMock en Api.post y asi cuando tengas que definir test poder mockear "

    Saludos

    martes, 27 de noviembre de 2018 14:03