Mais 4 Recomendações Práticas para Projetos de Microsserviços em .NET

Neste post, compartilho mais algumas ideias que tenho adotado, com êxito, em meus projetos envolvendo Microsserviços e que podem ajudar você a ser mais efetivo em suas implementações.

Se você ainda não leu, recomendo que acesse um post anterior sobre esse tema, com mais recomendações, antes de avançar.

1. Comece pelos comandos e pelas consultas que vai suportar

Antes de definir qualquer aspecto mais técnico, ter clareza sobre quais comandos e consultas seu microsserviço deverá suportar irá ajudar você a ser mais efetivo e mais alinhado com as necessidades do negócio.


No exemplo, apenas ilustrativo, o microsserviço irá manter um “contador”.

Tenho optado (não faz muito tempo) por usar o Mediatr para intermediar a chamada dos handlers, orquestrar validação das mensagegens, etc.

using System.Threading;
using System.Threading.Tasks;
using CountingMicroservice.Application.Services;
using MediatR;

namespace CountingMicroservice.Application.CommandSide.Commands
{
    public class IncrementCommandHandler
        : IRequestHandler<IncrementCommand, bool>
    {
        private readonly ICounterRepository _repository;

        public IncrementCommandHandler(ICounterRepository repository)
        {
            _repository = repository;
        }

        public Task Handle(
            IncrementCommand request, 
            CancellationToken cancellationToken
            )
        {
            if (request == null)
            {
                return Task.FromResult(false);
            }

            _repository.Increment();
                
            return Task.FromResult(true);
        }
    }
}

2. Mantenha sua WebApi simples (se essa for sua interface)

Manter um projeto específico para a aplicação permite que o projeto da Web API seja extremamente simplificado. Caberá a WebAPI, apenas, fazer as devidas inicializações e prover features que “chamam” os comandos e consultas no momento apropriado.

Aliás, para aliviar acoplamento, tenho adotado por hábito fazer inicializações específicas da aplicação no código da aplicação (fora da web api)

using CountingMicroservice.Application.Services;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using ServiceStack.Redis;

namespace CountingMicroservice.Application
{
    public static class StartupExtensions
    {
        public static IServiceCollection AddCounterApplication(
            this IServiceCollection services, 
            IConfiguration configuration
            )
        {
            var redisConnectionString = configuration["REDIS_CONNECTIONSTRING"] ?? "-counter.data";
            services
                .AddSingleton(sp => 
                    new RedisManagerPool(redisConnectionString)
                    )
                .AddSingleton<ICounterRepository, RedisCounterRepository>();

            return services;
        }

        public static IApplicationBuilder UseCounterApplication(
            this IApplicationBuilder app
        )
        {
            return app;
        }
    }
}

Fica dentro da WebAPI apenas inicializações que são específicas dela (Swagger, por exemplo)

using System;
using Autofac;
using Autofac.Extensions.DependencyInjection;
using CountingMicroservice.Application;
using CountingMicroservice.Application.CommandSide.Commands;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Swashbuckle.AspNetCore.Swagger;

namespace CountingMicroservice.WebApi
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        public IServiceProvider ConfigureServices(IServiceCollection services)
        {
            services.AddMvc(options =>
            {
                options.RespectBrowserAcceptHeader = true;
            });

            services.AddSwaggerGen(options =>
            {
                options.SwaggerDoc("v1", new Info()
                {
                    Title = "Counting Microservice",
                    Version = "v1",
                    Description = "Basic Microservice Example"
                });
            });

            services.AddCounterApplication(Configuration);

            var container = new ContainerBuilder();
            container.RegisterModule(
                MediatrModule.Create(typeof(StartupExtensions).Assembly)
                );
            container.Populate(services);
            return new AutofacServiceProvider(container.Build());
        }

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseMvcWithDefaultRoute();

            app
                .UseSwagger()
                .UseSwaggerUI(options =>
                {
                    options.SwaggerEndpoint(
                        "/swagger/v1/swagger.json",
                        "Counting Microservice v1"
                        );
                });

            app.UseCounterApplication();
        }
    }
}

3. Use e abuse do Docker

Provavelmente seu microsserviço irá rodar em um container;. Aproveite-se do suporte do Visual Studio para Docker e já comece seu projeto rodando e depurando em containers.

