Cara Menangani Permintaan

ID region

REGION_ID adalah kode singkat yang ditetapkan Google berdasarkan region yang Anda pilih saat membuat aplikasi. Kode ini tidak sesuai dengan negara atau provinsi, meskipun beberapa ID region mungkin tampak mirip dengan kode negara dan provinsi yang umum digunakan. Untuk aplikasi yang dibuat setelah Februari 2020, REGION_ID.r disertakan dalam URL App Engine. Untuk aplikasi lama yang dibuat sebelum tanggal tersebut, ID region bersifat opsional dalam URL.

Pelajari ID region lebih lanjut.

Dokumen ini menjelaskan cara aplikasi App Engine Anda menerima permintaan dan mengirim respons.

Untuk mengetahui detail selengkapnya, lihat Referensi Header dan Respons Permintaan.

Jika aplikasi Anda menggunakan layanan, Anda dapat mengajukan permintaan ke layanan tertentu atau versi tertentu dari layanan tersebut. Untuk mengetahui informasi selengkapnya tentang cara respons layanan, lihat Cara Permintaan Dirutekan.

Menangani permintaan

Aplikasi Anda bertanggung jawab memulai server web dan menangani permintaan. Anda dapat menggunakan framework web apa pun yang tersedia untuk bahasa pengembangan Anda.

Saat menerima permintaan web untuk aplikasi Anda, App Engine akan memanggil servlet yang sesuai dengan URL, seperti yang dijelaskan dalam file web.xml aplikasi di direktori WEB-INF/ ini. Alat ini mendukung spesifikasi Java Servlet API 2.5 atau 3.1, untuk memberikan data permintaan ke servlet dan menerima data respons.

App Engine menjalankan beberapa instance aplikasi Anda, setiap instance memiliki server webnya sendiri untuk menangani permintaan. Setiap permintaan dapat dirutekan ke instance mana pun, sehingga permintaan berturut-turut dari pengguna yang sama belum tentu dikirim ke instance yang sama. Jumlah instance dapat disesuaikan secara otomatis saat traffic berubah.

Secara default, setiap server web hanya memproses satu permintaan dalam satu waktu. Untuk mengirim beberapa permintaan ke setiap server web secara paralel, tandai aplikasi Anda sebagai threadsafe dengan menambahkan elemen <threadsafe>true</threadsafe> ke file appengine-web.xml.

Contoh class servlet berikut menampilkan pesan sederhana di browser pengguna.

// With @WebServlet annotation the webapp/WEB-INF/web.xml is no longer required.
@WebServlet(name = "requests", description = "Requests: Trivial request", urlPatterns = "/requests")
public class RequestsServlet extends HttpServlet {

  @Override
  public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
    resp.setContentType("text/plain");
    resp.getWriter().println("Hello, world");
  }
}

Kuota dan batas

App Engine otomatis mengalokasikan resource ke aplikasi Anda saat traffic meningkat. Namun, ini terikat oleh pembatasan berikut:

  • App Engine mencadangkan kapasitas penskalaan otomatis untuk aplikasi dengan latensi rendah, saat aplikasi merespons permintaan dalam waktu kurang dari satu detik.

  • Aplikasi yang sangat terikat dengan CPU juga dapat menimbulkan beberapa latensi tambahan untuk berbagi resource secara efisien dengan aplikasi lain di server yang sama. Permintaan untuk file statis dikecualikan dari batas latensi ini.

Setiap permintaan yang masuk ke aplikasi akan dihitung dalam batas Permintaan. Data yang dikirim sebagai respons terhadap permintaan akan dihitung dalam batas Bandwidth Keluar (dapat ditagih).

Permintaan HTTP dan HTTPS (aman) diperhitungkan dalam batas Permintaan, Bandwidth Masuk (dapat ditagih), dan Bandwidth Keluar (dapat ditagih). Halaman Detail Kuota konsol Google Cloud juga melaporkan Permintaan Aman, Bandwidth Masuk Aman, dan Bandwidth Keluar Aman sebagai nilai terpisah untuk tujuan informasi. Hanya permintaan HTTPS yang diperhitungkan dalam nilai ini. Untuk mengetahui informasi selengkapnya, lihat halaman Kuota.

Batas berikut berlaku khusus untuk penggunaan pengendali permintaan:

Batas Jumlah
Ukuran permintaan 32 megabyte
Ukuran respons 32 megabyte
Waktu tunggu permintaan Tergantung jenis penskalaan yang digunakan aplikasi Anda
Jumlah total maksimum file (file aplikasi dan file statis) Total 10.000
1.000 per direktori
Ukuran maksimum file aplikasi 32 megabyte
Ukuran maksimum file statis 32 megabyte
Ukuran total maksimum untuk semua file aplikasi dan file statis Gratis 1 gigabyte pertama
$ 0,026 per gigabyte per bulan setelah 1 gigabyte pertama
Waktu tunggu permintaan tertunda 10 detik
Ukuran maksimum satu kolom header permintaan 8 kilobyte untuk runtime generasi kedua di lingkungan standar. Permintaan ke runtime ini dengan kolom header yang melebihi 8 kilobyte akan menampilkan error HTTP 400.

Batas permintaan

Semua permintaan HTTP/2 akan diterjemahkan menjadi permintaan HTTP/1.1 saat diteruskan ke server aplikasi.

Batas respons

  • Respons dinamis dibatasi hingga 32 MB. Jika pengendali skrip menghasilkan respons yang lebih besar dari batas ini, server akan mengirim kembali respons kosong dengan kode status Error Server Internal 500. Batasan ini tidak berlaku untuk respons yang menyalurkan data dari Blobstore lama atau Cloud Storage.

  • Batas header respons adalah 8 KB untuk runtime generasi kedua. Header respons yang melebihi batas ini akan menampilkan error HTTP 502, dengan log yang menampilkan upstream sent too big header while reading response header from upstream.

Header permintaan

Permintaan HTTP masuk menyertakan header HTTP yang dikirim oleh klien. Untuk tujuan keamanan, beberapa header dibersihkan atau diubah oleh proxy perantara sebelum mencapai aplikasi.

Untuk mengetahui informasi selengkapnya, lihat Referensi header permintaan.

Menangani waktu tunggu permintaan

App Engine dioptimalkan untuk aplikasi dengan permintaan berumur pendek, biasanya yang memerlukan waktu beberapa ratus milidetik. Aplikasi yang efisien akan merespons sebagian besar permintaan dengan cepat. Aplikasi yang tidak diskalakan dengan baik dengan infrastruktur App Engine. Untuk memastikan tingkat performa ini, ada waktu tunggu permintaan maksimum yang diberlakukan oleh sistem yang harus direspons oleh setiap aplikasi.

Jika aplikasi Anda melebihi batas waktu ini, App Engine akan menginterupsi pengendali permintaan. Lingkungan runtime Java mengganggu servlet dengan menampilkan com.google.apphosting.api.DeadlineExceededException. Jika tidak ada pengendali permintaan untuk menangkap pengecualian ini, lingkungan runtime akan menampilkan error server HTTP 500 ke klien.

Jika ada pengendali permintaan dan DeadlineExceededException tersebut tertangkap, lingkungan runtime akan memberikan waktu kepada pengendali permintaan (kurang dari satu detik) untuk menyiapkan respons kustom. Jika pengendali permintaan memerlukan waktu lebih dari satu detik setelah menaikkan pengecualian untuk menyiapkan respons kustom, HardDeadlineExceededError akan ditampilkan.

DeadlineExceededExceptions dan HardDeadlineExceededErrors akan memaksa penghentian permintaan dan menghentikan instance.

Untuk mengetahui sisa waktu sebelum batas waktu, aplikasi dapat mengimpor com.google.apphosting.api.ApiProxy dan memanggil ApiProxy.getCurrentEnvironment().getRemainingMillis() ini. Hal ini berguna jika aplikasi berencana untuk memulai beberapa pekerjaan yang mungkin memerlukan waktu terlalu lama; jika Anda tahu bahwa diperlukan waktu lima detik untuk memproses satu unit tugas, tetapi getRemainingMillis() menampilkan lebih sedikit waktu, tidak ada gunanya memulai unit kerja tersebut.

Respons

App Engine memanggil servlet dengan objek permintaan dan objek respons, lalu menunggu servlet mengisi objek respons dan ditampilkan. Saat servlet ditampilkan, data pada objek respons akan dikirim ke pengguna.

Ada batas ukuran yang berlaku untuk respons yang Anda buat, dan respons dapat diubah sebelum ditampilkan ke klien.

Untuk informasi selengkapnya, lihat Referensi respons permintaan.

Respons Streaming

App Engine tidak mendukung respons streaming ketika data dikirim dalam potongan inkremental ke klien saat permintaan sedang diproses. Semua data dari kode Anda dikumpulkan seperti yang dijelaskan di atas dan dikirim sebagai respons HTTP tunggal.

Kompresi respons

