Sessões

Nesta página, descrevemos o conceito avançado de sessões no Spanner, incluindo práticas recomendadas para sessões de criação de uma biblioteca de cliente, usando as APIs REST ou RPC ou as bibliotecas de cliente do Google.

Visão geral das sessões

Uma sessão representa um canal de comunicação com o banco de dados do Spanner serviço. Uma sessão é usada para executar transações que leem, gravam ou modificam em um banco de dados do Spanner. Cada sessão aplica-se a um único banco de dados.

As sessões podem executar uma ou várias transações de uma só vez. Quando realizar várias transações, a sessão é chamada de sessão multiplexada.

Leituras, gravações e consultas independentes usam uma transação internamente.

Benefícios de desempenho de um pool de sessões

Criar uma sessão é algo caro. Para evitar o custo de desempenho sempre que operação do banco de dados for feita, os clientes deverão manter um pool de sessões, que é um pool de sessões disponíveis que estão prontas para uso. O pool deve armazenar as sessões atuais e retornar o tipo apropriado de sessão quando solicitado, além de lidar com a limpeza de sessões não utilizadas. Para um exemplo de como implementar um pool de sessões, consulte o código-fonte de uma das bibliotecas de cliente do Spanner, como Biblioteca cliente Go ou biblioteca cliente Java.

As sessões devem ser de longa duração, portanto, depois de uma sessão ser usada para um operação do banco de dados, o cliente deve retornar a sessão ao pool para reutilização.

Visão geral dos canais gRPC

Os canais gRPC são usados pelo cliente do Spanner para comunicação. Um gRPC equivale a uma conexão TCP. Um canal gRPC pode processar até 100 solicitações simultâneas. Isso significa que um aplicativo precisará de pelo menos tantos canais gRPC quanto o número de solicitações simultâneas que o aplicativo vai para execução, dividido por 100.

O cliente Spanner cria um pool de canais gRPC quando você para criá-la.

Práticas recomendadas ao usar bibliotecas de cliente do Google

A seguir estão descritas as práticas recomendadas ao usar o cliente do Google bibliotecas para o Spanner.

Configurar o número de sessões e canais gRPC nos pools

As bibliotecas de cliente têm um número padrão de sessões no grupo de sessões e um número padrão de canais gRPC no pool de canais. Os dois padrões são adequados na maioria dos casos. A seguir estão as sessões mínima e máxima padrão e o número padrão de canais gRPC para cada linguagem de programação.

C++

MinSessions: 100
MaxSessions: 400
NumChannels: 4

C#

MinSessions: 100
MaxSessions: 400
NumChannels: 4

Go

MinSessions: 100
MaxSessions: 400
NumChannels: 4

Java

MinSessions: 100
MaxSessions: 400
NumChannels: 4

Node.js

O cliente Node.js não é compatível com vários canais gRPC. Portanto, recomendado criar vários clientes em vez de aumentar o tamanho do de mais de 100 sessões para um único cliente.

MinSessions: 25
MaxSessions: 100

PHP

O cliente PHP não aceita um número configurável de canais gRPC.

MinSessions: 1
MaxSessions: 500

Python

O Python é compatível com quatro tipos diferentes de pools de sessões. que você pode usar para gerenciar sessões.

Ruby

O cliente Ruby não é compatível com vários canais gRPC. Portanto, recomendado criar vários clientes em vez de aumentar o tamanho do de mais de 100 sessões para um único cliente.

MinSessions: 10
MaxSessions: 100

O número de sessões usadas pelo aplicativo é igual ao número de transações simultâneas executadas pelo aplicativo. Você deve modificar as configurações padrão do pool de sessões somente se você espera que uma única instância do aplicativo execute mais transações simultâneas do que o pool de sessões padrão pode processar.

