הגדרת מאגרי חיבורים

חלק מספריות הלקוח של Cloud Bigtable מאפשרות להגדיר את מספר ערוצי ה-gRPC במאגר החיבורים של הלקוח, שנקרא גם מאגר ערוצים. ברוב המקרים, הגדרת ברירת המחדל נכונה ואין צורך לשנות אותה.

הגודל של מאגרי החיבורים משתנה אוטומטית לפי הצורך כשמשתמשים בספריית הלקוח של Cloud Bigtable ל-Java בגרסה 2.23.0 ואילך, וכשמשתמשים בלקוח Cloud Bigtable HBase ל-Java בגרסה 2.9.1 ואילך.

בדף הזה מוסבר איך לקבוע את הגודל האופטימלי של מאגר החיבורים לאפליקציה, ומוצגים בו קטעי קוד שמראים איך להגדיר את מאגרי החיבורים.

לפני שקוראים את הדף הזה, מומלץ לקרוא את הסקירה הכללית על מאגרי חיבורים של Bigtable כדי להבין איך הם פועלים והאם כדאי לשנות את המאגרים שלכם.

ספריות הלקוח הבאות מציעות מאגרי חיבורים ומאפשרות להגדיר את מספר המאגרים:

קביעת הגודל האופטימלי של מאגר החיבורים

כדי להשאיר מקום לתנודות בתנועה, מומלץ שבמאגר החיבורים יהיו בערך פי שניים חיבורים מהמספר הנדרש לרוויה מקסימלית. חיבור יכול לטפל במספר מקסימלי של 100 בקשות בו-זמניות, ולכן מספר אופטימלי של בקשות בהמתנה לכל חיבור הוא בין 10 ל-50. הקונספט הזה מוסבר בפירוט במאמר בנושא מאגרי חיבורים.

אחרי שמבצעים שינויים, עוקבים אחרי התנועה ומשנים את מספר החיבורים במאגר לפי הצורך.

השלבים הבאים יעזרו לכם לחשב את המספר האופטימלי של חיבורים במאגר הערוצים באמצעות מדדים בצד הלקוח, כמו אלה שזמינים ב-OpenCensus.

  1. מהמדדים בצד הלקוח, אוספים את הפרטים הבאים:
    1. המספר המקסימלי של שאילתות לשנייה (QPS) לכל לקוח כשהאפליקציה מפעילה עומס עבודה טיפוסי.
    2. זמן האחזור הממוצע (זמן התגובה לבקשה יחידה) באלפיות השנייה.
  2. כדי לקבוע את מספר הבקשות שאפשר לשלוח ברצף בכל שנייה, מחלקים את המספר 1,000 בערך החביון הממוצע.
  3. מחלקים את השאילתות לשנייה בשניות במספר הבקשות הסדרתיות לשנייה.
  4. מחלקים את התוצאה ב-50 בקשות לכל ערוץ כדי לקבוע את גודל המאגר האופטימלי המינימלי של הערוצים. (אם החישוב שלכם נמוך מ-2, בכל מקרה צריך להשתמש לפחות ב-2 ערוצים כדי להבטיח יתירות).
  5. מחלקים את אותה התוצאה ב-10 בקשות לכל ערוץ כדי לקבוע את הגודל המקסימלי האופטימלי של מאגר הערוצים.

השלבים האלה מופיעים במשוואות הבאות:

  • ‫(QPS sec ÷ (1,000 ÷ latency ms)) ÷ 50 streams = Minimum optimal number of connections

  • ‫(QPS sec ÷ (1,000 ÷ latency ms)) ÷ 10 streams = Maximum optimal number of connections

דוגמה

האפליקציה שלכם בדרך כלל שולחת 50,000 בקשות בשנייה, וזמן האחזור הממוצע הוא 10 אלפיות השנייה. מחלקים את 1,000 ב-10 אלפיות השנייה כדי לקבוע שאפשר לשלוח 100 בקשות ברצף בשנייה. מחלקים את המספר הזה ב-50,000 כדי לקבל את רמת המקביליות שנדרשת לשליחת 50,000 QPS: 500. בכל ערוץ יכולות להיות לכל היותר 100 בקשות בו-זמנית, והשימוש בערוץ היעד הוא בין 10 ל-50 סטרימינג בו-זמנית. לכן, כדי לחשב את הערך המינימלי, מחלקים את 500 ב-50 ומקבלים 10. כדי למצוא את המקסימום, מחלקים את 500 ב-10 ומקבלים 50. המשמעות היא שגודל מאגר הערוצים בדוגמה הזו צריך להיות בין 10 ל-50 חיבורים.

