Conectar ao Spanner usando o adaptador Cassandra

Nesta página, descrevemos o adaptador do Cassandra e explicamos como usar e conectar o Spanner com ele.

O adaptador do Cassandra foi projetado para ser executado na mesma máquina que o aplicativo. O adaptador expõe um endpoint no localhost que é compatível com o protocolo de transmissão da linguagem de consulta do Cassandra (CQL). Ele converte o protocolo de transmissão CQL em gRPC, o protocolo de transmissão do Spanner. Com esse proxy em execução localmente, um cliente do Cassandra pode se conectar a um banco de dados do Spanner.

Você pode iniciar o adaptador do Cassandra das seguintes maneiras:

  • No processo com seu aplicativo Go
  • No processo com seu aplicativo Java
  • Como um processo independente
  • Em um contêiner do Docker

Antes de começar

Antes de iniciar o adaptador do Cassandra, verifique se você fez a autenticação com uma conta de usuário ou de serviço na máquina em que o adaptador será executado. Se você estiver usando uma conta de serviço, saiba o local do arquivo de chave JSON (o arquivo de credenciais). Você define a variável de ambiente GOOGLE_APPLICATION_CREDENTIALS para especificar o caminho das credenciais.

Veja mais informações em:

Conecte o adaptador do Cassandra ao seu aplicativo

O adaptador do Cassandra exige as seguintes informações:

  • Nome do projeto
  • Nome da instância do Spanner
  • Banco de dados a ser conectado

Se você usa o Docker, precisa do caminho para um arquivo de credenciais formatado em JSON (arquivo de chave).

Java no processo

  1. Se você estiver usando uma conta de serviço para autenticação, verifique se a variável de ambiente GOOGLE_APPLICATION_CREDENTIALS está definida como o caminho do arquivo de credenciais.

  2. Para aplicativos Java, é possível vincular o adaptador do Cassandra diretamente ao aplicativo adicionando google-cloud-spanner-cassandra como uma dependência ao seu projeto.

Para o Maven, adicione a seguinte dependência na seção <dependencies>:

<dependency>
    <groupId>com.google.cloud</groupId>
    <artifactId>google-cloud-spanner-cassandra</artifactId>
    <version>0.4.0</version>
</dependency>

Para o Gradle, adicione o seguinte:

dependencies {
    implementation 'com.google.cloud:google-cloud-spanner-cassandra:0.4.0'
}

  1. Modifique o código de criação de CqlSession. Em vez de usar CqlSessionBuilder, use SpannerCqlSessionBuilder e forneça o URI do banco de dados do Spanner:
    
    import com.datastax.oss.driver.api.core.CqlSession;
    import com.datastax.oss.driver.api.core.config.DefaultDriverOption;
    import com.datastax.oss.driver.api.core.config.DriverConfigLoader;
    import com.datastax.oss.driver.api.core.cql.ResultSet;
    import com.datastax.oss.driver.api.core.cql.Row;
    import com.google.cloud.spanner.adapter.SpannerCqlSession;
    import java.net.InetSocketAddress;
    import java.time.Duration;
    import java.util.Random;
    
    // This sample assumes your spanner database <my_db> contains a table <users>
    // with the following schema:
    
    // CREATE TABLE users (
    //  id        INT64          OPTIONS (cassandra_type = 'int'),
    //  active    BOOL           OPTIONS (cassandra_type = 'boolean'),
    //  username  STRING(MAX)    OPTIONS (cassandra_type = 'text'),
    // ) PRIMARY KEY (id);
    
    class QuickStartSample {
    
      public static void main(String[] args) {
    
        // TODO(developer): Replace these variables before running the sample.
        final String projectId = "my-gcp-project";
        final String instanceId = "my-spanner-instance";
        final String databaseId = "my_db";
    
        final String databaseUri =
            String.format("projects/%s/instances/%s/databases/%s", projectId, instanceId, databaseId);
    
        try (CqlSession session =
            SpannerCqlSession.builder() // `SpannerCqlSession` instead of `CqlSession`
                .setDatabaseUri(databaseUri) // Set spanner database URI.
                .addContactPoint(new InetSocketAddress("localhost", 9042))
                .withLocalDatacenter("datacenter1")
                .withKeyspace(databaseId) // Keyspace name should be the same as spanner database name
                .withConfigLoader(
                    DriverConfigLoader.programmaticBuilder()
                        .withString(DefaultDriverOption.PROTOCOL_VERSION, "V4")
                        .withDuration(
                            DefaultDriverOption.CONNECTION_INIT_QUERY_TIMEOUT, Duration.ofSeconds(5))
                        .build())
                .build()) {
    
          final int randomUserId = new Random().nextInt(Integer.MAX_VALUE);
    
          System.out.printf("Inserting user with ID: %d%n", randomUserId);
    
          // INSERT data
          session.execute(
              "INSERT INTO users (id, active, username) VALUES (?, ?, ?)",
              randomUserId,
              true,
              "John Doe");
    
          System.out.printf("Successfully inserted user: %d%n", randomUserId);
          System.out.printf("Querying user: %d%n", randomUserId);
    
          // SELECT data
          ResultSet rs =
              session.execute("SELECT id, active, username FROM users WHERE id = ?", randomUserId);
    
          // Get the first row from the result set
          Row row = rs.one();
    
          System.out.printf(
              "%d %b %s%n", row.getInt("id"), row.getBoolean("active"), row.getString("username"));
    
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
    }
    

Entrar em andamento

Para aplicativos Go, faça uma mudança de uma linha no arquivo de inicialização do cluster para integrar o cliente Go do Spanner Cassandra. Em seguida, vincule o adaptador do Cassandra diretamente ao aplicativo.

  1. Importe o pacote spanner do adaptador do cliente Go do Spanner Cassandra no seu aplicativo Go.
import spanner "github.com/googleapis/go-spanner-cassandra/cassandra/gocql"
  1. Modifique o código de criação do cluster para usar spanner.NewCluster em vez de gocql.NewCluster e forneça o URI do banco de dados do Spanner:
    import (
    	"fmt"
    	"io"
    	"math"
    	"math/rand/v2"
    	"time"
    
    	spanner "github.com/googleapis/go-spanner-cassandra/cassandra/gocql"
    )
    
    // This sample assumes your spanner database <your_db> contains a table <users>
    // with the following schema:
    //
    // CREATE TABLE users (
    //	id   	 	INT64          OPTIONS (cassandra_type = 'int'),
    //	active    	BOOL           OPTIONS (cassandra_type = 'boolean'),
    //	username  	STRING(MAX)    OPTIONS (cassandra_type = 'text'),
    // ) PRIMARY KEY (id);
    
    func quickStart(databaseURI string, w io.Writer) error {
    	opts := &spanner.Options{
    		DatabaseUri: databaseURI,
    	}
    	cluster := spanner.NewCluster(opts)
    	if cluster == nil {
    		return fmt.Errorf("failed to create cluster")
    	}
    	defer spanner.CloseCluster(cluster)
    
    	// You can still configure your cluster as usual after connecting to your
    	// spanner database
    	cluster.Timeout = 5 * time.Second
    	cluster.Keyspace = "your_db_name"
    
    	session, err := cluster.CreateSession()
    
    	if err != nil {
    		return err
    	}
    
    	randomUserId := rand.IntN(math.MaxInt32)
    	if err = session.Query("INSERT INTO users (id, active, username) VALUES (?, ?, ?)",
    			       randomUserId, true, "John Doe").
    		Exec(); err != nil {
    		return err
    	}
    
    	var id int
    	var active bool
    	var username string
    	if err = session.Query("SELECT id, active, username FROM users WHERE id = ?",
    			       randomUserId).
    		Scan(&id, &active, &username); err != nil {
    		return err
    	}
    	fmt.Fprintf(w, "%d %v %s\n", id, active, username)
    	return nil
    }

É possível configurar o cluster normalmente depois de se conectar ao banco de dados do Spanner.

Independente

  1. Clone o repositório:
git clone https://github.com/googleapis/go-spanner-cassandra.git
cd go-spanner-cassandra
  1. Execute o comando cassandra_launcher.go com a flag -db necessária:
go run cassandra_launcher.go \
-db "projects/my_project/instances/my_instance/databases/my_database"
  1. Substitua -db pelo URI do banco de dados do Spanner.

Docker

Inicie o adaptador do Cassandra com o comando a seguir.

export GOOGLE_APPLICATION_CREDENTIALS=/path/to/credentials.json
docker run -d -p 9042:9042 \
-e GOOGLE_APPLICATION_CREDENTIALS \
-v ${GOOGLE_APPLICATION_CREDENTIALS}:${GOOGLE_APPLICATION_CREDENTIALS}:ro \
gcr.io/cloud-spanner-adapter/cassandra-adapter \
-db DATABASE_URI

A lista a seguir contém as opções de inicialização mais usadas para o adaptador do Spanner Cassandra:

  • -db <DatabaseUri>

O URI do banco de dados do Spanner (obrigatório). Isso especifica o banco de dados do Spanner a que o cliente se conecta. Por exemplo, projects/YOUR_PROJECT/instances/YOUR_INSTANCE/databases/YOUR_DATABASE.

  • -tcp <TCPEndpoint>

O endereço do listener do proxy do cliente. Isso define o endpoint TCP em que o cliente detecta conexões de clientes do Cassandra. Padrão:localhost:9042

  • -grpc-channels <NumGrpcChannels>

O número de canais gRPC a serem usados ao se conectar ao Spanner. Padrão: 4

Por exemplo, o comando a seguir inicia o adaptador do Cassandra na porta 9042 usando as credenciais do aplicativo e conecta o adaptador ao banco de dados projects/my_project/instances/my_instance/databases/my_database:

export GOOGLE_APPLICATION_CREDENTIALS=/path/to/credentials.json
docker run -d -p 9042:9042 \
-e GOOGLE_APPLICATION_CREDENTIALS \
-v ${GOOGLE_APPLICATION_CREDENTIALS}:${GOOGLE_APPLICATION_CREDENTIALS}:ro \
gcr.io/cloud-spanner-adapter/cassandra-adapter \
-db projects/my_project/instances/my_instance/databases/my_database

Recomendações

As recomendações a seguir ajudam a melhorar sua experiência com o adaptador do Cassandra. Essas recomendações são focadas em Java, especificamente no driver de cliente do Cassandra para Java versão 4.

Aumentar o tempo limite da solicitação

Um tempo limite de solicitação de cinco segundos ou mais oferece uma experiência melhor com o adaptador do Cassandra do que o valor padrão de dois segundos.

# Sample application.conf: increases request timeout to five seconds
datastax-java-driver {
  basic {
    request {
      timeout = 5 seconds
    }
  }
}

Ajustar o pool de conexões

As configurações padrão para contagem máxima de conexões e solicitações simultâneas máximas por conexão ou host são adequadas para desenvolvimento, teste e ambientes de produção ou preparo de baixo volume. No entanto, recomendamos que você aumente esses valores, já que o adaptador do Cassandra se disfarça como um único nó, ao contrário de um pool de nós no cluster do Cassandra.

Aumentar esses valores permite mais conexões simultâneas entre o cliente e a interface do Cassandra. Isso pode evitar o esgotamento do pool de conexões sob carga pesada.

# Sample application.conf: increases maximum number of requests that can be
# executed concurrently on a connection
advanced.connection {
  max-requests-per-connection = 32000
  pool {
    local.size = 10
  }
}

Ajustar canais gRPC

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

Desativar o roteamento com reconhecimento de token

Os drivers que usam o balanceamento de carga com reconhecimento de token podem imprimir um aviso ou não funcionar ao usar o adaptador do Cassandra. Como o adaptador do Cassandra se disfarça como um único nó, ele nem sempre funciona bem com drivers compatíveis com tokens que esperam que haja pelo menos um número de nós de fator de replicação no cluster. Alguns drivers podem imprimir um aviso (que pode ser ignorado) e recorrer a algo como uma política de balanceamento round-robin, enquanto outros drivers podem falhar com um erro. Para os drivers que falham com um erro, é necessário desativar o reconhecimento de token ou configurar a política de balanceamento de carga round-robin.

# Sample application.conf: disables token-aware routing
metadata {
  token-map {
    enabled = false
  }
}

Fixar a versão do protocolo na V4

O adaptador do Cassandra é compatível com qualquer protocolo de rede binário v4 do CQL e com um driver de cliente do Apache Cassandra de código aberto. Fixe PROTOCOL_VERSION em V4. Caso contrário, você pode encontrar erros de conexão.

# Sample application.conf: overrides protocol version to V4
datastax-java-driver {
  advanced.protocol.version = V4
}

A seguir