Sessões

Esta página descreve o conceito avançado de sessões no Spanner, incluindo práticas recomendadas para sessões quando cria uma biblioteca cliente, usa as APIs REST ou RPC ou usa as bibliotecas cliente Google.

Uma sessão representa um canal de comunicação com o serviço de base de dados do Spanner. Uma sessão é usada para realizar transações que leem, escrevem ou modificam dados numa base de dados do Spanner. Cada sessão aplica-se a uma única base de dados.

As sessões podem executar uma ou várias transações de cada vez. Quando realiza várias transações, a sessão é denominada sessão multiplexada. As leituras, as escritas e as consultas autónomas usam uma transação internamente.

Vantagens de desempenho de um conjunto de sessões

A criação de uma sessão é dispendiosa. Para evitar o custo de desempenho cada vez que é feita uma operação de base de dados, os clientes devem manter um conjunto de sessões, que é um conjunto de sessões disponíveis prontas a usar. O conjunto deve armazenar as sessões existentes e devolver o tipo de sessão adequado quando solicitado, bem como processar a limpeza das sessões não usadas. Para ver um exemplo de como implementar um conjunto de sessões, consulte o código fonte de uma das bibliotecas cliente do Spanner, como a biblioteca cliente Go ou a biblioteca cliente Java.

As sessões destinam-se a ser de longa duração, pelo que, após a utilização de uma sessão para uma operação de base de dados, o cliente deve devolvê-la ao conjunto para reutilização.

Vista geral dos canais gRPC

Os canais gRPC são usados pelo cliente do Spanner para comunicação. Um canal gRPC é aproximadamente equivalente a uma ligação TCP. Um canal gRPC pode processar até 100 pedidos simultâneos. Isto significa que uma aplicação precisa de, pelo menos, tantos canais gRPC quanto o número de pedidos concorrentes que a aplicação vai executar, dividido por 100.

O cliente do Spanner cria um conjunto de canais gRPC quando o cria.

Práticas recomendadas ao usar bibliotecas de cliente da Google

As seguintes opções descrevem as práticas recomendadas quando usa as bibliotecas de cliente da Google para o Spanner.

Configure o número de sessões e canais gRPC nos conjuntos

As bibliotecas de cliente têm um número predefinido de sessões no conjunto de sessões e um número predefinido de canais gRPC no conjunto de canais. Ambas as predefinições são adequadas para a maioria dos casos. Seguem-se as sessões mínimas e máximas predefinidas, bem como o número predefinido 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 suporta vários canais gRPC. Por isso, recomendamos que crie vários clientes em vez de aumentar o tamanho do conjunto de sessões para além de 100 sessões para um único cliente.

MinSessions: 25
MaxSessions: 100

PHP

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

MinSessions: 1
MaxSessions: 500

Python

O Python suporta quatro tipos de conjunto de sessões diferentes que pode usar para gerir sessões.

Ruby

O cliente Ruby não suporta vários canais gRPC. Por isso, recomendamos que crie vários clientes em vez de aumentar o tamanho do conjunto de sessões para além de 100 sessões para um único cliente.

MinSessions: 10
MaxSessions: 100

O número de sessões que a sua aplicação usa é igual ao número de transações simultâneas que a sua aplicação executa. Só deve modificar as definições do conjunto de sessões predefinido se esperar que uma única instância da aplicação execute mais transações simultâneas do que o conjunto de sessões predefinido consegue processar.

Para aplicações de alta concorrência, recomendamos o seguinte:

  1. Defina MinSessions para o número esperado de transações simultâneas que um único cliente vai executar.
  2. Defina MaxSessions para o número máximo de transações simultâneas que um único cliente pode executar.
  3. Defina MinSessions=MaxSessions se a simultaneidade esperada não mudar muito durante o período de vida da aplicação. Isto impede o dimensionamento para cima ou para baixo do conjunto de sessões. Aumentar ou diminuir a escala do conjunto de sessões também consome alguns recursos.
  4. Defina NumChannels como MaxSessions / 100. Um canal gRPC pode processar até 100 pedidos em simultâneo. Aumente este valor se observar uma latência de cauda elevada (latência p95/p99), uma vez que pode ser um indicador de congestionamento do canal gRPC.

