Connettiti a Spanner utilizzando l'adattatore Cassandra

Questa pagina descrive l'adattatore Cassandra e spiega come utilizzare e connettere Spanner da questo adattatore.

L'adattatore Cassandra è progettato per essere eseguito sulla stessa macchina dell'applicazione. L'adattatore espone un endpoint su localhost che supporta il protocollo di rete Cassandra Query Language (CQL). Converte il protocollo di rete CQL in gRPC, il protocollo di rete Spanner. Con questo proxy in esecuzione in locale, un client Cassandra può connettersi a un database Spanner.

Puoi avviare l'adattatore Cassandra nei seguenti modi:

  • In-process con l'applicazione Go
  • In-process con l'applicazione Java
  • Come processo autonomo
  • In un container Docker

Prima di iniziare

Prima di avviare l'adattatore Cassandra, assicurati di aver eseguito l'autenticazione con un account utente o un account di servizio sulla macchina in cui verrà eseguito l'adattatore Cassandra. Se utilizzi un account di servizio, devi conoscere la posizione del file della chiave JSON (il file delle credenziali). Imposta la variabile di ambiente GOOGLE_APPLICATION_CREDENTIALS per specificare il percorso delle credenziali. Prima di avviare l'adattatore Cassandra, assicurati di aver eseguito l'autenticazione con un account utente o un account di servizio sulla macchina in cui verrà eseguito l'adattatore Cassandra. Se utilizzi un account di servizio, devi conoscere la posizione del file della chiave JSON (il file delle credenziali). Imposta la variabile di ambiente GOOGLE_APPLICATION_CREDENTIALS per specificare il percorso delle credenziali.

Per ulteriori informazioni, vedi:

Connettere l'adattatore Cassandra all'applicazione

L'adattatore Cassandra richiede le seguenti informazioni:

  • Nome progetto
  • Nome istanza Spanner
  • Database a cui connettersi

Se utilizzi Docker, ti serve il percorso di un file delle credenziali in formato JSON (file della chiave).

Java in-process

  1. Se utilizzi un account di servizio per l'autenticazione, assicurati che la variabile di ambiente GOOGLE_APPLICATION_CREDENTIALS sia impostata sul percorso del file delle credenziali.

  2. Per le applicazioni Java, puoi collegare l'adattatore Cassandra direttamente all'applicazione aggiungendo google-cloud-spanner-cassandra come dipendenza al tuo progetto.

Per Maven, aggiungi la seguente nuova dipendenza nella <dependencies> sezione:

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

Per Gradle, aggiungi quanto segue:

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

  1. Modifica il codice di creazione di CqlSession. Anziché utilizzare CqlSessionBuilder, utilizza SpannerCqlSessionBuilder e fornisci il URI del database 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();
        }
      }
    }
    

Go in-process

Per le applicazioni Go, devi apportare una modifica di una riga al file di inizializzazione del cluster per integrare il client Spanner Cassandra Go. A questo punto, puoi collegare l'adattatore Cassandra direttamente all'applicazione.

  1. Importa il pacchetto spanner dell'adattatore dal client Spanner Cassandra Go nella tua applicazione Go.
import spanner "github.com/googleapis/go-spanner-cassandra/cassandra/gocql"
  1. Modifica il codice di creazione del cluster in modo da utilizzare spanner.NewCluster anziché gocql.NewCluster e fornisci l'URI del database 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
    }

Dopo aver eseguito la connessione al database Spanner, puoi configurare il cluster come di consueto.

Autonoma

  1. Clona il repository:
git clone https://github.com/googleapis/go-spanner-cassandra.git
cd go-spanner-cassandra
  1. Esegui cassandra_launcher.go con il flag -db obbligatorio:
go run cassandra_launcher.go \
-db "projects/my_project/instances/my_instance/databases/my_database"
  1. Sostituisci -db con l'URI del database Spanner.

Docker

Avvia l'adattatore Cassandra con il seguente comando.

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

Il seguente elenco contiene le opzioni di avvio più utilizzate per l'adattatore Spanner Cassandra:

  • -db <DatabaseUri>

L'URI del database Spanner (obbligatorio). Specifica il database Spanner a cui si connette il client. Ad esempio, projects/YOUR_PROJECT/instances/YOUR_INSTANCE/databases/YOUR_DATABASE.

  • -tcp <TCPEndpoint>

L'indirizzo del listener del proxy client. Definisce l'endpoint TCP in cui il client ascolta le connessioni client Cassandra in entrata. Valore predefinito:localhost:9042

  • -grpc-channels <NumGrpcChannels>

Il numero di canali gRPC da utilizzare per la connessione a Spanner. Valore predefinito: 4

Ad esempio, il seguente comando avvia l'adattatore Cassandra sulla porta 9042 utilizzando le credenziali dell'applicazione e connette l'adattatore al database 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

Consigli

I seguenti consigli ti aiutano a migliorare la tua esperienza con l'adattatore Cassandra. Questi consigli sono incentrati su Java, in particolare sul driver client Cassandra per Java versione 4.

Aumentare il timeout della richiesta

Un timeout della richiesta di cinque secondi o più offre un'esperienza migliore con l'adattatore Cassandra rispetto al valore predefinito di due secondi.

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

Ottimizzare il pool di connessioni

Le configurazioni predefinite per il numero massimo di connessioni e il numero massimo di richieste simultanee per connessione o host sono appropriate per gli ambienti di sviluppo, test e produzione o staging a basso volume. Tuttavia, ti consigliamo di aumentare questi valori, poiché l'adattatore Cassandra si maschera come un singolo nodo, a differenza di un pool di nodi all'interno del cluster Cassandra.

L'aumento di questi valori consente un maggior numero di connessioni simultanee tra il client e l'interfaccia Cassandra. In questo modo è possibile evitare l'esaurimento del pool di connessioni in caso di carico elevato.

# 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
  }
}

Ottimizzare i canali gRPC

I canali gRPC vengono utilizzati dal client Spanner per la comunicazione. Un canale gRPC è approssimativamente equivalente a una connessione TCP. Un canale gRPC può gestire fino a 100 richieste simultanee. Ciò significa che un'applicazione avrà bisogno di almeno tanti canali gRPC quante sono le richieste simultanee che eseguirà, divise per 100.

Disattivare il routing basato su token

I driver che utilizzano il bilanciamento del carico basato su token potrebbero stampare un avviso o non funzionare quando si utilizza l'adattatore Cassandra. Poiché l'adattatore Cassandra si maschera come un singolo nodo, non sempre funziona bene con i driver basati su token che si aspettano che nel cluster sia presente almeno un numero di nodi pari al fattore di replica. Alcuni driver potrebbero stampare un avviso (che può essere ignorato) e ricorrere a una policy di bilanciamento round robin, mentre altri potrebbero generare un errore. Per i driver che generano un errore, devi disattivare il routing basato su token o configurare la policy di bilanciamento del carico round robin.

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

Bloccare la versione del protocollo alla V4

L'adattatore Cassandra è compatibile con qualsiasi protocollo di rete CQL Binary v4 conforme, driver client Apache Cassandra open source. Assicurati di bloccare PROTOCOL_VERSION su V4, altrimenti potresti visualizzare errori di connessione.

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

Passaggi successivi