Menulis dan Merespons Pesan Pub/Sub

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.

Pub/Sub menyediakan pesan yang andal, many-to-many, dan asinkron antara aplikasi. Aplikasi penayang dapat mengirim pesan ke topik, dan aplikasi lain dapat berlangganan topik tersebut untuk menerima pesan.

Dokumen ini menjelaskan cara menggunakan Library Klien Cloud untuk mengirim dan menerima pesan Pub/Sub di aplikasi Java 8.

Prasyarat

  • Ikuti petunjuk di "Hello, World!" untuk Java 8 di App Engine guna menyiapkan lingkungan dan project Anda, serta memahami cara struktur aplikasi App Engine Java 8.
  • Tuliskan dan simpan project ID Anda karena Anda akan membutuhkannya untuk menjalankan contoh aplikasi yang dijelaskan dalam dokumen ini.

Membuat clone aplikasi contoh

Salin aplikasi contoh ke komputer lokal Anda, lalu buka direktori pubsub:

git clone https://github.com/GoogleCloudPlatform/java-docs-samples
cd java-docs-samples/appengine-java8/pubsub

Membuat topik dan langganan

Buat topik dan langganan, termasuk menentukan endpoint yang harus dikirimi permintaan oleh server Pub/Sub:

 bv
# Configure the topic
gcloud pubsub topics create YOUR_TOPIC_NAME

# Configure the push subscription
gcloud pubsub subscriptions create YOUR_SUBSCRIPTION_NAME \
    --topic=YOUR_TOPIC_NAME \
    --push-endpoint=https://YOUR_PROJECT_ID.REGION_ID.r.appspot.com/push-handlers/receive_messages?token=YOUR_TOKEN \
    --ack-deadline=10

Ganti YOUR_TOKEN dengan token acak rahasia. Endpoint push menggunakannya untuk memverifikasi permintaan.

Untuk menggunakan Pub/Sub dengan autentikasi, buat langganan lain:

# Configure the push subscription
gcloud pubsub subscriptions create YOUR_SUBSCRIPTION_NAME \
    --topic=YOUR_TOPIC_NAME \
    --push-auth-service-account=YOUR-SERVICE-ACCOUNT-EMAIL\
    --push-auth-token-audience=OPTIONAL_AUDIENCE_OVERRIDE\
    --push-endpoint=https://YOUR_PROJECT_ID.REGION_ID.r.appspot.com/push-handlers/receive_messages?token=YOUR_TOKEN \
    --ack-deadline=10

# Your Google-managed service account
# `service-{PROJECT_NUMBER}@gcp-sa-pubsub.iam.gserviceaccount.com` needs to have the
# `iam.serviceAccountTokenCreator` role.
PUBSUB_SERVICE_ACCOUNT="service-${PROJECT_NUMBER}@gcp-sa-pubsub.iam.gserviceaccount.com"
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
    --member="serviceAccount:${PUBSUB_SERVICE_ACCOUNT}"\
    --role='roles/iam.serviceAccountTokenCreator'
Ganti `YOUR-SERVICE-ACCOUNT-EMAIL` dengan email [akun layanan](/appengine/docs/flexible/configure-service-accounts) Anda. ### Menetapkan variabel lingkungan {: edit_appyaml} Edit file ` appengine-web.xml `untuk menetapkan variabel lingkungan untuk topik dan token verifikasi Anda:
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
  <threadsafe>true</threadsafe>
  <runtime>java8</runtime>

  <env-variables>
    <env-var name="PUBSUB_TOPIC" value="your-topic" />
    <env-var name="PUBSUB_VERIFICATION_TOKEN" value="your-verification-token" />
  </env-variables>
</appengine-web-app>
## Tinjauan kode Aplikasi contoh menggunakan [Library Klien Cloud](https://googleapis.dev/java/google-cloud-clients/latest/index.html){: class="external" } ini. Aplikasi contoh menggunakan nilai yang Anda tetapkan dalam file ` appengine-web.xml untuk mengonfigurasi variabel lingkungan. Pengendali permintaan push menggunakan nilai ini untuk mengonfirmasi bahwa permintaan berasal dari Pub/Sub dan berasal dari sumber tepercaya: String pubsubVerificationToken = System.getenv("PUBSUB_VERIFICATION_TOKEN"); Aplikasi contoh mempertahankan instance database Cloud Datastore untuk menyimpan pesan. Servlet `PubSubPush` menerima pesan yang dikirim dan menambahkannya ke instance database `messageRepository`:
@WebServlet(value = "/pubsub/push")
public class PubSubPush extends HttpServlet {

  @Override
  public void doPost(HttpServletRequest req, HttpServletResponse resp)
      throws IOException, ServletException {
    String pubsubVerificationToken = System.getenv("PUBSUB_VERIFICATION_TOKEN");
    // Do not process message if request token does not match pubsubVerificationToken
    if (req.getParameter("token").compareTo(pubsubVerificationToken) != 0) {
      resp.setStatus(HttpServletResponse.SC_BAD_REQUEST);
      return;
    }
    // parse message object from "message" field in the request body json
    // decode message data from base64
    Message message = getMessage(req);
    try {
      messageRepository.save(message);
      // 200, 201, 204, 102 status codes are interpreted as success by the Pub/Sub system
      resp.setStatus(102);
    } catch (Exception e) {
      resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
    }
  }