O aumento do número de sessões ativas usa recursos adicionais no serviço de base de dados do Spanner e na biblioteca do cliente. Aumentar o número de sessões além da necessidade real da aplicação pode prejudicar o desempenho do sistema.

Aumentar o conjunto de sessões em vez de aumentar o número de clientes

A dimensão do conjunto de sessões de uma aplicação determina quantas transações simultâneas uma única instância da aplicação pode executar. Não é recomendado aumentar o tamanho do conjunto de sessões além da simultaneidade máxima que uma única instância da aplicação pode processar. Se a aplicação receber uma rajada de pedidos que exceda o número de sessões no conjunto, os pedidos são colocados em fila de espera enquanto aguardam que uma sessão fique disponível.

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

  1. Cada canal gRPC usa uma ligação TCP.
  2. Cada invocação gRPC requer um segmento. O número máximo de linhas de execução usado pela biblioteca cliente é igual ao número máximo de consultas simultâneas que a aplicação executa. Estas linhas de execução são apresentadas acima de quaisquer linhas de execução que a aplicação use para a sua própria lógica empresarial.

Não é recomendado aumentar o tamanho do conjunto de sessões além do número máximo de threads que uma única instância da aplicação pode processar. Em alternativa, aumente o número de instâncias da aplicação.

Faça a gestão da 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/escrita, denominada fração de sessões de escrita. Se a sua app usar todas as sessões de leitura, o Spanner usa as sessões de leitura/escrita, mesmo para transações só de leitura. As sessões de leitura/escrita requerem spanner.databases.beginOrRollbackReadWriteTransaction. Se o utilizador tiver a função de IAM spanner.databaseReader, a chamada falha e o Spanner devolve esta mensagem de erro:

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

Para as bibliotecas de cliente que mantêm uma fração de sessões de escrita, pode definir a fração de sessões de escrita.

C++

Todas as sessões de C++ são iguais. Não existem sessões só de leitura nem de leitura/escrita.

C#

A fração de sessões de escrita predefinida para C# é 0,2. Pode alterar a fração através do campo WriteSessionsFraction de SessionPoolOptions.

Go

Todas as sessões do Go são iguais. Não existem sessões só de leitura ou de leitura/escrita.

Java

Todas as sessões Java são iguais. Não existem sessões só de leitura nem de leitura/escrita.

Node.js

Todas as sessões do Node.js são iguais. Não existem sessões só de leitura nem de leitura/escrita.

PHP

Todas as sessões de PHP são iguais. Não existem sessões só de leitura nem de leitura/escrita.

Python

O Python suporta quatro tipos de conjunto de sessões diferentes que pode usar para gerir sessões de leitura e leitura/escrita.

Ruby

A fração de sessões de gravação predefinida para Ruby é 0,3. Pode alterar a fração através do método de inicialização do cliente.

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

As seguintes descrições apresentam práticas recomendadas para implementar sessões numa biblioteca do cliente para o Spanner ou para usar sessões com as APIs REST ou RPC.

Estas práticas recomendadas só se aplicam se estiver a desenvolver uma biblioteca de cliente ou se estiver a usar APIs REST/RPC. Se estiver a usar uma das bibliotecas de cliente da Google para o Spanner, consulte as práticas recomendadas quando usar bibliotecas de cliente da Google.

Crie e dimensione o conjunto de sessões

Para determinar um tamanho ideal do conjunto de sessões para um processo de cliente, defina o limite inferior para o número de transações simultâneas esperadas e defina o limite superior para um número de teste inicial, como 100. Se o limite superior não for adequado, aumente-o. O aumento do número de sessões ativas usa recursos adicionais no serviço de base de dados do Spanner, pelo que a não limpeza das sessões não usadas pode degradar o desempenho. Para os utilizadores que trabalham com a API RPC, recomendamos que tenham, no máximo, 100 sessões por canal gRPC.

