התחברות ל-Spanner באמצעות Cassandra Adapter

בדף הזה מתואר Cassandra Adapter ומוסבר איך להשתמש בו כדי להתחבר ל-Spanner.

המתאם של Cassandra מיועד להפעלה באותו מחשב שבו פועלת האפליקציה. המתאם חושף נקודת קצה ב-localhost שתומכת בפרוטוקול Cassandra Query Language (CQL). הוא מתרגם את פרוטוקול התקשורת של CQL ל-gRPC, פרוטוקול התקשורת של Spanner. כשהפרוקסי הזה פועל באופן מקומי, לקוח Cassandra יכול להתחבר למסד נתונים של Spanner.

אפשר להפעיל את Cassandra Adapter בדרכים הבאות:

  • בתהליך עם אפליקציית Go
  • בתוך האפליקציה שלכם ב-Java
  • כתהליך עצמאי
  • במאגר Docker

לפני שמתחילים

לפני שמפעילים את Cassandra Adapter, צריך לוודא שעברתם אימות באמצעות חשבון משתמש או חשבון שירות במחשב שבו Cassandra Adapter יפעל. אם אתם משתמשים בחשבון שירות, אתם צריכים לדעת את המיקום של קובץ מפתח ה-JSON (קובץ פרטי הכניסה). מגדירים את משתנה הסביבה GOOGLE_APPLICATION_CREDENTIALS כדי לציין את הנתיב של פרטי הכניסה. לפני שמפעילים את Cassandra Adapter, צריך לוודא שעברתם אימות באמצעות חשבון משתמש או חשבון שירות במחשב שבו Cassandra Adapter יפעל. אם אתם משתמשים בחשבון שירות, אתם צריכים לדעת את המיקום של קובץ מפתח ה-JSON (קובץ פרטי הכניסה). מגדירים את משתנה הסביבה GOOGLE_APPLICATION_CREDENTIALS כדי לציין את הנתיב של פרטי הכניסה.

למידע נוסף:

חיבור Cassandra Adapter לאפליקציה

כדי להשתמש ב-Cassandra Adapter, צריך לספק את הפרטים הבאים:

  • Project name
  • שם המכונה ב-Spanner
  • מסד הנתונים שאליו מתחברים

אם אתם משתמשים ב-Docker, אתם צריכים את הנתיב לקובץ פרטי כניסה בפורמט JSON (קובץ מפתח).

Java in-process

  1. אם אתם משתמשים בחשבון שירות לאימות, חשוב לוודא שמשתנה הסביבה GOOGLE_APPLICATION_CREDENTIALS מוגדר לנתיב של קובץ פרטי הכניסה.

  2. באפליקציות Java, אפשר לקשר את Cassandra Adapter לאפליקציה ישירות על ידי הוספת google-cloud-spanner-cassandra כתלות לפרויקט.

ב-Maven, מוסיפים את התלות החדשה הבאה בקטע <dependencies>:

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

ב-Gradle, מוסיפים את הקוד הבא:

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

  1. משנים את קוד היצירה של CqlSession. במקום להשתמש ב-CqlSessionBuilder, משתמשים ב-SpannerCqlSessionBuilder ומזינים את ה-URI של מסד הנתונים ב-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, צריך לשנות שורה אחת בקובץ האתחול של האשכול כדי לשלב את לקוח Spanner Cassandra Go. לאחר מכן תוכלו לקשר את Cassandra Adapter לאפליקציה ישירות.

  1. מייבאים את חבילת spanner של המתאם מלקוח Spanner Cassandra Go באפליקציית Go.
import spanner "github.com/googleapis/go-spanner-cassandra/cassandra/gocql"
  1. משנים את קוד יצירת האשכול כך שישתמש ב-spanner.NewCluster במקום ב-gocql.NewCluster, ומזינים את ה-URI של מסד הנתונים ב-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
    }

אחרי שמתחברים למסד הנתונים של Spanner, אפשר להגדיר את האשכול כרגיל.

עצמאי

  1. משכפלים את המאגר:
git clone https://github.com/googleapis/go-spanner-cassandra.git
cd go-spanner-cassandra
  1. מריצים את הפקודה cassandra_launcher.go עם הדגל -db הנדרש:
go run cassandra_launcher.go \
-db "projects/my_project/instances/my_instance/databases/my_database"
  1. מחליפים את -db ב-URI של מסד הנתונים שלכם ב-Spanner.