הגדרת גודל המאגר

בדוגמאות הקוד הבאות אפשר לראות איך מגדירים את מספר המאגרים בספריות הלקוח שמאפשרות להגדיר את גודל המאגר.

המשך

import (
	"context"
	"fmt"
	"io"

	"cloud.google.com/go/bigtable"
	"google.golang.org/api/option"
)

func configureConnectionPool(w io.Writer, projectID, instanceID string) error {
	// projectID := "my-project-id"
	// instanceID := "my-instance-id"
	ctx := context.Background()

	// Set up Bigtable data operations client.
	poolSize := 10
	client, err := bigtable.NewClient(ctx, projectID, instanceID, option.WithGRPCConnectionPool(poolSize))
	defer client.Close()

	if err != nil {
		return fmt.Errorf("bigtable.NewClient: %w", err)
	}

	fmt.Fprintf(w, "Connected with pool size of %d", poolSize)

	return nil
}

HBase

הדוגמה הזו רלוונטית רק לגרסאות של ספריות לקוח שקודמות לגרסה 2.9.1, שבה הוצגה האפשרות של שינוי גודל אוטומטי.



import static com.google.cloud.bigtable.hbase.BigtableOptionsFactory.BIGTABLE_DATA_CHANNEL_COUNT_KEY;

import com.google.cloud.bigtable.hbase.BigtableConfiguration;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.client.Connection;

public class ConfigureConnectionPool {

  public static void configureConnectionPool(String projectId, String instanceId) {
    // String projectId = "my-project-id";
    // String instanceId = "my-instance-id";
    Configuration config = BigtableConfiguration.configure(projectId, instanceId);
    config.setInt(BIGTABLE_DATA_CHANNEL_COUNT_KEY, 10);
    try (Connection connection = BigtableConfiguration.connect(config)) {
      int poolSize = connection.getConfiguration().getInt(BIGTABLE_DATA_CHANNEL_COUNT_KEY, 0);

      System.out.println(String.format("Connected with pool size of %d", poolSize));
    } catch (Exception e) {
      System.out.println("Error during ConfigureConnectionPool: \n" + e.toString());
    }
  }
}

Java

הדוגמה הזו רלוונטית רק לגרסאות של ספריית הלקוח שקדמו לגרסה 2.23.0, שבה הוצגה האפשרות של שינוי גודל אוטומטי.


import com.google.api.gax.grpc.InstantiatingGrpcChannelProvider;
import com.google.cloud.bigtable.data.v2.BigtableDataClient;
import com.google.cloud.bigtable.data.v2.BigtableDataSettings;
import com.google.cloud.bigtable.data.v2.stub.EnhancedBigtableStubSettings;
import java.io.IOException;

public class ConfigureConnectionPool {

  public static void configureConnectionPool(String projectId, String instanceId) {
    // String projectId = "my-project-id";
    // String instanceId = "my-instance-id";

    BigtableDataSettings.Builder settingsBuilder =
        BigtableDataSettings.newBuilder().setProjectId(projectId).setInstanceId(instanceId);

    settingsBuilder
        .stubSettings()
        .setTransportChannelProvider(
            EnhancedBigtableStubSettings.defaultGrpcTransportProviderBuilder()
                .setPoolSize(10)
                .build());

    BigtableDataSettings settings = settingsBuilder.build();
    try (BigtableDataClient dataClient = BigtableDataClient.create(settings)) {
      InstantiatingGrpcChannelProvider provider =
          (InstantiatingGrpcChannelProvider)
              settings.getStubSettings().getTransportChannelProvider();

      int poolSize = provider.toBuilder().getPoolSize();

      System.out.println(String.format("Connected with pool size of %d", poolSize));
    } catch (IOException e) {
      System.out.println("Error during ConfigureConnectionPool: \n" + e.toString());
    }
  }
}

C++‎

namespace cbt = ::google::cloud::bigtable;
namespace gc = ::google::cloud;
[](std::string const& project_id, std::string const& instance_id,
   std::string const& table_id) {
  auto constexpr kPoolSize = 10;
  auto options = gc::Options{}.set<gc::GrpcNumChannelsOption>(kPoolSize);
  cbt::Table table(cbt::MakeDataConnection(options),
                   cbt::TableResource(project_id, instance_id, table_id));
  std::cout << "Connected with channel pool size of " << kPoolSize << "\n";
}