App Engine melakukan yang terbaik untuk menayangkan konten terkompresi (gzip) kepada klien yang mendukungnya. Untuk menentukan apakah konten harus dikompresi, App Engine melakukan hal berikut saat menerima permintaan:

  1. Mengonfirmasi apakah klien dapat menerima respons terkompresi secara andal dengan melihat header Accept-Encoding dan User-Agent dalam permintaan. Pendekatan ini menghindari beberapa bug umum dengan konten yang dikompresi dengan gzip di browser populer.

  2. Konfirmasi apakah kompresi konten sudah sesuai dengan melihat header Content-Type yang telah Anda konfigurasi untuk pengendali respons. Secara umum, kompresi sesuai untuk jenis konten berbasis teks, bukan jenis konten biner.

Perhatikan hal-hal berikut:

  • Klien dapat memaksa jenis konten berbasis teks dikompresi dengan menetapkan header permintaan Accept-Encoding dan User-Agent ke gzip.

  • Jika permintaan tidak menentukan gzip pada header Accept-Encoding, App Engine tidak akan mengompresi data respons.

  • Google Frontend menyimpan respons dari file statis App Engine dan pengendali direktori ke dalam cache. Bergantung pada berbagai faktor, seperti jenis data respons yang disimpan dalam cache terlebih dahulu, header Vary mana yang telah Anda tentukan dalam respons, dan header mana yang disertakan dalam permintaan, klien dapat meminta data yang dikompresi tetapi menerima data yang tidak dikompresi, begitu juga sebaliknya. Untuk mengetahui informasi selengkapnya, lihat Penyimpanan respons dalam cache.

Penyimpanan dalam cache respons

Google Frontend, dan kemungkinan browser yang digunakan pengguna serta server proxy dengan cache perantara lainnya, akan menyimpan dalam cache respons aplikasi Anda seperti yang diinstruksikan oleh header penyimpanan cache standar yang Anda tentukan dalam respons. Anda dapat menentukan header respons ini melalui framework, langsung di kode, atau melalui pengendali direktori dan file statis App Engine.

Di Google Frontend, kunci cache adalah URL lengkap permintaan.

Menyimpan konten statis ke dalam cache

Untuk memastikan bahwa klien selalu menerima konten statis yang diperbarui segera setelah dipublikasikan, sebaiknya Anda menayangkan konten statis dari direktori berversi, seperti css/v1/styles.css. Google Frontend tidak akan memvalidasi cache (memeriksa konten yang diperbarui) hingga cache berakhir. Bahkan setelah masa berlaku cache berakhir, cache tidak akan diperbarui hingga konten di URL permintaan berubah.

Header respons berikut yang dapat Anda tetapkan di appengine-web.xml memengaruhi cara dan waktu Google Frontend menyimpan konten dalam cache:

  • Cache-Control harus disetel ke public agar Google Frontend dapat menyimpan konten dalam cache; tetapi juga dapat disimpan dalam cache oleh Google Frontend, kecuali jika Anda menentukan perintah Cache-Control private atau no-store. Jika Anda tidak menetapkan header ini di appengine-web.xml, App Engine akan otomatis menambahkannya untuk semua respons yang ditangani oleh file statis atau pengendali direktori. Untuk mengetahui informasi selengkapnya, lihat Header yang ditambahkan atau diganti.

  • Vary: Agar cache dapat menampilkan respons yang berbeda untuk URL berdasarkan header yang dikirim dalam permintaan, tentukan satu atau beberapa nilai berikut di header responds Vary: Accept danAccept-Encoding danOrigin , atauX-Origin

    Karena potensi kardinalitas yang tinggi, data untuk Vary lainnya tidak akan disimpan dalam cache.

    Contoh:

    1. Anda menentukan header respons berikut:

      Vary: Accept-Encoding

    2. Aplikasi Anda menerima permintaan yang berisi header Accept-Encoding: gzip. App Engine menampilkan respons terkompresi dan Google Frontend meng-cache versi data respons yang di-gzip. Semua permintaan berikutnya untuk URL ini yang berisi header Accept-Encoding: gzip akan menerima data hasil gzip dari cache hingga cache menjadi tidak valid (karena konten berubah setelah cache berakhir masa berlakunya).

    3. Aplikasi Anda akan menerima permintaan yang tidak berisi header Accept-Encoding. App Engine menampilkan respons yang tidak dikompresi dan Google Frontend akan meng-cache versi data respons yang tidak dikompresi. Semua permintaan berikutnya untuk URL ini yang tidak berisi header Accept-Encoding akan menerima data terkompresi dari cache hingga cache menjadi tidak valid.

    Jika Anda tidak menentukan header respons Vary, Google Frontend akan membuat satu entri cache untuk URL dan akan menggunakannya untuk semua permintaan, terlepas dari header dalam permintaan. Contoh:

    1. Anda tidak menentukan header respons Vary: Accept-Encoding.
    2. Permintaan berisi header Accept-Encoding: gzip, dan versi data respons yang di-gzip akan disimpan dalam cache.
    3. Permintaan kedua tidak berisi header Accept-Encoding: gzip. Namun, karena cache berisi versi data respons yang di-gzip, respons akan di-gzip meskipun klien meminta data yang tidak dikompresi.