Para aplicativos de alta simultaneidade, recomendamos o seguinte:

  1. Defina MinSessions como o número esperado de transações simultâneas que um único cliente será executado.
  2. Defina MaxSessions como o número máximo de transações simultâneas que um único cliente pode ser executado.
  3. Defina MinSessions=MaxSessions se a simultaneidade esperada não mudar. muito durante o ciclo de vida do aplicativo. Isso evita que o pool de sessões aumentando ou diminuindo a escala. Aumentar ou diminuir o pool de sessões também consome parte do Google Cloud.
  4. Defina NumChannels como MaxSessions / 100. Um canal gRPC pode lidar com até 100 solicitações simultaneamente. Aumente esse valor se você observar uma cauda alta (latência p95/p99), porque isso pode indicar que o gRPC congestionamento de canal.

Aumentar o número de sessões ativas usa recursos adicionais na serviço de banco de dados do Spanner e na biblioteca de cliente. Aumentar o o número de sessões além da necessidade real do aplicativo pode prejudicar o desempenho do seu sistema.

Aumentar o pool de sessões versus aumentar o número de clientes

O tamanho do pool de sessões de um aplicativo determina quantas sessões que uma única instância de aplicativo pode executar. Aumentar a sessão tamanho do pool além da simultaneidade máxima que uma única instância de aplicativo não é recomendado. Se o aplicativo receber um burst de solicitações ultrapassar o número de sessões no pool, as solicitações serão colocadas na fila enquanto aguarda a disponibilização de uma sessão.

Os recursos consumidos pela biblioteca de cliente são os seguintes:

  1. Cada canal gRPC usa uma conexão TCP.
  2. Cada invocação gRPC requer uma linha de execução. O número máximo de que é usado pela biblioteca de cliente é igual ao número máximo de consultas simultâneas executadas pelo aplicativo. Essas conversas ficam no topo de todas as linhas de execução que o aplicativo usa para a própria lógica de negócios.

Aumentar o tamanho do pool de sessões além do número máximo de linhas de execução que uma única instância de aplicativo possa processar. Em vez disso, aumentar o número de instâncias do aplicativo.

Gerenciar a fração de sessões de gravação

Para algumas bibliotecas de cliente, o Spanner reserva uma parte das sessões para transações de leitura/gravação, chamadas de fração de sessões de gravação. Se o seu app usar todas as sessões de leitura, o Spanner vai usar mesmo em transações somente leitura. As sessões de leitura e gravação exigem spanner.databases.beginOrRollbackReadWriteTransaction. Se o usuário estiver no spanner.databaseReader, a chamada falhará e o Spanner retorna esta mensagem de erro:

generic::permission_denied: Resource %resource% is missing IAM permission:
spanner.databases.beginOrRollbackReadWriteTransaction

É possível definir a fração de sessões de gravação para as bibliotecas de cliente que mantêm uma fração de sessões de gravação.

C++

Todas as sessões em C ++ são iguais. Não há sessões somente de leitura ou sessões de leitura e gravação.

C#

A fração padrão de sessões de gravação para C# é 0,2. É possível alterar usando o campo WriteSessionsFraction da SessionPoolOptions.

Go

Todas as sessões Go são iguais. Não há sessões somente de leitura ou sessões de leitura e gravação.

Java

Todas as sessões do Java são iguais. Não há sessões somente de leitura ou sessões de leitura e gravação.

Node.js

Todas as sessões do Node.js são iguais. Não há sessões somente de leitura ou sessões de leitura e gravação.

PHP

Todas as sessões do PHP são as mesmas. Não há sessões somente de leitura ou sessões de leitura e gravação.

Python

O Python é compatível com quatro tipos diferentes de tipos de pool de sessões, que podem ser usados para gerenciar sessões de leitura e sessões de leitura e gravação.

Ruby

A fração padrão de sessões de gravação para Ruby é 0.3. Para alterar a fração, use o método de inicialização do cliente.

Práticas recomendadas ao criar uma biblioteca de cliente ou usar REST/RPC

A seguir, descrevemos as práticas recomendadas para implementar sessões em um cliente para o Spanner ou para usar sessões com a biblioteca REST ou RPC.

Essas práticas recomendadas se aplicam somente se você estiver desenvolvendo uma biblioteca de cliente ou se estiver usando APIs REST/RPC. Se você estiver usando um dos serviços de cliente do Google para o Spanner, consulte Práticas recomendadas ao usar bibliotecas de cliente do Google

