Remote API untuk layanan paket lama

Java SDK dilengkapi dengan library bernama Remote API yang memungkinkan Anda untuk mengakses layanan App Engine secara transparan dari aplikasi Java apa pun. Misalnya, Anda dapat menggunakan Remote API untuk mengakses datastore produksi dari aplikasi yang berjalan di komputer lokal. Anda juga dapat menggunakan Remote API untuk mengakses datastore satu aplikasi App Engine dari aplikasi App Engine lain.

Mengonfigurasi Remote API di Server

Komponen server Remote API adalah Java servlet yang merupakan bagian dari runtime App Engine untuk Java. Servlet ini menerima permintaan dari klien Remote API, mengirimkannya ke layanan backend yang sesuai, lalu menampilkan hasil panggilan layanan ke klien tersebut. Untuk menginstal servlet Remote API, tambahkan kode berikut ke web.xml Anda:

<servlet>
  <display-name>Remote API Servlet</display-name>
  <servlet-name>RemoteApiServlet</servlet-name>
  <servlet-class>com.google.apphosting.utils.remoteapi.RemoteApiServlet</servlet-class>
  <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
  <servlet-name>RemoteApiServlet</servlet-name>
  <url-pattern>/remote_api</url-pattern>
</servlet-mapping>

Servlet akan menampilkan error jika tidak ada pengguna yang diautentikasi atau pengguna yang diautentikasi bukan admin aplikasi Anda, sehingga tidak perlu mengonfigurasi keamanan tambahan. Setelah Anda men-deploy aplikasi dengan setelan ini, aplikasi apa pun yang menginstal klien Remote API dapat menggunakan layanannya. Ini termasuk klien Python yang menggunakan Python Remote API.

Mengonfigurasi Remote API pada Klien Mandiri

Untuk mengonfigurasi komponen klien Remote API agar dapat digunakan di dalam aplikasi Java, tambahkan ${SDK_ROOT}/lib/impl/appengine-api.jar dan ${SDK_ROOT}/lib/appengine-remote-api.jar ke classpath Anda. Kemudian, konfigurasikan dan instal Remote API pada kode Anda:

import com.google.appengine.tools.remoteapi.RemoteApiInstaller;
import com.google.appengine.tools.remoteapi.RemoteApiOptions;

// ...
RemoteApiOptions options = new RemoteApiOptions()
    .server("[APP_ID].[REGION_ID].r.appspot.com", 443)
    .useApplicationDefaultCredential();

RemoteApiInstaller installer = new RemoteApiInstaller();
installer.install(options);
// ... all API calls executed remotely
installer.uninstall();

Klien Remote API akan mengandalkan Kredensial Default Aplikasi yang menggunakan OAuth 2.0.

Untuk menjalankan kredensial:

gcloud auth application-default login

Anda dapat dengan mudah terhubung ke aplikasi App Engine yang berjalan secara lokal di Server Pengembangan:

RemoteApiOptions options = new RemoteApiOptions()
    .server("localhost", 8888) // server name must equal "localhost"
    .useDevelopmentServerCredential();

Berikut adalah aplikasi Java lengkap yang akan memasukkan Entity ke dalam datastore saat dijalankan:

public class RemoteApiExample {

  public static void main(String[] args) throws IOException {
    String serverString = args[0];
    RemoteApiOptions options;
    if (serverString.equals("localhost")) {
      options = new RemoteApiOptions().server(serverString,
        8080).useDevelopmentServerCredential();
    } else {
      options = new RemoteApiOptions().server(serverString,
        443).useApplicationDefaultCredential();
    }
    RemoteApiInstaller installer = new RemoteApiInstaller();
    installer.install(options);
    try {
      DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
      System.out.println("Key of new entity is " + ds.put(new Entity("Hello Remote API!")));
    } finally {
      installer.uninstall();
    }
  }
}

Mengonfigurasi Remote API pada Klien App Engine

Anda juga dapat menggunakan Remote API untuk mengakses layanan satu aplikasi App Engine dari aplikasi App Engine yang berbeda. Anda perlu menambahkan ${SDK_ROOT}/lib/appengine-remote-api.jar ke direktori WEB-INF/lib. Kemudian, di aplikasi App Engine klien, konfigurasi dan instal Remote API seperti yang Anda lakukan di klien Java mandiri.

Perhatikan bahwa RemoteApiInstaller hanya menginstal Remote API di thread yang melakukan penginstalan, jadi berhati-hatilah untuk tidak membagikan instance class ini ke semua thread.

Menggunakan Remote API dengan Maven