Header dalam permintaan juga memengaruhi penyimpanan cache:

  • Jika permintaan berisi header Authorization, konten tidak akan disimpan dalam cache oleh Google Frontend.

Masa berlaku cache

Secara default, header caching yang ditambahkan oleh file statis dan pengendali direktori App Engine ke respons memerintahkan klien dan proxy web seperti Google Frontend untuk menghentikan masa berlaku cache setelah 10 menit.

Setelah file dikirimkan dengan waktu habis masa berlaku tertentu, biasanya tidak mungkin untuk menghapusnya dari cache web-proxy, meskipun pengguna menghapus cache browsernya sendiri. Men-deploy ulang versi baru aplikasi tidak akan mereset cache apa pun. Oleh karena itu, jika Anda berencana mengubah file statis, file tersebut harus memiliki waktu habis masa berlaku yang singkat (kurang dari satu jam). Biasanya, waktu habis masa berlaku default 10 menit sudah sesuai.

Anda dapat mengubah masa berlaku default untuk semua pengendali direktori dan file statis dengan menentukan elemen static-files dalam file appengine-web.xml Anda.

Logging

Aplikasi Anda dapat menulis informasi ke log aplikasi menggunakan java.util.logging.Logger. Data log untuk aplikasi Anda dapat dilihat di Konsol Google Cloud menggunakan Cloud Logging. Setiap permintaan yang dicatat ke dalam log akan diberi ID permintaan, yaitu ID unik secara global berdasarkan waktu mulai permintaan. Konsol Google Cloud dapat mengenali level log class Logger, dan menampilkan pesan secara interaktif pada level yang berbeda.

Semua yang ditulis servlet ke aliran output standar (System.out) dan aliran error standar (System.err) ditangkap oleh App Engine dan dicatat dalam log aplikasi. Baris yang ditulis ke aliran output standar dicatat ke dalam log di level "INFO", dan baris yang ditulis ke aliran data error standar dicatat ke dalam log pada level "WARNING". Setiap framework logging (seperti log4j) yang mencatat log ke output atau aliran error akan berfungsi. Namun, untuk kontrol yang lebih mendetail atas tampilan level log di Konsol Google Cloud, framework logging harus menggunakan adaptor java.util.logging.

// With @WebServlet annotation the webapp/WEB-INF/web.xml is no longer required.
@WebServlet(
    name = "RequestLogging",
    description = "Requests: Logging example",
    urlPatterns = "/requests/log"
)
public class LoggingServlet extends HttpServlet {

  private static final Logger log = Logger.getLogger(LoggingServlet.class.getName());

  @Override
  public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
    log.info("An informational message.");
    log.warning("A warning message.");
    log.severe("An error message.");
    // ...
  }
}

App Engine Java SDK menyertakan file logging.properties template, dalam direktori appengine-java-sdk/config/user/. Untuk menggunakannya, salin file ke direktori WEB-INF/classes (atau di tempat lain di WAR), lalu properti sistem java.util.logging.config.file ke "WEB-INF/logging.properties" (atau jalur mana pun yang Anda pilih, relatif terhadap root aplikasi). Anda dapat menetapkan properti sistem di file appengine-web.xml sebagai berikut:

<appengine-web-app xmlns="http://appengine.google.com/ns/1.0"> ... <system-properties> <property name="java.util.logging.config.file" value="WEB-INF/logging.properties" /> </system-properties> </appengine-web-app>

Servlet mencatat pesan menggunakan level log INFO (menggunakan log.info()). Level log default adalah WARNING, yang menyembunyikan pesan INFO dari output. Untuk mengubah level log, edit file logging.properties.

Lingkungan

Semua properti sistem dan variabel lingkungan bersifat pribadi untuk aplikasi Anda. Menetapkan properti sistem hanya memengaruhi tampilan aplikasi Anda atas properti tersebut, bukan tampilan JVM.

Anda dapat menetapkan properti sistem dan variabel lingkungan untuk aplikasi Anda di deskripsi deployment.