Criar e dimensionar o pool de sessões

Para determinar um tamanho ideal do pool de sessões para um processo do cliente, defina o limite inferior para o número de transações simultâneas esperadas e defina o máximo vinculado a um número de teste inicial, como 100. Se o limite superior não for adequado, aumente-o. Aumentar o número de sessões ativas usa outros recursos no serviço de banco de dados do Spanner, portanto, não limpar sessões não utilizadas pode prejudicar o desempenho. Para usuários que trabalham com a API RPC, recomendamos não ter mais de 100 sessões por canal gRPC.

Lidar com sessões excluídas

Há três maneiras de excluir uma sessão:

  • Um cliente pode excluir uma sessão.
  • O serviço de banco de dados do Spanner pode excluir uma sessão quando ela é inativo por mais de 1 hora.
  • O serviço de banco de dados do Spanner poderá excluir uma sessão se ela for há mais de 28 dias.

As tentativas de usar uma sessão excluída resultam em NOT_FOUND. Se você encontrar esse erro, criar e usar uma nova sessão, adicioná-la ao pool e remova a sessão excluída do pool.

Manter uma sessão inativa operante

O serviço de banco de dados do Spanner se reserva o direito de eliminar uma sessão. É possível impedir que a sessão seja encerrada, se você precisar mesmo manter uma sessão inativa operante, por exemplo, se for esperado um aumento significativo de curto prazo no uso do banco de dados. Realizar uma operação de baixo custo, como executar a consulta SQL SELECT 1 para manter a sessão ativa. Se você tiver um ociosa que não é necessária para uso a curto prazo, deixe o Spanner eliminar sessão e criar uma nova sessão na próxima vez que for necessária uma sessão.

Um cenário para manter as sessões ativas é lidar com a demanda de pico regular no banco de dados. Se ocorre um uso intenso do banco de dados diariamente das 9h às 18h, mantenha algumas sessões inativas disponíveis durante esse período, uma vez que elas provavelmente serão necessárias para o uso no horário de pico. Depois das 18h, deixe o Spanner cair em sessões inativas. Todos os dias, antes das 9h, crie algumas sessões novas para que elas estejam prontas para a demanda esperada.

Outro cenário é se você tem um aplicativo que usa o Spanner, mas precisa evitar a sobrecarga de conexão nesse momento. Mantenha um conjunto de sessões ativas para evitar que a sobrecarga de conexão aconteça.

Ocultar detalhes da sessão do usuário da biblioteca de cliente

Se você estiver criando uma biblioteca de cliente, não exponha sessões ao cliente. do consumidor de biblioteca. Permita que o cliente faça chamadas de banco de dados sem a complexidade de criar e manter sessões. Para um exemplo de biblioteca de cliente que oculte os detalhes da sessão do consumidor da biblioteca de cliente, consulte a biblioteca de cliente do Spanner para Java.

Lidar com erros de transações de gravação que não sejam idempotentes

As transações de gravação sem proteção de repetição podem aplicar mutações mais de uma vez. Se uma mutação não é idempotente, uma mutação que é aplicada mais de uma vez pode resultar em uma falha. Por exemplo, uma inserção pode apresentar falha com ALREADY_EXISTS mesmo que a linha não exista antes da tentativa de gravação. Isso pode ocorrer se o servidor de back-end confirmou a mutação, mas não conseguiu comunicar o sucesso ao cliente. Nesse caso, a mutação poderia ser tentada novamente, resultando na falha ALREADY_EXISTS.

Estas são as formas possíveis de abordar esse cenário quando você implementa sua própria biblioteca de cliente ou usa a API REST:

  • Estruturar suas gravações para que sejam idempotentes.
  • Usar gravações com proteção contra repetição.
  • Implementar um método que execute a lógica "upsert": inserir se for novo ou atualizar se existir.
  • Lidar com o erro em nome do cliente.

Manter conexões estáveis

