Práticas recomendadas para o desempenho dos microsserviços

ID da região

O REGION_ID é um código abreviado que a Google atribui com base na região que seleciona quando cria a sua app. O código não corresponde a um país ou uma província, embora alguns IDs de regiões possam parecer semelhantes aos códigos de países e províncias usados frequentemente. Para apps criadas após fevereiro de 2020, REGION_ID.r está incluído nos URLs do App Engine. Para apps existentes criadas antes desta data, o ID da região é opcional no URL.

Saiba mais acerca dos IDs de regiões.

O desenvolvimento de software envolve compromissos e os microsserviços não são exceção. O que ganha em implementação de código e independência de funcionamento, paga em termos de sobrecarga de desempenho. Esta secção fornece algumas recomendações de passos que pode seguir para minimizar este impacto.

Transforme operações CRUD em microsserviços

Os microsserviços são particularmente adequados para entidades acedidas com o padrão de criação, obtenção, atualização e eliminação (CRUD). Quando trabalha com estas entidades, normalmente, usa apenas uma entidade de cada vez, como um utilizador, e, normalmente, executa apenas uma das ações CRUD de cada vez. Por conseguinte, só precisa de uma única chamada de microsserviço para a operação. Procure entidades que tenham operações CRUD, além de um conjunto de métodos empresariais que possam ser usados em muitas partes da sua aplicação. Estas entidades são boas candidatas a microsserviços.

Fornecer APIs de lote

Além das APIs de estilo CRUD, ainda pode oferecer um bom desempenho dos microsserviços para grupos de entidades através de APIs em lote. Por exemplo, em vez de expor apenas um método GET da API que obtenha um único utilizador, forneça uma API que receba um conjunto de IDs de utilizadores e devolva um dicionário de utilizadores correspondentes:

Pedido:

/user-service/v1/?userId=ABC123&userId=DEF456&userId=GHI789

Resposta:

{
  "ABC123": {
    "userId": "ABC123",
    "firstName": "Jake",
    … },
  "DEF456": {
    "userId": "DEF456",
    "firstName": "Sue",
    … },
  "GHI789": {
    "userId": "GHI789",
    "firstName": "Ted",
    … }
}

O SDK do App Engine suporta muitas APIs de processamento em lote, como a capacidade de obter muitas entidades do Cloud Datastore através de um único RPC, pelo que a prestação de serviços destes tipos de APIs de processamento em lote pode ser muito eficiente.

Use pedidos assíncronos

Muitas vezes, tem de interagir com muitos microsserviços para compor uma resposta. Por exemplo, pode ter de obter as preferências do utilizador com sessão iniciada, bem como os detalhes da respetiva empresa. Frequentemente, estas informações não dependem umas das outras e pode obtê-las em paralelo. A biblioteca Urlfetch no SDK do App Engine suporta pedidos assíncronos, o que lhe permite chamar microsserviços em paralelo.

Usar o trajeto mais curto

Dependendo da forma como invoca Urlfetch, pode fazer com que sejam usadas infraestruturas e rotas diferentes. Para usar o percurso com melhor desempenho, considere as seguintes recomendações:

Use REGION_ID.r.appspot.com e não um domínio personalizado
Um domínio personalizado faz com que seja usada uma rota diferente quando o encaminhamento é feito através da infraestrutura da Google. Uma vez que as chamadas de microsserviços são internas, é fácil de fazer e tem um melhor desempenho se usar https://PROJECT_ID.REGION_ID.r.appspot.com.
Defina follow_redirects como False
Defina explicitamente follow_redirects=False quando chamar Urlfetch, uma vez que evita um serviço de maior peso concebido para seguir redirecionamentos. Os seus pontos finais da API não devem precisar de redirecionar os clientes, porque são os seus próprios microsserviços, e os pontos finais só devem devolver respostas das séries 200, 400 e 500 de HTTP.
Prefira serviços num projeto em vez de vários projetos
Existem bons motivos para usar vários projetos ao criar uma aplicação baseada em microsserviços, mas se o desempenho for o seu objetivo principal, use serviços num único projeto. Os serviços de um projeto estão alojados no mesmo centro de dados e, embora o débito na rede entre centros de dados da Google seja excelente, as chamadas locais são mais rápidas.

Evite conversas durante a aplicação da segurança

É prejudicial para o desempenho usar mecanismos de segurança que envolvem muita comunicação de vaivém para autenticar a API de chamada. Por exemplo, se o seu microserviço precisar de validar um pedido da sua aplicação através de uma chamada de retorno à aplicação, incorreu num número de viagens de ida e volta para obter os seus dados.

Uma implementação do OAuth2 pode amortizar este custo ao longo do tempo através da utilização de tokens de atualização e da colocação em cache de um token de acesso entre invocações de Urlfetch. No entanto, se a chave de acesso em cache estiver armazenada em memcache, tem de incorrer em custos gerais de memcache para a obter. Para evitar esta sobrecarga, pode colocar o token de acesso em cache na memória da instância, mas continua a ter a atividade do OAuth2 com frequência, uma vez que cada nova instância negoceia um token de acesso. Lembre-se de que as instâncias do App Engine são iniciadas e terminadas com frequência. Uma combinação de memcache e cache de instâncias ajuda a mitigar este problema, mas a sua solução começa a tornar-se mais complexa.

Outra abordagem com bom desempenho é partilhar um token secreto entre os microsserviços, por exemplo, transmitido como um cabeçalho HTTP personalizado. Nesta abordagem, cada microsserviço pode ter um token exclusivo para cada autor da chamada. Normalmente, os segredos partilhados são uma escolha questionável para implementações de segurança, mas, uma vez que todos os microsserviços estão na mesma aplicação, torna-se menos problemático, tendo em conta os ganhos de desempenho. Com um segredo partilhado, o microsserviço só precisa de comparar uma string do segredo recebido com um dicionário presumivelmente na memória, e a aplicação da segurança é muito leve.

Se todos os seus microsserviços estiverem no App Engine, também pode inspecionar o cabeçalho X-Appengine-Inbound-Appid incoming. Este cabeçalho é adicionado pela infraestrutura Urlfetch quando faz um pedido a outro projeto do App Engine e não pode ser definido por uma entidade externa. Consoante o seu requisito de segurança, os seus microsserviços podem inspecionar este cabeçalho recebido para aplicar a sua política de segurança.

Rastreie pedidos de microsserviços

À medida que cria a sua aplicação baseada em microsserviços, começa a acumular custos gerais de chamadas Urlfetch sucessivas. Quando isto acontece, pode usar o Cloud Trace para compreender que chamadas estão a ser feitas e onde está a sobrecarga. É importante referir que o Cloud Trace também pode ajudar a identificar onde os microsserviços independentes estão a ser invocados em série, para que possa refatorar o seu código para realizar estas obtenções em paralelo.

Uma funcionalidade útil do Cloud Trace é ativada quando usa vários serviços num único projeto. À medida que as chamadas são feitas entre os serviços de microsserviços no seu projeto, o Cloud Trace reduz todas as chamadas num único gráfico de chamadas para lhe permitir visualizar todo o pedido ponto a ponto como um único rastreio.

Captura de ecrã do Google Cloud Trace

Tenha em atenção que, no exemplo acima, as chamadas para pref-service e user-service são realizadas em paralelo através de um Urlfetch assíncrono. Por isso, os RPCs aparecem desordenados na visualização. No entanto, continua a ser uma ferramenta valiosa para diagnosticar a latência.

O que se segue?