Processar sessões eliminadas

Existem três formas de eliminar uma sessão:

  • Um cliente pode eliminar uma sessão.
  • O serviço de base de dados do Spanner pode eliminar uma sessão quando esta estiver inativa durante mais de 1 hora.
  • O serviço de base de dados do Spanner pode eliminar uma sessão se tiver mais de 28 dias.

As tentativas de usar um resultado de sessão eliminado resultam em NOT_FOUND. Se encontrar este erro, crie e use uma nova sessão, adicione a nova sessão ao conjunto e remova a sessão eliminada do conjunto.

Mantenha uma sessão inativa ativa

O serviço de base de dados do Spanner reserva-se o direito de eliminar uma sessão não utilizada. Se precisar mesmo de manter uma sessão inativa ativa, por exemplo, se for esperado um aumento significativo a curto prazo na utilização da base de dados, pode impedir que a sessão seja terminada. Faça uma operação barata, como executar a consulta SQL SELECT 1, para manter a sessão ativa. Se tiver uma sessão inativa que não seja necessária para utilização a curto prazo, deixe o Spanner eliminar a sessão e, em seguida, crie uma nova sessão da próxima vez que precisar de uma.

Um cenário para manter as sessões ativas é processar a procura de pico regular na base de dados. Se a utilização intensa da base de dados ocorrer diariamente entre as 09:00 e as 18:00, deve manter algumas sessões inativas ativas durante esse período, uma vez que é provável que sejam necessárias para a utilização máxima. Após as 18:00, pode permitir que o Spanner elimine as sessões inativas. Antes das 09:00 de cada dia, crie algumas novas sessões para que estejam prontas para a procura esperada.

Outro cenário é se tiver uma aplicação que use o Spanner, mas tiver de evitar a sobrecarga de ligação quando o faz. Pode manter um conjunto de sessões ativas para evitar a sobrecarga de ligação.

Oculte os detalhes da sessão ao utilizador da biblioteca de cliente

Se estiver a criar uma biblioteca de cliente, não exponha sessões ao consumidor da biblioteca de cliente. Oferecer ao cliente a capacidade de fazer chamadas de base de dados sem a complexidade de criar e manter sessões. Para ver um exemplo de uma biblioteca cliente que oculta os detalhes da sessão do consumidor da biblioteca cliente, consulte a biblioteca cliente do Spanner para Java.

Trate erros de transações de escrita que não sejam idempotentes

As transações de escrita sem proteção contra repetição podem aplicar mutações mais do que uma vez. Se uma mutação não for idempotente, uma mutação aplicada mais do que uma vez pode resultar numa falha. Por exemplo, uma inserção pode falhar com ALREADY_EXISTS, mesmo que a linha não existisse antes da tentativa de escrita. Isto pode ocorrer se o servidor de back-end tiver confirmado a mutação, mas não tiver conseguido comunicar o êxito ao cliente. Nesse caso, a mutação pode ser tentada novamente, o que resulta na falha ALREADY_EXISTS.

Seguem-se possíveis formas de abordar este cenário quando implementa a sua própria biblioteca cliente ou usa a API REST:

  • Estruture as suas escritas para serem idempotentes.
  • Use gravações com proteção contra repetição.
  • Implemente um método que execute a lógica "upsert": insira se for novo ou atualize se existir.
  • Tratar o erro em nome do cliente.

Manter ligações estáveis

Para o melhor desempenho, a ligação que usa para alojar uma sessão deve permanecer estável. Quando a ligação que aloja uma sessão muda, o Spanner pode anular a transação ativa na sessão e causar uma pequena quantidade de carga adicional na sua base de dados enquanto atualiza os metadados da sessão. Não há problema se algumas associações mudarem esporadicamente, mas deve evitar situações que alterem um grande número de associações ao mesmo tempo. Se usar um proxy entre o cliente e o Spanner, deve manter a estabilidade da ligação para cada sessão.