O efeito positivo dessa escolha é que ficará muito mais fácil gerenciar dependências de softwares tecerceiros. Veja o docker-compose.yml da aplicação exemplo

version: '3'

services:
  countingmicroservice.webapi:
    image: countingmicroservice.webapi
    build:
      context: .
      dockerfile: CountingMicroservice.WebApi/Dockerfile
    depends_on:
      - redis

  redis:
    image: redis

No exemplo, não preciso mais me preocupar em ter um servidor redis rodando em meu Windows. Ao começar a rodar minha aplicação, uma imagem do Redis irá ser baixada e um container iniciado.

4. Use variáveis de ambiente para configuração

É muito mais fácil configurar sua aplicação usando variáveis de ambiente do que utilizando arquivos de configuração. No Asp.net Core, é simples fazer isso.

namespace CountingMicroservice.WebApi
{
    public class Program
    {
        public static void Main(string[] args)
        {
            BuildWebHost(args).Run();
        }

        public static IWebHost BuildWebHost(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseStartup()
                .ConfigureAppConfiguration((builderContext, config) =>
                {
                    config.AddEnvironmentVariables();
                })
                .Build();
    }
}

Além disso, variáveis de ambiente são perfeitas combinadas ao Docker. No exemplo, configuro endereço do Redis no arquivo de composição. Isso simplificará muito o deploy mais tarde.

version: '3'

services:
  countingmicroservice.webapi:
    environment:
      - ASPNETCORE_ENVIRONMENT=Development
      - REDIS_CONNECTIONSTRING=redis
    ports:
      - "5000:80"

  redis:
    ports:
      - "6379:6379"

Concluindo

Novamente, “são as cicatrizes que contam a história do guerreiro”.

  • Sempre achei tedioso fazer o link entre meus Controllers e o código do domínio. Mediatr é uma “mão na roda” e a separação do microsserviço em projetos “adaptadores” e um “core” me ajuda a manter focado no negócio.
  • A ideia de implementar comandos e consultas me faz manter o foco nas histórias de negócio ao invés de dados colecionados.
  • Sempre achei péssimo instalar bancos de dados e outros artefatos em meu computador apenas para desenvolver – Docker é vida!
  • Sempre odiei o web.config! Felizmente, não preciso mais dele. Adoro a ideia de poder usar simples variáveis de ambiente para configurar minha aplicação.

Novamente, há bem mais que poderia ser compartilhado. Entretanto, mais uma vez, é hora de pedir a sua opinião.

 

Compartilhe este insight:

Elemar Júnior

Sou fundador e CEO da EximiaCo e atuo como tech trusted advisor ajudando diversas empresas a gerar mais resultados através da tecnologia.

Elemar Júnior

Sou fundador e CEO da EximiaCo e atuo como tech trusted advisor ajudando diversas empresas a gerar mais resultados através da tecnologia.

Mais insights para o seu negócio

Veja mais alguns estudos e reflexões que podem gerar alguns insights para o seu negócio:

Um dos princípios que mais valorizo em práticas ágeis é o feedback. De todos os tipos de feedback que já...
Você ainda acredita em estimativas? Nós, não. Embora aceitemos que ter uma boa ideia de esforço e prazo sejam diferenciais...
In the previous post, I asked which function, in the following code, would fill the array with 1’s faster and...
Poucas empresas foram tão impactadas por inovações disruptivas quanto a Encyclopaedia Britannica – empresa com mais de 250 anos. Entretanto,...
Nesse ano, palestrei na APIX sobre microsserviços. Abaixo, registro em vídeo feito pela organização do evento. Comentários? Feedback?
No último post desta série, tratamos da “Lei do Retorno Acelerado”. Sabemos que negócios digitais tem crescimento potencialmente exponencial. Neste...

Crie sua conta

Preencha os dados para iniciar o seu cadastro no plano anual do Clube de Estudos:

Crie sua conta

Preencha os dados para iniciar o seu cadastro no plano mensal do Clube de Estudos:

Mentoria em
Arquitetura de Software
com ênfase em IA

Aprenda a coordenar equipes de desenvolvimento, aplicar padrões e técnicas de arquitetura e aumentar sua produtividade criando sistemas inovadores com o suporte da IA.

× Precisa de ajuda?