使用Java的Google Datastore Emulator(不使用GAE)

我正在使用Google Cloud的Java数据存储客户端库访问云数据存储区。

注意 :我没有使用App Engine来部署我的应用程序; 只是为了开发目的运行本地应用程序。

在示例之后,我可以读/写Cloud Datastore。

Datastore datastore = DatastoreOptions.defaultInstance().service(); KeyFactory keyFactory = datastore.newKeyFactory().setKind("MyKind"); Key key = keyFactory.newKey(); Entity entity = datastore.get(key); 

我希望能够写入本地数据存储模拟器实例。 按照这里的指南,我运行gcloud beta emulators datastore start 。 这显示在我的终端中:

 C:\Users\User>gcloud beta emulators datastore start WARNING: Reusing existing data in [C:\Users\User\AppData\Roaming\gcloud\emulators\datastore]. Executing: cmd /c C:\Users\User\AppData\Local\Google\Cloud SDK\google-cloud-sdk\platform\cloud-datastore-emulator\cloud_datastore_emulator.cmd start --host=localhost --port=8964 --store_on_disk=True --consistency=0.9 --allow_remote_shutdown C:\Users\User\AppData\Roaming\gcloud\emulators\datastore [datastore] Oct 31, 2016 11:37:27 AM com.google.cloud.datastore.emulator.CloudDatastore$FakeDatastoreAction$7 apply [datastore] INFO: Provided --allow_remote_shutdown to start command which is no longer necessary. [datastore] Oct 31, 2016 11:37:27 AM com.google.cloud.datastore.emulator.impl.LocalDatastoreFileStub  [datastore] INFO: Local Datastore initialized: [datastore] Type: High Replication [datastore] Storage: C:\Users\User\AppData\Roaming\gcloud\emulators\datastore\WEB-INF\appengine-generated\local_db.bin [datastore] Oct 31, 2016 11:37:28 AM io.grpc.internal.ManagedChannelImpl  [datastore] INFO: [ManagedChannelImpl@5e955596] Created with target localhost:8964 [datastore] Oct 31, 2016 11:37:28 AM com.google.cloud.datastore.emulator.impl.LocalDatastoreFileStub load [datastore] INFO: The backing store, C:\Users\User\AppData\Roaming\gcloud\emulators\datastore\WEB-INF\appengine-generated\local_db.bin, does not exist. It will be created. [datastore] Oct 31, 2016 11:37:28 AM io.gapi.emulators.netty.NettyUtil applyJava7LongHostnameWorkaround [datastore] INFO: Unable to apply Java 7 long hostname workaround. [datastore] API endpoint: http://localhost:8964 [datastore] If you are using a library that supports the DATASTORE_EMULATOR_HOST environment variable, run: [datastore] [datastore] export DATASTORE_EMULATOR_HOST=localhost:8964 [datastore] [datastore] Dev App Server is now running. [datastore] 

我打开另一个终端并设置环境变量:

 C:\Users\User>gcloud beta emulators datastore env-init > set_vars.cmd && set_vars.cmd C:\Users\User>set DATASTORE_DATASET=my-project-id C:\Users\User>set DATASTORE_EMULATOR_HOST=localhost:8964 C:\Users\User>set DATASTORE_EMULATOR_HOST_PATH=localhost:8964/datastore C:\Users\User>set DATASTORE_HOST=http://localhost:8964 C:\Users\User>set DATASTORE_PROJECT_ID=my-project-id 

我运行我的应用程序并进行REST调用以发布或检索实体,但这只是对云数据存储区进行读/写操作。 前往localhost:8964/datastore给我Not Found 。 虽然启动模拟器告诉我它创建了local_db.bin文件,但据说包含它的文件夹是空的。 我还想远离使用LocalDatastoreHelper来访问本地模拟器。 有没有办法实现只使用gcloud?

下面的行始终连接到远程数据存储区。 使用gcloud设置中的默认选项(例如,项目,身份validation凭据)。

 Datastore datastore = DatastoreOptions.defaultInstance().service(); 

要连接到本地数据存储区,请尝试以下操作:

@Test public void test1() throws IOException, InterruptedException { Datastore ds = DatastoreOptions.builder().host("http://localhost:9999").projectId("my-project").build().service(); com.google.cloud.datastore.Key key = ds.newKeyFactory().kind("MyEntity").newKey("mykey"); com.google.cloud.datastore.Entity entity = com.google.cloud.datastore.Entity.builder(key).set("p1", "Hello World!").build(); entity = ds.put(entity); entity = ds.get(key); System.out.println(entity); }