Monitorize sessões ativas

Pode usar o comando ListSessions para monitorizar sessões ativas na sua base de dados a partir da linha de comandos, com a API REST ou com a API RPC. ListSessions mostra as sessões ativas para uma determinada base de dados. Isto é útil se precisar de encontrar a causa de uma fuga de sessão. (Uma fuga de sessão é um incidente em que as sessões estão a ser criadas, mas não são devolvidas a um conjunto de sessões para reutilização.)

ListSessions permite-lhe ver metadados sobre as suas sessões ativas, incluindo quando uma sessão foi criada e quando foi usada pela última vez. A análise destes dados indica-lhe o caminho certo quando resolve problemas de sessões. Se a maioria das sessões ativas não tiver um approximate_last_use_time recente, isto pode indicar que a sua aplicação não está a reutilizar as sessões corretamente. Consulte a referência da API RPC para obter mais informações sobre o campo approximate_last_use_time.

Consulte a referência da API REST, a referência da API RPC ou a referência da ferramenta de linha de comandos gcloud para obter mais informações sobre a utilização de ListSessions.

Limpeza automática de fugas de sessões

Quando usa todas as sessões no seu conjunto de sessões, cada nova transação aguarda até que uma sessão seja devolvida ao conjunto. Quando as sessões são criadas, mas não são devolvidas ao conjunto de sessões para reutilização, isto denomina-se uma fuga de sessões. Quando existe uma fuga de sessão, as transações que aguardam uma sessão aberta ficam bloqueadas indefinidamente e bloqueiam a aplicação. As fugas de sessões são frequentemente causadas por transações problemáticas que estão em execução durante um período extremamente longo e não são confirmadas.

Pode configurar o conjunto de sessões para resolver automaticamente estas transações inativas. Quando ativa a resolução automática de transições inativas na biblioteca de cliente, esta identifica transações problemáticas que podem causar uma fuga de sessão, remove-as do conjunto de sessões e substitui-as por uma nova sessão.

O registo também pode ajudar a identificar estas transações problemáticas. Se o registo estiver ativado, os registos de aviso são partilhados por predefinição quando mais de 95% do seu conjunto de sessões está em utilização. Se a utilização da sessão for superior a 95%, tem de aumentar o número máximo de sessões permitidas no conjunto de sessões ou pode ter uma fuga de sessões. Os registos de aviso contêm rastreios de pilha de transações que são executadas durante mais tempo do que o esperado e podem ajudar a identificar a causa da elevada utilização do conjunto de sessões. Os registos de aviso são enviados consoante a configuração do exportador de registos.

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

Pode ativar a biblioteca de cliente para enviar registos de aviso e resolver automaticamente as transações inativas ou ativar a biblioteca de cliente para receber apenas registos de aviso.

Java

Para receber registos de avisos 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 registos 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 registos de avisos 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 registos 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-lhe criar um grande número de pedidos simultâneos numa única sessão. Uma sessão multiplexada é um identificador que usa em vários canais gRPC. Não introduz estrangulamentos adicionais. As sessões multiplexadas têm as seguintes vantagens:

  • Consumo de recursos de back-end reduzido devido a um protocolo de gestão de sessões mais simples. Por exemplo, evitam atividades de manutenção de sessões associadas à manutenção da propriedade das sessões e à recolha de lixo.
  • Sessão de longa duração que não requer pedidos de manutenção quando está inativa.

As sessões multiplexadas são suportadas no seguinte:

  • As bibliotecas cliente Java, Go, Node e Python.
  • Ferramentas do ecossistema Spanner que dependem das bibliotecas de cliente mencionadas, como PGAdapter, JDBC, Hibernate, controlador database/sql, controlador dbAPI e GORM.

  • Ferramentas do ecossistema Spanner que dependem das bibliotecas de cliente Java e Go, como PGAdapter, JDBC, Hibernate, base de dados ou controlador SQL e GORM. Pode usar as métricas OpenTelemetry para ver como o tráfego é dividido entre o conjunto de sessões existente e a sessão multiplexada. O OpenTelemetry tem um filtro de métricas, is_multiplexed, que mostra sessões multiplexadas quando definido como true.

