1. Introduzione
In questo codelab, utilizzerai gli strumenti di monitoraggio di Cloud Bigtable per creare varie opere d'arte scrivendo e leggendo i dati con Cloud Dataflow e il client Java HBase.
Imparerai a
- Carica grandi quantità di dati in Bigtable utilizzando Cloud Dataflow
- Monitora le istanze e le tabelle Bigtable durante l'importazione dei dati
- Query su Bigtable utilizzando un job Dataflow
- Esplora lo strumento Key Visualizer, che può essere usato per trovare gli hotspot in base alla progettazione dello schema
- Crea arte usando il Key Visualizer
Come valuteresti la tua esperienza di utilizzo di Cloud Bigtable?
Come utilizzerai questo tutorial?
2. Crea il tuo database Bigtable
Cloud Bigtable è il servizio di database di big data NoSQL di Google. È lo stesso database su cui si basano molti dei principali servizi di Google, tra cui Ricerca, Analytics, Maps e Gmail. È ideale per eseguire carichi di lavoro analitici di grandi dimensioni e creare applicazioni a bassa latenza. Consulta Introduction to Cloud Bigtable Codelab per un'introduzione approfondita.
Creare un progetto
Per prima cosa, crea un nuovo progetto. Usa Cloud Shell integrato, che puoi aprire facendo clic su "Attiva Cloud Shell" nell'angolo in alto a destra.
Imposta le seguenti variabili di ambiente per semplificare l'operazione di copia e incolla dei comandi del codelab:
BIGTABLE_PROJECT=$GOOGLE_CLOUD_PROJECT INSTANCE_ID="keyviz-art-instance" CLUSTER_ID="keyviz-art-cluster" TABLE_ID="art" CLUSTER_NUM_NODES=1 CLUSTER_ZONE="us-central1-c" # You can choose a zone closer to you
Cloud Shell include gli strumenti che utilizzerai in questo codelab, lo strumento a riga di comando gcloud, l'interfaccia a riga di comando cbt e Maven, già installati.
Abilita le API Cloud Bigtable eseguendo questo comando.
gcloud services enable bigtable.googleapis.com bigtableadmin.googleapis.com
Crea un'istanza eseguendo questo comando:
gcloud bigtable instances create $INSTANCE_ID \ --cluster=$CLUSTER_ID \ --cluster-zone=$CLUSTER_ZONE \ --cluster-num-nodes=$CLUSTER_NUM_NODES \ --display-name=$INSTANCE_ID
Dopo aver creato l'istanza, compila il file di configurazione cbt, quindi crea una famiglia di tabelle e colonne eseguendo questi comandi:
echo project = $GOOGLE_CLOUD_PROJECT > ~/.cbtrc echo instance = $INSTANCE_ID >> ~/.cbtrc cbt createtable $TABLE_ID cbt createfamily $TABLE_ID cf
3. Scopri: scrivere in Bigtable con Dataflow
Nozioni di base sulla scrittura
Quando scrivi in Cloud Bigtable, devi fornire un oggetto di configurazione CloudBigtableTableConfiguration
. Questo oggetto specifica l'ID progetto e l'ID istanza della tabella, nonché il nome della tabella stessa:
CloudBigtableTableConfiguration bigtableTableConfig = new CloudBigtableTableConfiguration.Builder() .withProjectId(PROJECT_ID) .withInstanceId(INSTANCE_ID) .withTableId(TABLE_ID) .build();
Quindi la pipeline può passare oggetti HBase Mutation
, che possono includere Put e Delete.
p.apply(Create.of("hello", "world")) .apply( ParDo.of( new DoFn<String, Mutation>() { @ProcessElement public void processElement(@Element String rowkey, OutputReceiver<Mutation> out) { long timestamp = System.currentTimeMillis(); Put row = new Put(Bytes.toBytes(rowkey)); row.addColumn(...); out.output(row); } })) .apply(CloudBigtableIO.writeToTable(bigtableTableConfig));
Job Dataflow di LoadData
La pagina successiva mostrerà come eseguire il job LoadData, ma qui tratterò le parti importanti della pipeline.
Per generare dati, creerai una pipeline che utilizza la classe GenerateSequence (analogamente a un ciclo for) per scrivere un numero di righe con pochi megabyte di dati casuali. Il valore rowkey corrisponderà al numero di sequenza riempito e invertito, quindi 250
diventa 0000000052
.
LoadData.java
String numberFormat = "%0" + maxLength + "d"; p.apply(GenerateSequence.from(0).to(max)) .apply( ParDo.of( new DoFn<Long, Mutation>() { @ProcessElement public void processElement(@Element Long rowkey, OutputReceiver<Mutation> out) { String paddedRowkey = String.format(numberFormat, rowkey); // Reverse the rowkey for more efficient writing String reversedRowkey = new StringBuilder(paddedRowkey).reverse().toString(); Put row = new Put(Bytes.toBytes(reversedRowkey)); // Generate random bytes byte[] b = new byte[(int) rowSize]; new Random().nextBytes(b); long timestamp = System.currentTimeMillis(); row.addColumn(Bytes.toBytes(COLUMN_FAMILY), Bytes.toBytes("C"), timestamp, b); out.output(row); } })) .apply(CloudBigtableIO.writeToTable(bigtableTableConfig));
4. Genera dati in Bigtable e monitora il flusso
I seguenti comandi eseguiranno un job Dataflow che genera 40 GB di dati nella tabella, più che sufficienti per l'attivazione di Key Visualizer:
Abilita l'API Cloud Dataflow
gcloud services enable dataflow.googleapis.com
Recupera il codice da GitHub e modificalo nella directory
git clone https://github.com/GoogleCloudPlatform/java-docs-samples.git cd java-docs-samples/bigtable/beam/keyviz-art
Genera i dati (lo script richiede circa 15 minuti)
mvn compile exec:java -Dexec.mainClass=keyviz.LoadData \ "-Dexec.args=--bigtableProjectId=$BIGTABLE_PROJECT \ --bigtableInstanceId=$INSTANCE_ID --runner=dataflow \ --bigtableTableId=$TABLE_ID --project=$GOOGLE_CLOUD_PROJECT"
Monitorare l'importazione
Puoi monitorare il job nell'interfaccia utente di Cloud Dataflow. Inoltre, puoi visualizzare il carico sull'istanza Cloud Bigtable con la relativa UI di monitoraggio.
Nell'interfaccia utente di Dataflow, potrai vedere il grafico del job e le varie metriche del job, inclusi gli elementi elaborati, le vCPU attuali e la velocità effettiva.
Bigtable offre strumenti di monitoraggio standard per le operazioni di lettura/scrittura, lo spazio di archiviazione utilizzato, la percentuale di errori e altro ancora a livello di istanza, cluster e tabella. Inoltre, Bigtable dispone anche di Key Visualizer che suddivide l'utilizzo in base alle chiavi di riga che utilizzeremo una volta generati almeno 30 GB di dati.
5. Scopri: lettura da Bigtable con Dataflow
Nozioni di base sulla lettura
Quando leggi da Cloud Bigtable, devi fornire un oggetto di configurazione CloudBigtableTableScanConfiguration
. È simile a CloudBigtableTableConfiguration
, ma puoi specificare le righe di cui eseguire la scansione e da cui leggere.
Scan scan = new Scan(); scan.setCacheBlocks(false); scan.setFilter(new FirstKeyOnlyFilter()); CloudBigtableScanConfiguration config = new CloudBigtableScanConfiguration.Builder() .withProjectId(options.getBigtableProjectId()) .withInstanceId(options.getBigtableInstanceId()) .withTableId(options.getBigtableTableId()) .withScan(scan) .build();
Quindi utilizzalo per avviare la pipeline:
p.apply(Read.from(CloudBigtableIO.read(config))) .apply(...
Tuttavia, se vuoi eseguire una lettura come parte della pipeline, puoi passare un CloudBigtableTableConfiguration
a un doFn
che estende AbstractCloudBigtableTableDoFn
.
p.apply(GenerateSequence.from(0).to(10)) .apply(ParDo.of(new ReadFromTableFn(bigtableTableConfig, options)));
Quindi chiama super()
con la tua configurazione e getConnection()
per ottenere una connessione distribuita.
public static class ReadFromTableFn extends AbstractCloudBigtableTableDoFn<Long, Void> { public ReadFromTableFn(CloudBigtableConfiguration config, ReadDataOptions readDataOptions) { super(config); } @ProcessElement public void processElement(PipelineOptions po) { Table table = getConnection().getTable(TableName.valueOf(options.getBigtableTableId())); ResultScanner imageData = table.getScanner(scan); } }
Job Dataflow di ReadData
Per questo codelab dovrai leggere la tabella ogni secondo, in modo da poter avviare la pipeline con una sequenza generata che attiva più intervalli di lettura in base all'ora in cui un file CSV inserito è stato inserito.
È necessario un po' di calcolo per determinare quali intervalli di righe analizzare data l'ora, ma puoi fare clic sul nome del file per visualizzare il codice sorgente se vuoi saperne di più.
ReadData.java
p.apply(GenerateSequence.from(0).withRate(1, new Duration(1000))) .apply(ParDo.of(new ReadFromTableFn(bigtableTableConfig, options)));
ReadData.java
public static class ReadFromTableFn extends AbstractCloudBigtableTableDoFn<Long, Void> { List<List<Float>> imageData = new ArrayList<>(); String[] keys; public ReadFromTableFn(CloudBigtableConfiguration config, ReadDataOptions readDataOptions) { super(config); keys = new String[Math.toIntExact(getNumRows(readDataOptions))]; downloadImageData(readDataOptions.getFilePath()); generateRowkeys(getNumRows(readDataOptions)); } @ProcessElement public void processElement(PipelineOptions po) { // Determine which column will be drawn based on runtime of job. long timestampDiff = System.currentTimeMillis() - START_TIME; long minutes = (timestampDiff / 1000) / 60; int timeOffsetIndex = Math.toIntExact(minutes / KEY_VIZ_WINDOW_MINUTES); ReadDataOptions options = po.as(ReadDataOptions.class); long count = 0; List<RowRange> ranges = getRangesForTimeIndex(timeOffsetIndex, getNumRows(options)); if (ranges.size() == 0) { return; } try { // Scan with a filter that will only return the first key from each row. This filter is used // to more efficiently perform row count operations. Filter rangeFilters = new MultiRowRangeFilter(ranges); FilterList firstKeyFilterWithRanges = new FilterList( rangeFilters, new FirstKeyOnlyFilter(), new KeyOnlyFilter()); Scan scan = new Scan() .addFamily(Bytes.toBytes(COLUMN_FAMILY)) .setFilter(firstKeyFilterWithRanges); Table table = getConnection().getTable(TableName.valueOf(options.getBigtableTableId())); ResultScanner imageData = table.getScanner(scan); } catch (Exception e) { System.out.println("Error reading."); e.printStackTrace(); } } /** * Download the image data as a grid of weights and store them in a 2D array. */ private void downloadImageData(String artUrl) { ... } /** * Generates an array with the rowkeys that were loaded into the specified Bigtable. This is * used to create the correct intervals for scanning equal sections of rowkeys. Since Bigtable * sorts keys lexicographically if we just used standard intervals, each section would have * different sizes. */ private void generateRowkeys(long maxInput) { ... } /** * Get the ranges to scan for the given time index. */ private List<RowRange> getRangesForTimeIndex(@Element Integer timeOffsetIndex, long maxInput) { ... } }
6. Crea il tuo capolavoro
Ora che sai come caricare i dati in Bigtable e leggerli con Dataflow, puoi eseguire il comando finale che genererà un'immagine della Gioconda in 8 ore.
mvn compile exec:java -Dexec.mainClass=keyviz.ReadData \ "-Dexec.args=--bigtableProjectId=$BIGTABLE_PROJECT \ --bigtableInstanceId=$INSTANCE_ID --runner=dataflow \ --bigtableTableId=$TABLE_ID --project=$GOOGLE_CLOUD_PROJECT"
Puoi utilizzare un bucket con immagini esistenti. In alternativa, puoi creare un file di input da una qualsiasi delle tue immagini con questo strumento e quindi caricarlo in un bucket GCS pubblico.
I nomi file sono creati a partire da gs://keyviz-art/[painting]_[hours]h.txt
esempio: gs://keyviz-art/american_gothic_4h.txt
opzioni per il disegno:
- american_gothic
- mona_lisa
- pearl_earring
- persistence_of_memory
- starry_night
- sunday_afternoon
- the_scream
opzioni di ora: 1, 4, 8, 12, 24, 48, 72, 96, 120, 144
Rendi pubblico il bucket o il file GCS assegnando a allUsers
il ruolo Storage Object Viewer
.
Dopo aver scelto l'immagine, modifica il parametro --file-path
in questo comando:
mvn compile exec:java -Dexec.mainClass=keyviz.ReadData \ "-Dexec.args=--bigtableProjectId=$BIGTABLE_PROJECT \ --bigtableInstanceId=$INSTANCE_ID --runner=dataflow \ --bigtableTableId=$TABLE_ID --project=$GOOGLE_CLOUD_PROJECT \ --filePath=gs://keyviz-art/american_gothic_4h.txt"
7. Controlla più tardi
Potrebbero essere necessarie alcune ore perché l'immagine completa diventi realtà, ma dopo 30 minuti dovresti iniziare a vedere l'attività nel visualizzatore chiave. Puoi utilizzare diversi parametri: zoom, luminosità e metrica. Puoi eseguire lo zoom utilizzando la rotellina del mouse o trascinando un rettangolo sulla griglia del visualizzatore dei tasti.
La luminosità modifica il ridimensionamento dell'immagine, il che è utile per vedere più da vicino una zona molto calda.
Puoi anche modificare la metrica da visualizzare. Ci sono OP, client di lettura byte, client byte scritti per citarne alcuni. "Leggi byte client" sembra produrre immagini fluide mentre "Ops" produce immagini con più linee che possono risultare molto interessanti su alcune immagini.
8. Completa la configurazione
Eseguire la pulizia per evitare addebiti
Per evitare che al tuo account Google Cloud Platform vengano addebitati costi relativi alle risorse utilizzate in questo codelab, devi eliminare la tua istanza.
gcloud bigtable instances delete $INSTANCE_ID
Argomenti trattati
- Scrittura su Bigtable con Dataflow
- Lettura da Bigtable con Dataflow (all'inizio della pipeline, al centro della pipeline)
- Utilizzo degli strumenti di monitoraggio di Dataflow
- Utilizzo degli strumenti di monitoraggio di Bigtable, tra cui Key Visualizer
Passaggi successivi
- Scopri di più su come è stata creata la grafica Key Visualizer.
- Scopri di più su Cloud Bigtable nella documentazione.
- Prova le altre funzioni di Google Cloud Platform. Dai un'occhiata ai nostri tutorial.