  private Message getMessage(HttpServletRequest request) throws IOException {
    String requestBody = request.getReader().lines().collect(Collectors.joining("\n"));
    JsonElement jsonRoot = JsonParser.parseString(requestBody).getAsJsonObject();
    String messageStr = jsonRoot.getAsJsonObject().get("message").toString();
    Message message = gson.fromJson(messageStr, Message.class);
    // decode from base64
    String decoded = decode(message.getData());
    message.setData(decoded);
    return message;
  }

  private String decode(String data) {
    return new String(Base64.getDecoder().decode(data));
  }

  private final Gson gson = new Gson();
  private MessageRepository messageRepository;

  PubSubPush(MessageRepository messageRepository) {
    this.messageRepository = messageRepository;
  }

  public PubSubPush() {
    this.messageRepository = MessageRepositoryImpl.getInstance();
  }
}
Servlet `PubSubPublish` berinteraksi dengan aplikasi web App Engine untuk memublikasikan pesan baru dan menampilkan pesan yang diterima:
/*
 * Copyright 2017 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.example.appengine.pubsub;

import com.google.cloud.ServiceOptions;
import com.google.cloud.pubsub.v1.Publisher;
import com.google.protobuf.ByteString;
import com.google.pubsub.v1.ProjectTopicName;
import com.google.pubsub.v1.PubsubMessage;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.http.HttpStatus;

@WebServlet(name = "Publish with PubSub", value = "/pubsub/publish")
public class PubSubPublish extends HttpServlet {

  @Override
  public void doPost(HttpServletRequest req, HttpServletResponse resp)
      throws IOException, ServletException {
    Publisher publisher = this.publisher;
    try {
      String topicId = System.getenv("PUBSUB_TOPIC");
      // create a publisher on the topic
      if (publisher == null) {
        ProjectTopicName topicName =
            ProjectTopicName.newBuilder()
                .setProject(ServiceOptions.getDefaultProjectId())
                .setTopic(topicId)
                .build();
        publisher = Publisher.newBuilder(topicName).build();
      }
      // construct a pubsub message from the payload
      final String payload = req.getParameter("payload");
      PubsubMessage pubsubMessage =
          PubsubMessage.newBuilder().setData(ByteString.copyFromUtf8(payload)).build();

      publisher.publish(pubsubMessage);
      // redirect to home page
      resp.sendRedirect("/");
    } catch (Exception e) {
      resp.sendError(HttpStatus.SC_INTERNAL_SERVER_ERROR, e.getMessage());
    }
  }

  private Publisher publisher;

  public PubSubPublish() {}

  PubSubPublish(Publisher publisher) {
    this.publisher = publisher;
  }
}
## Menjalankan sampel secara lokal {: #run_the_sample_locally} Saat berjalan secara lokal, Anda dapat menggunakan Google Cloud CLI untuk menyediakan autentikasi agar dapat menggunakan Google Cloud API. Dengan asumsi Anda menyiapkan lingkungan seperti yang dijelaskan dalam [Prasyarat](#prerequisites), Anda telah menjalankan perintah `gcloud init`, yang menyediakan autentikasi ini. mvn clean package Kemudian tetapkan variabel lingkungan sebelum memulai aplikasi: export PUBSUB_VERIFICATION_TOKEN=[your-verification-token] export PUBSUB_TOPIC=[your-topic] mvn appengine:run ### Menyimulasikan notifikasi push {: optimize_push_notifications} Aplikasi dapat mengirim pesan secara lokal, tetapi tidak mampu menerima pesan push secara lokal. Namun, Anda dapat menyimulasikan pesan push dengan membuat permintaan HTTP ke endpoint notifikasi push lokal. Contoh ini berisi file `sample_message.json`. Anda dapat menggunakan `curl` atau [`httpie`](https://github.com/jkbrzt/httpie){: class="external"} untuk mengirimkan permintaan `POST` HTTP: curl -H "Content-Type: application/json" -i --data @sample_message.json "localhost:8080/pubsub/push?token=[your-token]" Atau http POST ":8080/pubsub/push?token=[your-token]" < sample_message.json Respons: HTTP/1.1 200 OK Date: Wed, 26 Apr 2017 00:03:28 GMT Content-Length: 0 Server: Jetty(9.3.8.v20160314) Setelah permintaan selesai, Anda dapat memuat ulang `localhost:8080` dan melihat pesan dalam daftar pesan yang diterima. ## Berjalan di App Engine {: #run_on_app_engine} Untuk men-deploy aplikasi demo ke App Engine dengan menggunakan alat command line `gcloud`, jalankan perintah berikut dari direktori tempat `pom.xml` terletak:
mvn package appengine:deploy -Dapp.deploy.projectId=PROJECT_ID

Ganti PROJECT_ID dengan ID project Google Cloud Anda. Jika file pom.xml sudah menentukan project ID, Anda tidak perlu menyertakan properti -Dapp.deploy.projectId dalam perintah yang dijalankan.

Anda kini dapat mengakses aplikasi di https://PROJECT_ID.REGION_ID.r.appspot.com. Anda dapat menggunakan formulir ini untuk mengirim pesan, tetapi tidak ada jaminan terkait instance mana dari aplikasi Anda yang akan menerima notifikasi tersebut. Anda dapat mengirim beberapa pesan dan memuat ulang halaman untuk melihat pesan yang diterima.