As sessões multiplexadas são suportadas para todos os tipos de transações.

As bibliotecas de cliente rodam as sessões multiplexadas a cada 7 dias para evitar o envio de transações em sessões desatualizadas.

As sessões multiplexadas estão ativadas por predefinição em algumas bibliotecas cliente. Para outros, tem de usar variáveis de ambiente para os ativar. Para ver detalhes, consulte o artigo Ative as sessões multiplexadas.

Considerações

Se estiver a tentar confirmar um corpo de transação de leitura ou escrita vazio, ou uma transação em que todas as consultas ou declarações DML falharam, existem alguns cenários a considerar com sessões multiplexadas. As sessões multiplexadas requerem que inclua um token de pré-confirmação gerado pelo servidor em cada pedido de confirmação. Para transações que contenham consultas ou DML, tem de existir, pelo menos, uma transação de consulta ou DML bem-sucedida anterior para que o servidor envie um token válido para a biblioteca de cliente. Se não tiverem existido consultas ou transações DML bem-sucedidas, a biblioteca de cliente adiciona implicitamente SELECT 1 antes de uma confirmação.

Para uma transação de leitura ou escrita numa sessão multiplexada que só tenha mutações, se uma das mutações for para uma tabela ou uma coluna que NÃO exista no esquema, o cliente pode devolver um erro INVALID_ARGUMENT em vez de um erro NOT_FOUND.

Ative as sessões multiplexadas

As sessões multiplexadas estão ativadas por predefinição nas seguintes bibliotecas cliente:

  • Java na versão 6.98.0 e posteriores.
  • Go na versão 1.85.0 e posteriores.
  • Python na versão 3.57.0 e posteriores.

Para usar sessões multiplexadas em aplicações cliente Node ou versões anteriores das bibliotecas cliente Java e Go, tem de definir primeiro uma variável de ambiente para as ativar.

Para ativar as sessões multiplexadas, defina a variável de ambiente GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS como TRUE. Esta flag também ativa o suporte de sessões multiplexadas para transações ReadOnly.

export GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS=TRUE

Para ativar o suporte de operações particionadas para sessões multiplexadas, defina a variável de ambiente GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS_PARTITIONED_OPS como TRUE.

export GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS_PARTITIONED_OPS=TRUE

Para ativar o suporte de transações de leitura/escrita para sessões multiplexadas, defina a variável de ambiente GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS_FOR_RW como TRUE.

export GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS_FOR_RW=True

Tem de definir GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS como TRUE como pré-requisito para suportar uma transação numa sessão multiplexada.

Veja o tráfego para sessões normais e multiplexadas

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

  1. Configure o OpenTelemetry para o Spanner através dos procedimentos na secção Spanner OpenTelemetry Antes de começar.
  2. Navegue para o Explorador de métricas.

    Aceda ao Metrics Explorer

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

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

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

    a. is_multiplexed = false para ver sessões regulares. b. is_multiplexed = true para ver sessões multiplexadas.

    A imagem seguinte mostra a opção Filtrar com sessões multiplexadas selecionadas.

Para mais informações sobre a utilização do OpenTelemetry com o Spanner, consulte os artigos Tirar partido do OpenTelemetry para democratizar a observabilidade do Spanner e Examine a latência num componente do Spanner com o OpenTelemetry.

Painel de controlo do Opentelemetry a mostrar o filtro is-multiplexed.

Resolver problemas

Os erros comuns relacionados com a sessão que a sua aplicação pode encontrar incluem:

  • Session not found
  • RESOURCE_EXHAUSTED

Para mais informações, consulte o artigo Erros de sessão.