Docker

מריצים את Cassandra Adapter באמצעות הפקודה הבאה.

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

הרשימה הבאה מכילה את אפשרויות ההפעלה הנפוצות ביותר של Spanner Cassandra Adapter:

  • -db <DatabaseUri>

ה-URI של מסד הנתונים של Spanner (חובה). כאן מציינים את מסד הנתונים של Spanner שאליו הלקוח מתחבר. לדוגמה, projects/YOUR_PROJECT/instances/YOUR_INSTANCE/databases/YOUR_DATABASE.

  • -tcp <TCPEndpoint>

כתובת מאזין ה-Proxy של הלקוח. ההגדרה הזו מגדירה את נקודת הקצה של TCP שבה הלקוח מאזין לחיבורים נכנסים של לקוח Cassandra. ברירת מחדל:localhost:9042

  • -grpc-channels <NumGrpcChannels>

מספר ערוצי gRPC שבהם יש להשתמש כשמתחברים ל-Spanner. ברירת מחדל: 4

לדוגמה, הפקודה הבאה מפעילה את Cassandra Adapter ביציאה 9042 באמצעות פרטי הכניסה של האפליקציה, ומקשרת את המתאם למסד הנתונים 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

המלצות

ההמלצות הבאות יעזרו לכם לשפר את חוויית השימוש ב-Cassandra Adapter. ההמלצות האלה מתמקדות ב-Java, ובמיוחד במנהל התקן של לקוח Cassandra ל-Java בגרסה 4.

הגדלת הזמן הקצוב לתפוגת הבקשה

זמן קצוב לתפוגה של בקשה של חמש שניות או יותר מספק חוויה טובה יותר עם Cassandra Adapter מאשר ערך ברירת המחדל של שתי שניות.

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

שיפור הביצועים של מאגר החיבורים

ההגדרות שמוגדרות כברירת מחדל למספר החיבורים המקסימלי ולמספר הבקשות המקסימלי בו-זמנית לכל חיבור או לכל מארח מתאימות לפיתוח, לבדיקה ולסביבות ייצור או לבמה עם נפח נמוך. עם זאת, מומלץ להגדיל את הערכים האלה, כי Cassandra Adapter מתחזה לצומת יחיד, בניגוד למאגר צמתים בתוך Cassandra cluster.

הגדלת הערכים האלה מאפשרת יותר חיבורים בו-זמניים בין הלקוח לבין Cassandra Interface. כך אפשר למנוע מצב שבו מאגר החיבורים מתרוקן בעומס כבד.

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

כוונון ערוצי gRPC

הלקוח של Spanner משתמש בערוצי gRPC לתקשורת. ערוץ gRPC אחד שווה בערך לחיבור TCP. ערוץ gRPC אחד יכול לטפל בעד 100 בקשות בו-זמניות. כלומר, לאפליקציה צריך להיות לפחות מספר הערוצים של gRPC ששווה למספר הבקשות המקבילות שהאפליקציה תבצע, חלקי 100.

השבתת ניתוב מודע לטוקן

יכול להיות שיוצג לנהגים שמשתמשים באיזון עומסים מבוסס-טוקנים אזהרה, או שהם לא יוכלו לעבוד עם Cassandra Adapter. מכיוון ש-Cassandra Adapter מתחזה לצומת יחיד, הוא לא תמיד פועל בצורה טובה עם מנהלי התקנים שמודעים לטוקנים ומצפים שיהיו לפחות מספר צמתים ששווה לגורם השכפול באשכול. חלק מהדרייברים עשויים להדפיס אזהרה (שאפשר להתעלם ממנה) ולחזור למדיניות איזון כמו round-robin, בעוד שדרייברים אחרים עשויים להיכשל עם שגיאה. לגבי הדרייברים שנכשלו עם שגיאה, צריך להשבית את המודעות לטוקנים או להגדיר את מדיניות איזון העומסים מסוג round-robin.

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

הצמדת גרסת הפרוטוקול ל-V4

מתאם Cassandra תואם לכל מנהל התקן של לקוח Apache Cassandra בקוד פתוח שתואם לפרוטוקול CQL Binary v4 wire. חשוב להקפיד להצמיד את PROTOCOL_VERSION אל V4, אחרת יכול להיות שיוצגו שגיאות חיבור.

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

המאמרים הבאים