我在localhost:9999上启动了我的数据存储模拟器。 在构建DatastoreOptions时将其设置为主机。

我已经确认模拟器控制台显示已收到请求并且实体已持久存在。 我还检查了数据文件(local_db.bin)并显示了数据(当然它不是纯文本文件)。

我不知道的一件事是 – 如果有办法使用浏览器界面管理本地数据存储区。 我找不到关于如何管理本地数据存储的文档,就像我们如何从云控制台执行远程数据存储一样。 也许其他人可以帮助解决这个问题。

我假设您要针对数据存储模拟器进行测试。 在这种情况下,没有必要从shell启动数据存储模拟器。 gcloud库中有一个LocalDatastoreHelper ,允许您轻松创建,启动,重置和停止本地数据存储模拟器。

我没有找到任何相关文档,因此我为您创建了这个测试用例:

 import com.google.cloud.datastore.Datastore; import com.google.cloud.datastore.DatastoreOptions; import com.google.cloud.datastore.Entity; import com.google.cloud.datastore.KeyFactory; import com.google.cloud.datastore.testing.LocalDatastoreHelper; import org.junit.*; import java.io.IOException; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; /** * This testcase demonstrate the use of the datastore emulator in JUnit test cases. * * from @link https://www.kontaktlinsen-preisvergleich.de */ public class DatastoreEmulatorTest { protected static LocalDatastoreHelper localDatastoreHelper; protected Datastore datastore; protected KeyFactory keyFactory; @BeforeClass public static void setUpClass() throws InterruptedException, IOException { // create and start a local datastore emulator on a random free port // this also means that you probably can run tests like this concurrently. System.out.println("[Datastore-Emulator] start"); localDatastoreHelper = LocalDatastoreHelper.create(); localDatastoreHelper.start(); System.out.println("[Datastore-Emulator] listening on port: " + localDatastoreHelper.getPort()); // set the system property to tell the gcloud lib to use the datastore emulator System.setProperty("DATASTORE_EMULATOR_HOST","localhost:" + localDatastoreHelper.getPort()); } @Before public void setUp() { // create the datastore instance // because of the system property set it in setUpClass() this // datastore will be connected with the datastore emulator. datastore = DatastoreOptions.getDefaultInstance().getService(); keyFactory = datastore.newKeyFactory().setKind("TestEntity"); } @After public void tearDown() throws IOException { System.out.println("[Datastore-Emulator] reset"); // this resets the datastore after every test localDatastoreHelper.reset(); } @AfterClass public static void tearDownClass() throws InterruptedException, IOException { System.out.println("[Datastore-Emulator] stop"); // this stops the datastore emulator after all tests are done localDatastoreHelper.stop(); } @Test public void test1() { // stores an entity in the datastore and retrieves it later // create an Entity "TestEntity" Entity.Builder builder = Entity.newBuilder(keyFactory.newKey(42)); builder.set("name", "Test1"); // store it in datastore datastore.put(builder.build()); // retrieve entity by key Entity entity = datastore.get(keyFactory.newKey(42)); assertNotNull(entity); assertEquals("Test1", entity.getString("name")); } @Test public void test2() { // try to access the entity created in test1, shouldn't work because // of calling reset in tearDown() after each test. // try to retrieve entity by key Entity entity = datastore.get(keyFactory.newKey(42)); assertNull(entity); } } 

LocalDatastoreHelper在空闲端口上创建数据存储模拟器实例并且不存储到磁盘 – 当您使用调试器停止测试用例并查找进程时,您将找到如下内容:

 $ ps ax | grep CloudDatastore 2614 ?? R 0:01.39 /usr/bin/java -cp /Users/marco/google-cloud-sdk/platform/cloud-datastore-emulator/CloudDatastore.jar com.google.cloud.datastore.emulator.CloudDatastore /Users/marco/google-cloud-sdk/platform/cloud-datastore-emulator/cloud_datastore_emulator start --host=localhost --port=57640 --store_on_disk=False --consistency=0.9 --allow_remote_shutdown /var/folders/ky/c126qk_161159ltyrbpdxv8w0000gn/T/gcd2141205756617995044 

这也意味着你也应该能够并行运行测试。