Untuk menggunakan fitur Remote API di project Maven, tambahkan dependensi berikut ke file pom.xml project Anda:

<dependency>
  <groupId>com.google.appengine</groupId>
  <artifactId>appengine-remote-api</artifactId>
  <version>1.9.64</version>
</dependency>
<dependency>
  <groupId>com.google.appengine</groupId>
  <artifactId>appengine-api-1.0-sdk</artifactId>
  <version>1.9.64</version>
</dependency>

Batasan dan praktik terbaik

Modul remote_api secara optimal dirancang untuk sedapat mungkin, berperilaku sama persis dengan datastore App Engine native. Dalam beberapa kasus, ini berarti melakukan hal-hal yang kurang efisien dibandingkan yang seharusnya. Saat menggunakan remote_api, berikut beberapa hal yang perlu diingat:

Setiap permintaan datastore memerlukan proses dua arah

Karena Anda mengakses datastore melalui HTTP, terdapat sedikit lebih banyak overhead dan latensi dibandingkan ketika Anda mengaksesnya secara lokal. Untuk mempercepat dan mengurangi beban, coba batasi jumlah perjalanan dua arah yang Anda lakukan dengan mengelompokkan get dan put, serta mengambil batch entity dari kueri. Ini merupakan saran yang bagus tidak hanya untuk remote_api, tetapi juga untuk menggunakan datastore secara umum, karena operasi batch hanya dianggap sebagai operasi Datastore tunggal.

Permintaan ke remote_api menggunakan kuota

Karena remote_api beroperasi melalui HTTP, setiap panggilan datastore yang Anda lakukan akan menyebabkan penggunaan kuota untuk permintaan HTTP, byte masuk dan keluar, serta kuota datastore biasa. Ingatlah hal ini jika Anda menggunakan remote_api untuk melakukan update massal.

Batas API sebesar 1 MB berlaku

Seperti saat berjalan secara native, batas 1 MB untuk permintaan dan respons API masih berlaku. Jika entity Anda sangat besar, Anda mungkin perlu membatasi jumlah yang Anda ambil atau tempatkan pada satu waktu agar tetap di bawah batas ini. Sayangnya, hal ini bertentangan dengan meminimalkan perjalanan dua arah. Oleh karena itu, saran terbaiknya adalah menggunakan batch terbesar yang Anda bisa tanpa melampaui batasan ukuran permintaan atau respons. Namun, bagi sebagian besar entity, hal ini mungkin tidak menjadi masalah.

Hindari melakukan iterasi pada kueri

Saat Anda melakukan iterasi pada kueri, SDK akan mengambil entity dari datastore dalam batch berisi 20, dengan mengambil batch baru setiap kali SDK menggunakan batch yang sudah ada. Karena setiap batch harus diambil dalam permintaan terpisah oleh remote_api, metode ini tidak dapat dlakukan secara efisien. Sebagai gantinya, remote_api mengeksekusi kueri yang benar-benar baru untuk setiap batch, menggunakan fungsi offset untuk mendapatkan hasil lebih lanjut.

Jika mengetahui jumlah entity yang diperlukan, Anda dapat melakukan seluruh pengambilan dalam satu permintaan dengan meminta jumlah yang diperlukan.

Jika tidak mengetahui jumlah entity yang diinginkan, Anda dapat menggunakan kursor untuk melakukan iterasi secara efisien pada kumpulan hasil yang besar. Hal ini juga memungkinkan Anda menghindari batas 1000 entity yang diberlakukan pada kueri datastore normal.

Transaksi kurang efisien

Untuk mengimplementasikan transaksi melalui remote_api, metode ini mengumpulkan informasi tentang entity yang diambil di dalam transaksi, bersama dengan salinan entity yang ditempatkan atau dihapus di dalam transaksi. Ketika transaksi melalui proses commitment, semua informasi ini akan dikirimkan ke server App Engine, di mana transaksi harus mengambil kembali semua entity yang digunakan dalam transaksi, memverifikasi bahwa entity tersebut belum dimodifikasi, kemudian menempatkan dan menghapus semua perubahan transaksi dan melakukan commitment pada transaksi. Jika terjadi konflik, server akan melakukan roll back transaksi dan memberi tahu klien, kemudian harus mengulangi prosesnya dari awal.

Pendekatan ini berfungsi dengan baik, dan menduplikasi fungsi yang dihasilkan oleh transaksi di datastore lokal, tetapi tidak efisien. Artinya, gunakan transaksi jika diperlukan, tetapi coba batasi jumlah dan kompleksitas transaksi yang Anda jalankan demi efisiensi.