Portal do Cidadão - Estudo de Ferramentas para Melhoria de Performance
OBJETIVO
Mapear soluções para melhoria de performance no projeto Portal do Cidadão conforme a User Story: “Eu como vingadores, preciso realizar um estudo de caso para melhoria de perfomance no Portal do Cidadão" presente na Sprint número 100 do time Vingadores.
JUSTIFICATIVA
Tendo em vista que o Portal do Cidadão terá um alto volume de acessos, os usuários poderão experimentar lentidões ou instabilidades durante o seu uso. Desta forma faz-se necessário a elaboração deste estudo para mapear possíveis soluções e ferramentas para a garantia da disponibilidade do sistema.
RESULTADOS ESPERADOS
Levantar ferramentas, técnicas ou soluções disponíveis que possam impactar significativamente na melhoria de performance do sistema parcialmente ou como um todo.
ENVOLVIDOS:
Gustavo Felix Gomes (Dev team)
Rafael Passos dos Santos (Dev team)
Emanuel Rufino Alcantara de Lima (Dev team)
Lucas de Souza e Sousa (Dev team)
André Honório de Andrade Silva (Dev team)
Alef Carvalho (Dev team)
Euriane Nogueira Frota (Product Owner)
1 - INTRODUÇÃO
É comum termos diversos dados das nossas aplicações que não mudam com frequência. Tudo que tem baixa mutabilidade, pode ser cacheado, evitando que a requisição precise chegar até a fonte de dados, sobrecarregando-a sem necessidade.
A técnica de cache normalmente é implementada entra a aplicação e a sua fonte de dados. Quando uma requisição ocorre, podemos cachear seus resultados em algum local e posteriormente, toda vez que esta mesma requisição for chamada, lemos estes dados ao invés de consultar o banco de dados.
O cache pode ser salvo em diversos lugares, incluindo memória e disco. Todos os dados possuem um tempo de expiração que quando atingido força a renovação do mesmo. Essa renovação significa que a próxima requisição irá novamente até o banco de dados e o processo de caching será feito novamente.
2 - CENÁRIO ATUAL
No Portal do Cidadão, não há nenhum tipo de caching de dados ou estratégia semelhante em execução. Devido ao alto volume de acessos previsto após o lançamento da plataforma faz-se necessário a implementação de uma ou mais técnicas deste tipo afim de garantir a performance da aplicação em produção.
3 - REDIS
Redis é um banco de dados estruturados em memória, open source, que pode ser utilizado como database, cache e/ou mensageria porém o seu uso mais comum é como sistema de cache.
Para que seja utilizado é necessário que o Redis esteja instalado na máquina atual ou em algum servidor remoto. Existem versões para os principais sistemas operacionais do mercado, além da opção de rodar o servidor via Docker.
3.1 - REDIS - IMPLEMENTAÇÃO:
Adicionar o pacote Nuget:
dotnet add package Microsoft.Extensions.Caching.StackExchangeRedis
Em seguida registrá-lo no método ConfigureServices
da classe Startup
:
public void ConfigureServices(IServiceCollection services)
{
//...
services.AddStackExchangeRedisCache(options =>
{
options.Configuration = "localhost:6379";
});
}
Consumir cache:
[Route("api/[controller]")]
[ApiController]
public class CidadaoController : ControllerBase
{
private readonly ICidadaoRepository<Cidadao> cidadaoRepository;
private readonly IDistributedCache _cache;
private ILogger<EmployeeController> logger;
public CidadaoController(
ICidadaoRepository<Cidadao> cidadaoRepository,
IDistributedCache cache,
ILogger<EmployeeController> logger
)
{
this.cidadaoRepository = cidadaoRepository;
this.cache = cache;
this.logger = logger;
}
[HttpGet]
public async Task<IActionResult> Index()
{
var cacheKey = "listaCidadoes";
var cidadoes = new List<Cidadao>();
var json = await cache.GetStringAsync(cacheKey);
if(json != null)
{
products = JsonSerializer.Deserialize<List<Cidadao>>(json);
}
else
{
_logger.Log(LogLevel.Information, "Nenhum cidadão encontrado no cache Redis. Buscando do banco de dados...");
cidadoes = cidadaoRepository.GetAll();
_logger.Log(LogLevel.Information, "Salvando cidadões no cache Redis...");
json = JsonSerializer.Serialize<List<Cidadao>>(cidadoes);
await _cache.SetStringAsync(cacheKey, json);
}
return Ok(cidadoes);
}
}
4 - ASP.NET IN-MEMORY CACHE
O cache em memória em ASP.NET Core uma forma simples e nativa de cache em que o aplicativo armazena dados na memória do servidor web. Isso é baseado na interface que representa um objeto de cache armazenado na memória do aplicativo.
4.1 ASP.NET IN-MEMORY CACHE - IMPLEMENTAÇÃO:
Registrar o Middleware de caching nativo no método ConfigureServices
da classe Startup
:
public void ConfigureServices(IServiceCollection services)
{
services.AddMemoryCache();
}
Consumir o cache na aplicaçao:
[Route("api/[controller]")]
[ApiController]
public class CidadaoController : ControllerBase
{
private const string cacheKey = "listaCidadoes";
private readonly ICidadaoRepository<Cidadao> cidadaoRepository;
private IMemoryCache cache;
private ILogger<EmployeeController> logger;
public CidadaoController(
ICidadaoRepository<Cidadao> cidadaoRepository,
IMemoryCache cache,
ILogger<EmployeeController> logger
)
{
this.cidadaoRepository = cidadaoRepository;
this.cache = cache;
this.logger = logger;
}
[HttpGet]
public async Task<IActionResult> Index()
{
if (_cache.TryGetValue(cacheKey, out IEnumerable<Cidadadao> cidadoes))
{
_logger.Log(LogLevel.Information, "Nenhum cidadão encontrado no cache.");
}
else
{
_logger.Log(LogLevel.Information, "Nenhum cidadão encontrado em cache. Buscando do banco de dados...");
cidadoes = cidadaoRepository.GetAll();
_logger.Log(LogLevel.Information, "Salvando cidadões no cache...");
var cacheEntryOptions = new MemoryCacheEntryOptions()
.SetSlidingExpiration(TimeSpan.FromSeconds(60))
.SetAbsoluteExpiration(TimeSpan.FromSeconds(3600))
.SetPriority(CacheItemPriority.Normal)
.SetSize(1024);
_cache.Set(cacheKey, cidadoes, cacheEntryOptions);
}
return Ok(cidadoes);
}
}
Esta técnica de cache tem dois pontos importantes à serem levados em conta antes de uma possível implementação, a memória e a escalabilidade.
Como estamos colocando os dados de cache na memória do servidor web, quanto mais dados forem inclusos em cache, mais memória será consumida pela aplicação em execução. O ASP.NET fica responsável por gerenciar a memória e desaloca-la caso necessário.
5 - POSSÍVEIS PROBLEMAS NA UTILIZAÇÃO
Como a aplicação do Portal do Cidadão é executado em ambiente Kubernetes (Openshift) faz-se necessário a observação de alguns pontos:
- Ao utilizar o cache nativo do ASP.NET a configuração padrão de escalonamento do Kubernetes faz com que quando a aplicação chegue à X% de CPU ou memória, um novo contâiner (pod) seja provisionad. Este novo contâiner possui apenas a aplicação em sí, a memória do container anterior não é replicada.
- Ao utilizar o cache via Redis agregamos mais um serviço no ecossistema da aplicação, trazendo com isso mais complexidade e custo a nossa infraestrutura.
6 - HISTÓRIAS DE USUÁRIO
HISTÓRIA |
PONTUAÇÃO |
PRODUTO |
Implementar caching de dados via REDIS para as informações da carta e seus serviços. |
13 |
Portal do Cidadão |
Implementar caching de dados via REDIS para as informações de média de avaliações de um serviço. | 8 | Portal do Cidadão |
Implementar caching de dados via REDIS para as informações de locais e horários de atendimento de um serviço. | 8 | Portal do Cidadão |
Implementar caching de dados via REDIS para as informações de serviços mais acessados na homepage do Portal. | 8 | Portal do Cidadão |
Implementar caching de dados via REDIS para as categorias de serviços exibidas na homepage do Portal. | 8 | Portal do Cidadão |
Implementar caching de dados via REDIS para a lista de horários de atendimento do serviço dentro da visualização dos detalhes da solicitação. | 8 | Portal do Cidadão |
Implementar caching de dados via REDIS para a lista das unidades de atendimento dentro do serviço. | 8 | Portal do Cidadão |
Implementar caching de dados via REDIS para a lista de solicitações e agendamentos realizados pelo cidadão. | 8 | Portal do Cidadão |
TOTAL |
69 |
|
7 - CONCLUSÃO
Dado que, uma alteração no fluxo das solicitações se faz necessária, é de suma importância que seja devidamente mapeada na aplicação os dados com baixa imutabilidade afim de que seja implementado uma das estratégias de caching citadas anteriormente.
Considerado o alto volume de trafego do Portal do Cidadão o impacto da aplicação de caching em funcionalidades específicas agrega valor ao produto final, impactando significativamente a experiência do usuário no uso da aplicação.
8 - REFERÊNCIAS:
ASP.NET Memory Cache | balta.io
Implementando cache distribuído no ASP.NET Core | Blog TreinaWeb
Configurando e usando memcached em ASP.NET núcleo - Referbruv