App Engine menetapkan beberapa properti sistem yang mengidentifikasi lingkungan runtime:

  • com.google.appengine.runtime.environment adalah "Production" saat berjalan di App Engine, dan "Development" saat berjalan di server pengembangan.

    Selain menggunakan System.getProperty(), Anda dapat mengakses properti sistem menggunakan type-safe API kami. Contoh:

    if (SystemProperty.environment.value() ==
        SystemProperty.Environment.Value.Production) {
        // The app is running on App Engine...
    }
    
  • com.google.appengine.runtime.version adalah ID versi lingkungan runtime, seperti "1.3.0". Anda bisa mendapatkan versi dengan memanggil hal-hal berikut: String version = SystemProperty.version.get();

  • com.google.appengine.application.id adalah ID aplikasi. Anda bisa mendapatkan ID dengan memanggil hal-hal berikut: String ID = SystemProperty.applicationId.get();

  • com.google.appengine.application.version adalah versi utama dan minor dari layanan aplikasi yang sedang berjalan, sebagai "XY". Nomor versi utama ("X") ditentukan dalam file appengine-web.xml layanan. Nomor versi minor ("Y") disetel secara otomatis saat setiap versi aplikasi diupload ke App Engine. Anda bisa mendapatkan ID dengan memanggil hal-hal berikut: String ID = SystemProperty.applicationVersion.get();

    Di server web pengembangan, versi utama yang ditampilkan selalu versi layanan default, dan versi minor selalu "1".

App Engine juga menetapkan properti sistem berikut saat menginisialisasi JVM di server aplikasi:

  • file.separator
  • path.separator
  • line.separator
  • java.version
  • java.vendor
  • java.vendor.url
  • java.class.version
  • java.specification.version
  • java.specification.vendor
  • java.specification.name
  • java.vm.vendor
  • java.vm.name
  • java.vm.specification.version
  • java.vm.specification.vendor
  • java.vm.specification.name
  • user.dir

ID Instance

Anda dapat mengambil ID instance yang menangani permintaan menggunakan kode ini:

com.google.apphosting.api.ApiProxy.getCurrentEnvironment().getAttributes().get("com.google.appengine.instance.id")

Dalam lingkungan produksi, admin yang login dapat menggunakan ID di URL: https://INSTANCE_ID-dot-VERSION_ID-dot-SERVICE_ID-dot-PROJECT_ID.REGION_ID.r.appspot.com. Permintaan akan dirutekan ke instance tertentu tersebut. Jika instance tidak dapat menangani permintaan, instance akan menampilkan 503 langsung.

ID permintaan

Pada saat permintaan, Anda dapat menyimpan ID permintaan yang unik untuk permintaan tersebut. ID permintaan dapat digunakan nanti untuk menghubungkan permintaan dengan log untuk permintaan tersebut.

Kode berikut menunjukkan cara mendapatkan ID permintaan dalam konteks permintaan:

com.google.apphosting.api.ApiProxy.getCurrentEnvironment().getAttributes().get("com.google.appengine.runtime.request_log_id")

Memaksa koneksi HTTPS

Untuk alasan keamanan, semua aplikasi harus mendorong klien untuk terhubung melalui https. Untuk menginstruksikan browser agar lebih memilih https daripada http untuk halaman tertentu atau seluruh domain, tetapkan header Strict-Transport-Security dalam respons Anda. Contoh:

Strict-Transport-Security: max-age=31536000; includeSubDomains
Untuk menetapkan header ini untuk konten statis apa pun yang disalurkan oleh aplikasi, tambahkan header ke pengendali direktori dan file statis aplikasi Anda.

Sebagian besar framework aplikasi dan server web memberikan dukungan untuk menyetel header ini bagi respons yang dihasilkan dari kode Anda. Untuk mengetahui informasi tentang header Strict-Transport-Security di Spring Boot, lihat HTTP Strict Transport Security (HSTS).

Menangani pekerjaan latar belakang asinkron

Pekerjaan latar belakang adalah pekerjaan apa pun yang dilakukan aplikasi untuk sebuah permintaan setelah Anda mengirimkan respons HTTP. Hindari melakukan pekerjaan latar belakang di aplikasi Anda, dan tinjau kode untuk memastikan semua operasi asinkron selesai sebelum Anda mengirimkan respons.

Untuk tugas yang berjalan lama, sebaiknya gunakan Cloud Tasks. Dengan Cloud Tasks, permintaan HTTP berumur panjang dan menampilkan respons hanya setelah pekerjaan asinkron berakhir.