Para melhor desempenho, a conexão utilizada para hospedar uma sessão deve permanecer estável. Quando a conexão que hospeda uma sessão muda, o Spanner pode abortar a transação ativa na sessão e causar uma pequena quantidade de carga extra no banco de dados enquanto atualiza os metadados da sessão. Não há problema se algumas conexões mudarem esporadicamente, mas devem ser evitadas situações em que um grande número de conexões mudam ao mesmo tempo. Se você usa um proxy entre o cliente e o Spanner, é importante manter a estabilidade da conexão para cada sessão.

Monitorar sessões ativas

É possível usar o comando ListSessions para monitorar sessões ativas no seu banco de dados na linha de comando, com a API REST ou a API RPC. ListSessions mostra as sessões ativas em um determinado banco de dados. Isso é útil se você precisa encontrar a causa de um vazamento de sessão. (Um vazamento de sessão é um incidente em que as sessões estão sendo criados, mas não retornados a um pool de sessões para reutilização.

ListSessions permite que você veja metadados sobre suas sessões ativas, incluindo quando uma sessão foi criada e quando ela foi usada pela última vez. Analisar esses dados vai lhe mostrar a direção certa na hora de solucionar problemas. Se a maioria sessões ativas não têm uma approximate_last_use_time recente, isso pode indicam que as sessões não estão sendo reutilizadas corretamente pelo aplicativo. Consulte a Referência da API RPC para mais informações sobre o campo approximate_last_use_time.

Consulte a referência da API REST, a referência da API RPC ou os comandos gcloud referência da ferramenta de linha de comando para mais informações sobre como usar ListSessions.

Limpeza automática de vazamentos de sessão.

Quando você usa todas as sessões no seu pool de sessões, cada nova transação aguarda até que uma sessão seja retornada ao pool. Quando as sessões são criadas mas não retornar ao pool da sessão para reutilização, isso é chamado de vazamento de sessão. Quando há um vazamento de sessão, as transações que aguardam uma sessão aberta ficam presas indefinidamente e bloquear o aplicativo. Os vazamentos de sessões geralmente são causados por transações problemáticas executadas há muito tempo e não estão comprometidos.

Você pode configurar seu pool de sessões para resolver esses problemas automaticamente para transações inativas. Quando você ativa a biblioteca de cliente para resolver uma transição inativa, identifica transações problemáticas possa causar um vazamento de sessão, removê-la do pool de sessões e os substitui por uma nova sessão.

A geração de registros também pode ajudar a identificar essas transações problemáticas. Se o registro estiver ativado, os registros de aviso serão compartilhados por padrão quando mais de 95% do seu pool de sessões está em uso. Se o uso da sessão for maior que 95%, você precisa aumentar o número máximo de sessões permitidas no seu grupo de sessões, ou pode ter vazamento de sessão. Os registros de aviso contêm pilhas de transações que são executadas por mais tempo do que o esperado e podem ajudam a identificar a causa da alta utilização do pool de sessões. Os registros de aviso são enviados dependendo da configuração do exportador de registros.

Ative a biblioteca de cliente para resolver automaticamente transações inativas

É possível ativar a biblioteca de cliente para enviar registros de avisos e automaticamente resolver transações inativas ou ativar a biblioteca de cliente para receber somente avisos ou de sistemas operacionais de contêineres.

Java

Para receber registros de aviso e remover transações inativas, use setWarnAndCloseIfInactiveTransactions.

 final SessionPoolOptions sessionPoolOptions = SessionPoolOptions.newBuilder().setWarnAndCloseIfInactiveTransactions().build()

 final Spanner spanner =
         SpannerOptions.newBuilder()
             .setSessionPoolOption(sessionPoolOptions)
             .build()
             .getService();
 final DatabaseClient client = spanner.getDatabaseClient(databaseId);

Para receber apenas registros de aviso, use setWarnIfInactiveTransactions:

 final SessionPoolOptions sessionPoolOptions = SessionPoolOptions.newBuilder().setWarnIfInactiveTransactions().build()

 final Spanner spanner =
         SpannerOptions.newBuilder()
             .setSessionPoolOption(sessionPoolOptions)
             .build()
             .getService();
 final DatabaseClient client = spanner.getDatabaseClient(databaseId);

Go

Para receber registros de aviso e remover transações inativas, use SessionPoolConfig com InactiveTransactionRemovalOptions.

 client, err := spanner.NewClientWithConfig(
     ctx, database, spanner.ClientConfig{SessionPoolConfig: spanner.SessionPoolConfig{
         InactiveTransactionRemovalOptions: spanner.InactiveTransactionRemovalOptions{
         ActionOnInactiveTransaction: spanner.WarnAndClose,
         }
     }},
 )
 if err != nil {
     return err
 }
 defer client.Close()

Para receber apenas registros de aviso, use customLogger.

 customLogger := log.New(os.Stdout, "spanner-client: ", log.Lshortfile)
 // Create a logger instance using the golang log package
 cfg := spanner.ClientConfig{
         Logger: customLogger,
     }
 client, err := spanner.NewClientWithConfig(ctx, db, cfg)

Sessões multiplexadas

As sessões multiplexadas permitem criar um número ilimitado de solicitações simultâneas ao mesmo tempo. As sessões multiplexadas têm as seguintes vantagens:

  • Requisitos reduzidos de recursos de back-end. Por exemplo, eles evitam as atividades de manutenção associadas à manutenção da propriedade da sessão e coleta de lixo.
  • Sessão de longa duração que não requer solicitações de sinal de atividade quando está inativa.
  • Bibliotecas de cliente típicas podem usar uma sessão multiplexada para cada cliente. O o número de sessões regulares em uso é menor para clientes que usam para algumas operações em comparação com clientes que usam apenas de conteúdo.
  • Não é necessário ter afinidade com apenas um canal gRPC. Os clientes podem enviar solicitações em vários canais para a mesma sessão multiplexada.

As sessões multiplexadas são compatíveis com:

  • A biblioteca-cliente Java
  • As ferramentas do ecossistema do Spanner que dependem da biblioteca de cliente do Java, como PGAdapter, JDBC e Hibernate,
  • APIs Spanner para transações somente leitura

Use as métricas do OpenTelemetry para ver como o tráfego é dividido. entre o pool de sessões existente e a sessão multiplexada. O OpenTelemetry tem Um filtro de métrica, is_multiplexed, que mostra sessões multiplexadas quando definido como true.

As sessões multiplexadas são ativadas por padrão para o adaptador JDBC e PG. Para Java bibliotecas de cliente, ele fica desativado por padrão. Você usa o Biblioteca de cliente Java para ativar sessões multiplexadas. Para ativar uma sessão multiplexada usando Java, consulte Ativar sessões multiplexadas.

Ativar sessões multiplexadas

Para ativar sessões multiplexadas usando o cliente Java, defina GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS para true.

export GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS=TRUE

Ver o tráfego de sessões regulares e multiplexadas

O Opentelemetry tem o filtro is_multiplexed para mostrar o tráfego de sessões multiplexadas. Defina esse filtro como true to view multiplexed sessions andfalse` para ver as sessões normais.

  1. Configure o Opentelemetry para o Spanner usando os procedimentos no Opentelemetry do Spanner Antes de começar nesta seção.
  2. Acesse o Metrics Explorer.

    Acessar o Metrics Explorer

  3. No menu suspenso Métrica, filtre por generic.

  4. Clique em Tarefa genérica e acesse Spanner > Spanner/num_acquired_sessions.

  5. No campo Filtro, selecione uma das seguintes opções:

    a. is_multiplexed = false para acessar as sessões normais. b. is_multiplexed = true para ver sessões multiplexadas.

    A imagem a seguir mostra a opção Filtrar com sessões multiplexadas selecionados.

Para mais informações sobre como usar o OpenTelemetry com o Spanner, consulte Uso do OpenTelemetry para democratizar a observabilidade do Spanner e Analisar a latência em um componente do Spanner com o OpenTelemetry.

Painel do Opentelemetry mostrando o filtro é multiplexado.