Scrittura di messaggi Cloud Pub/Sub e risposta a tali messaggi

ID regione

REGION_ID è un codice abbreviato assegnato da Google in base alla regione selezionata al momento della creazione dell'app. Il codice non corrispondono a un paese o a una provincia, anche se potrebbero essere visualizzati alcuni ID regione in modo simile ai codici paese e provincia di uso comune. Per le app create dopo febbraio 2020, REGION_ID.r è incluso negli URL di App Engine. Per le app esistenti create prima di questa data, l'ID regione è facoltativo nell'URL.

Scopri di più sugli ID regione.

Pub/Sub fornisce una messaggistica asincrona many-to-many affidabile tra le applicazioni. Le applicazioni publisher possono inviare messaggi a un argomento e altre applicazioni possono abbonarsi all'argomento per riceverli.

Questo documento descrive come utilizzare Cloud Client Raccolta per inviare e ricevere messaggi Pub/Sub in un'app Java 8.

Prerequisiti

  • Segui le istruzioni in "Ciao, mondo!" per Java 8 su App Engine per configurare l'ambiente e il progetto e comprendere Le app Java 8 di App Engine sono strutturate.
  • Annota e salva l'ID progetto, perché ti servirà per eseguire dell'applicazione di esempio descritta in questo documento.

Clonazione dell'app di esempio

Copia le app di esempio sulla tua macchina locale e vai alla directory pubsub:

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

Creazione di un argomento e una sottoscrizione

Creare un argomento e una sottoscrizione, che includono la specifica dell'endpoint a cui il server Pub/Sub deve inviare le richieste:

 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

Sostituisci YOUR_TOKEN con un token casuale segreto. L'endpoint push lo utilizza per verificare le richieste.

Per utilizzare Pub/Sub con l'autenticazione, crea un altro abbonamento:

# 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 service agent
# `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'
Sostituisci "YOUR-SERVICE-ACCOUNT-EMAIL" con l'email del tuo [account di servizio](/appengine/docs/flex/configure-service-accounts). ### Impostazione delle variabili di ambiente {: edit_appyaml} Modifica il file " appengine-web.xml " per impostare le variabili di ambiente per l'argomento e il token di verifica:
<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>
## Revisione del codice L'app di esempio utilizza la [libreria client Cloud](https://googleapis.dev/java/google-cloud-clients/latest/index.html){: class="external"}. L'app di esempio utilizza i valori impostati nel file " appengine-web.xml" per configurare le variabili di ambiente. Il gestore delle richieste push utilizza questi valori per confermare che la richiesta proviene da Pub/Sub e ha avuto origine da una fonte attendibile: String pubsubVerificationToken = System.getenv("PUBSUB_VERIFICATION_TOKEN"); L'app di esempio gestisce un'istanza del database Cloud Datastore per archiviare i messaggi. Il servlet "PubSubPush" riceve i messaggi inviati tramite push e li aggiunge al Istanza di 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();
  }
}
Il servlet "PubSubPublish" interagisce con l'app web App Engine per pubblicare nuovi messaggi e visualizzare quelli ricevuti:
/*
 * 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;
  }
}
## Eseguire l'esempio localmente {: #run_the_sample_locally} Quando esegui l'esempio localmente, puoi utilizzare l'interfaccia a riga di comando Google Cloud per fornire l'autenticazione per utilizzare le API Google Cloud. Supponendo di aver configurato l'ambiente come descritto in [Prerequisiti](#prerequisites), hai già eseguito il comando "gcloud init", che fornisce questa autenticazione. Pacchetto mvn clean Quindi imposta le variabili di ambiente prima di avviare l'applicazione: esportazione PUBSUB_VERIFICATION_TOKEN=[token-di-verifica] esporta PUBSUB_TOPIC=[tuo-argomento] mvn appengine:run ### Simulazione di notifiche push {: Simula_push_notifications} L'applicazione può inviare messaggi localmente, ma non è in grado di ricevere messaggi push in locale. Tuttavia, puoi simulare un messaggio push inviando una richiesta HTTP all'endpoint di notifica push locale. L'esempio include il file `sample_message.json`. Puoi usare "curl" o un client [`httpie`](https://github.com/jkbrzt/httpie){: class="external"} per invia una richiesta HTTP "POST": curl -H "Content-Type: application/json" -i --data @sample_message.json "localhost:8080/pubsub/push?token=[tuo-token]" Oppure: http POST ":8080/pubsub/push?token=[tuo-token]" &lt; sample_message.json Risposta: HTTP/1.1 200 OK Data: Mer, 26 apr 2017 00:03:28 GMT Content-Length: 0 Server: Jetty(9.3.8.v20160314) Una volta completata la richiesta, puoi aggiornare "localhost:8080" e vedere messaggio nell'elenco dei messaggi ricevuti. ## In esecuzione su App Engine {: #run_on_app_engine} Per eseguire il deployment dell'app demo in App Engine mediante la riga di comando "gcloud" esegui il comando seguente dalla directory in cui `pom.xml` ha sede:
mvn package appengine:deploy -Dapp.deploy.projectId=PROJECT_ID

Sostituisci PROJECT_ID con l'ID del tuo progetto Google Cloud. Se il tuo file pom.xml specifica già il tuo ID progetto, non devi includere la proprietà -Dapp.deploy.projectId nel comando eseguito.

Ora puoi accedere all'applicazione da https://PROJECT_ID.REGION_ID.r.appspot.com. Puoi utilizzare il modulo per inviare messaggi, ma non c'è alcuna garanzia di quale dell'applicazione riceveranno la notifica. Puoi inviare più messaggi e aggiornare la pagina per visualizzare il messaggio ricevuto.