Cloud Spanner エミュレータを使ってみる。

## はじめに

この記事は、
　[Get started with Cloud Spanner
](https://www.youtube.com/watch?v=rG3n3YHNZIQ)という動画を参考に、『実際にやってみた』という記事になります。


## この記事で実施する事。  
- `Cloud Spanner エミュレータ` とは
- エミュレータをインストールして実行する準備を行う。
- `エミュレータ` で gcloud CLI を使用する。
- Java で `Spanner エミュレータ` を使用する。
- `Spanner` インスタンスを作成。
- `Spanner` データベースを作成。
- 書き込み、読み取り、SQL クエリの実行を行う。


## Cloud Spanner エミュレータ とは
`エミュレータ` を使用することで、`Spanner` 機能を
模倣した開発環境をローカルマシン上に作成できます。

これを使用することで、ユーザーは 
Google Cloud プロジェクトや
請求先アカウントを作成することなく、
無料でアプリケーションの開発とテストができる。

ただし、`エミュレータ` はメモリにのみ
データを格納する為、再起動すると、
データ、スキーマ、構成など、
すべての状態が失われます。

この`エミュレータ` は `Spanner` の本番環境サービスと
同じ API を提供し、本番環境へのデプロイではなく、
ローカルでの開発とテストを目的として作られている。


## エミュレータをインストールして実行する準備を行う。
https://cloud.google.com/spanner/docs/emulator?utm_source=youtube&utm_medium=unpaidsoc&utm_campaign=CDR_ret_gke_rg3n3yhnziq_CloudSpanner_040422&utm_content=description&hl=ja

エミュレータを実行するための手順は、
2つの異なる方が示されており、
今回は `Docker` を使用します。

Dockerを起動した状態で、下記のコマンドを実行。

最新のDockerの `エミュレータ` イメージを取得。
```
docker pull gcr.io/cloud-spanner-emulator/emulator
```

Dockerがない場合は、Dockerのインストールを行なってください。

Emulator を起動。
```
docker run -p 9010:9010 -p 9020:9020 gcr.io/cloud-spanner-emulator/emulator
```

エミュレーターが `Docker` 上で起動されますと、下記のように表示されます。
![spanner_emulator_003.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952807/a422af28-0815-f414-d833-d9ac643e7516.png)

次に、実行中のコマンドを一度、手動で停止して、
Docker上のコンテナを手動で再起動させてください。

Macの `iTerm` などで、コマンドを実行すると、
次のコマンドが実行できない状態にあると思います。
![spanner_emulator_014.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952807/0d050e61-b910-9ca4-224f-56565d1131cc.png)

その場合は、実行中のコマンドを一度、手動で停止させてください。

この時、一緒にDocker側も停止しますが、
こちらは再度手動で再起動が可能となります。

停止状態のDockerコンテナを再起動させてください。
![spanner_emulator_005.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952807/57d879ce-9226-707d-7c87-dbcdcca3277a.png)

なお、この手順は、直接Docker上で停止と再起動を行うこともできます。


## エミュレータ で gcloud CLI を使用する。
エミュレータを gcloud で使用するには、
認証を無効にしてエンドポイントを
オーバーライドする必要があります。

エミュレータと本番環境サービスを
すばやく切り替えることができるように、
別の [gcloud 構成](https://cloud.google.com/sdk/docs/configurations?hl=ja) を作成することが推奨されています。

gcloud構成を作成する前に、現在の Google Cloud CLI
 (gcloud) の設定状態を確認してください。
下記のコマンドで確認ができます。

```
gcloud config list
```

このコマンドでは、現在アクティブな状態の
アカウント、プロジェクト、
その他の重要な設定情報を確認できます。

![spanner_emulator_006.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952807/f1b846a2-da4f-16fd-1913-d8713a79c33b.png)


`emulator` という名前の構成ファイルを作成。
```
gcloud config configurations create emulator
```

認証情報の使用を無効にする。
```
gcloud config set auth/disable_credentials true
```

アカウントを設定。
`YOUR_ACCOUNT` を個人のアカウントに書き換えてください。
```
gcloud config set account YOUR_ACCOUNT
```

プロジェクトを設定。
エミュレータは検証しない為、指定するプロジェクトは、
Google Cloud プロジェクトである必要はありません。

ただし、これはアプリケーションが、
SpannerのJavaライブラリを使用するために必要です。
```
gcloud config set project YOUR-PROJECT-ID
```

Google Cloud Spanner APIのエンドポイントを
ローカルのアドレス（`http://localhost:9020/`）にオーバーライドする。
```
gcloud config set api_endpoint_overrides/spanner http://localhost:9020/
```
 
構成が完了すると、gcloud コマンドが本番環境サービスではなく
エミュレータに送信されるようになります。

`SPANNER_EMULATOR_HOST` 環境変数を設定する

```
export SPANNER_EMULATOR_HOST=localhost:9010
```

`Spannerエミュレータ` は、`Google Cloud Spanner` の
ローカル開発およびテスト用に使用されるものであり、
実際のクラウドサービスとは異なります。

このエミュレータを使用する際、アプリケーションは
エミュレータのホストとポートに接続する必要があります。

`SPANNER_EMULATOR_HOST`環境変数を設定することで、
アプリケーションはエミュレータを正しく参照できます。


## Java で Spanner エミュレータ を使用する。
https://cloud.google.com/spanner/docs/getting-started/java?hl=ja

今回はクイックスタート内の目標とされている以下を行います。
- Spanner インスタンスとデータベースを作成。
- データベースのデータに対し書き込み、
読み取り、SQL クエリの実行を行う。

[https://github.com/googleapis/java-spanner](https://github.com/googleapis/java-spanner/tree/main/samples/snippets) を、git clone してください。

```
git clone https://github.com/googleapis/java-spanner.git
```

git cloneの実行が完了したら、cdコマンドを使って、対象のディレクトリ階層へ移動。

```
cd java-spanner/samples/snippets
```


## Spanner インスタンスを作成。
Spannerを使用する時、`インスタンス` の準備が必要になります。

`インスタンス` とは、`Spanner` データベースによって
使用されるリソースを割り当て、管理する為の環境を指します。

今回は、エミュレータを使用する為、
インスタンス構成は、 `--config=emulator-config` を入力してください。

```
gcloud spanner instances create test-instance \
   --config=emulator-config --description="Test Instance" --nodes=1
```

![spanner_emulator_007.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952807/f464d69c-ab17-f659-eaa9-e0429f0af6cd.png)

インスタンスが作成されたかは、下記のコマンドで確認できます。
```
gcloud spanner instances list
```

Java用の `Google Cloud Spanner` クライアントライブラリを
含むプロジェクトをビルドし、実行可能な `JARファイル` を作成します。

```
mvn package
```

`mvn` コマンドが実行されない場合は、
`maven` がインストールされていない場合があります。

下記のブログでインストール手順を確認してください。

https://qiita.com/toranoko92114/items/0ce47d3a63147ce3df00


## Spanner データベースを作成。

`test-instance` というインスタンスに `example-db` というデータベースを作成。

```
java -jar target/spanner-snippets/spanner-google-cloud-samples.jar \
createdatabase test-instance example-db
```

![spanner_emulator_008.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952807/8103914a-f60f-d4e8-83e4-82d6d4c738fe.png)

作成されたデータベースを確認。

```
gcloud spanner databases list --instance=test-instance
```

![spanner_emulator_009.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952807/3067ac12-98e3-f390-95c5-e098af7de90a.png)

作成されたデータベースでは、DDL（Data Definition Language）が
含まれており、これにより、データベース内のテーブル、インデックス、
その他のスキーマオブジェクトに関する定義を確認することができます。

データベース内のDDLを確認
```
gcloud spanner databases ddl describe example-db --instance=test-instance
```

![spanner_emulator_010.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952807/3e6a65cf-a423-26f3-e37f-b72975149b96.png)


## 書き込み、読み取り、SQL クエリの実行を行う。
Spanner とのすべてのやり取りは [DatabaseClient](https://github.com/googleapis/java-spanner/blob/HEAD/samples/snippets/src/main/java/com/example/spanner/SpannerSample.java#L2193) を経由する必要があり、
通常はアプリケーション開始時に DatabaseClient を作成しなければなりません。

これにより、読み取り、書き込み、トランザクションの実行が可能となります。

データベースクライアントを作成した後は、
`データ操作言語（DML）` もしくは `ミューテーション` を
使用することで、データの書き込みが可能となります。

データ操作言語（DML）を使用してデータを書き込み。
[writeusingdml](https://github.com/googleapis/java-spanner/blob/HEAD/samples/snippets/src/main/java/com/example/spanner/SpannerSample.java#L1118) 引数を使用してサンプルを実行。

```
java -jar target/spanner-snippets/spanner-google-cloud-samples.jar \
    writeusingdml test-instance example-db
```

![spanner_emulator_011.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952807/d68ee5b6-c6e0-6bf0-5168-97bb6201cd2d.png)

データ操作言語（DML）を使用して、書き込んだデータを読み取り。

```
gcloud spanner databases execute-sql example-db --instance=test-instance \
    --sql='SELECT SingerId, FirstName, LastName FROM Singers'
```

![spanner_emulator_012.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952807/61d1212f-474f-774c-a8ed-3df5da5e3d5f.png)

ミューテーションを使用してデータを書き込み。
[write](https://github.com/googleapis/java-spanner/blob/HEAD/samples/snippets/src/main/java/com/example/spanner/SpannerSample.java#L189) 引数を使用してサンプルを実行。

```
java -jar target/spanner-snippets/spanner-google-cloud-samples.jar \
    write test-instance example-db
```

![spanner_emulator_015.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952807/8d4f060d-a736-e4a2-03f6-8462a323e827.png)

ミューテーションを使用して、書き込んだデータを読み取り。

```
gcloud spanner databases execute-sql example-db --instance=test-instance \
    --sql='SELECT SingerId, AlbumId, AlbumTitle FROM Albums'
```

![spanner_emulator_013.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952807/893130c4-215f-cd90-f0b0-4f64d68f4815.png)


## 終わりに
今回の記事は、動画を視聴しまして、
実際に『手を動かしてみた』という内容でまとめました。

`Cloud Spanner` について学習するにあたって、
ローカルでその環境を実装できるエミュレータは、
すごく便利であり、そのままCloud環境へ
移行できるメリットが含まれます。

コストをかけずに、まずはローカルで、
`Cloud Spanner` を試してみたいと考えていましたら、
この記事を参考にしていただけると幸いです。

あとで『じっくり読みたい』、『繰り返し読みたい』と
思ってくれましたら、『`ストック`』へ登録、
この記事が読まれている方にとって、
参考になる記事となりましたら、『`いいね`』を
付けていただけますと、励みになりますので、
よろしくお願いします。