Como gravar e responder mensagens do Pub/Sub

ID da região

O REGION_ID é um código abreviado que o Google atribui com base na região que você selecionou ao criar o aplicativo. O código não corresponde a um país ou estado, ainda que alguns IDs de região sejam semelhantes aos códigos de país e estado geralmente usados. Para apps criados após fevereiro de 2020, o REGION_ID.r está incluído nos URLs do App Engine. Para apps existentes criados antes dessa data, o ID da região é opcional no URL.

Saiba mais sobre IDs de região.

O Pub/Sub mensagens assíncronas confiáveis de muitos para muitos entre os aplicativos. Os aplicativos do editor podem enviar mensagens para um tópico e outros aplicativos podem assinar esse tópico para receber as mensagens.

Este documento descreve como usar a biblioteca de cliente do Cloud para enviar e receber mensagens de Pub/Sub em um aplicativo Java.

Pré-requisitos

  • Siga as instruções em "Hello, World!" para Java no App Engine para configurar seu ambiente e projeto e entender como os aplicativos Java do App Engine estão estruturados.
  • Anote e salve o ID do projeto. Ele será necessário para executar o aplicativo de amostra descrito neste documento.

    Como clonar o app de amostra

    Copie os aplicativos de amostra para sua máquina local e navegue até o diretório pubsub:

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

    Como criar um tópico e uma assinatura

    Crie um tópico e uma assinatura. Isso inclui especificar o endpoint que receberá as solicitações do Pub/Sub:

    gcloud pubsub topics create YOUR_TOPIC_NAME
    gcloud pubsub subscriptions create YOUR_SUBSCRIPTION_NAME \
        --topic YOUR_TOPIC_NAME \
        --push-endpoint \
        https://YOUR_PROJECT_ID.REGION_ID.r.appspot.com/pubsub/push?token=YOUR_TOKEN \
        --ack-deadline 10
    

    Substitua YOUR_TOKEN por um token aleatório secreto. Ele é usado pelo endpoint do push para verificar as solicitações.

    Como definir variáveis de ambiente

    Edite o arquivo app.yaml para definir as variáveis de ambiente do tópico e do token de verificação:

    env_variables:
      PUBSUB_TOPIC: <your-topic-name>
      # This token is used to verify that requests originate from your
      # application. It can be any sufficiently random string.
      PUBSUB_VERIFICATION_TOKEN: <your-verification-token>

    Revisão de código

    O aplicativo de amostra usa a Biblioteca de cliente do Cloud.

    O aplicativo de amostra usa os valores definidos no arquivo app.yaml para configurar variáveis de ambiente. Esses valores são usados pelo gerenciador da solicitação de push para confirmar que a solicitação veio do Pub/Sub e de uma fonte confiável:

    String pubsubVerificationToken = System.getenv("PUBSUB_VERIFICATION_TOKEN");
    

    O aplicativo de amostra mantém uma instância de banco de dados do Cloud Datastore para armazenar mensagens. O servlet PubSubPush recebe as mensagens enviadas por push e as adiciona à instância do banco de dados 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(HttpServletResponse.SC_OK);
        } catch (Exception e) {
          resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        }
      }

    O servlet PubSubPublish interage com o aplicativo da Web do App Engine para publicar novas mensagens e exibir mensagens recebidas:

    @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) {
            publisher = Publisher.newBuilder(
                ProjectTopicName.of(ServiceOptions.getDefaultProjectId(), topicId))
                .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());
        }
      }

    Executar a amostra no local

    Com a Google Cloud CLI em execução no local, você pode fornecer autenticação para usar as APIs do Google Cloud. Se tiver configurado o ambiente conforme descrito nos Pré-requisitos, você já terá executado o comando gcloud init, que fornece essa autenticação.

    mvn clean package
    

    Defina as variáveis de ambiente antes de iniciar o aplicativo:

    export PUBSUB_VERIFICATION_TOKEN=[your-verification-token]
    export PUBSUB_TOPIC=[your-topic]
    mvn jetty:run
    

    Como simular notificações push

    Pelo aplicativo, é possível enviar mensagens localmente, mas não é possível receber mensagens push localmente. É possível simular uma mensagem de push com uma solicitação HTTP para o notification endpoint de push local. A amostra inclui o sample_message.json do arquivo.

    É possível usar curl ou um cliente httpie para enviar uma solicitação POST HTTP:

    curl -H "Content-Type: application/json" -i --data @sample_message.json "localhost:8080/pubsub/push?token=[your-token]"
    

    Ou

    http POST ":8080/pubsub/push?token=[your-token]" < sample_message.json
    

    Resposta:

    HTTP/1.1 200 OK
    Date: Wed, 26 Apr 2017 00:03:28 GMT
    Content-Length: 0
    Server: Jetty(9.3.8.v20160314)
    

    Após a conclusão da solicitação, é possível atualizar localhost:8080 e ver a mensagem na lista de mensagens recebidas.

    Como executar no App Engine

    Para implantar o app de demonstração no App Engine usando a ferramenta de linha de comando gcloud, execute o comando a seguir no diretório em que seu arquivo app.yaml está localizado:

    mvn package appengine:deploy -Dapp.deploy.projectId=PROJECT_ID

    Substitua PROJECT_ID pelo ID do projeto do Cloud. Se o arquivo pom.xmlespecificar o ID do projeto, não será necessário incluir a propriedade -Dapp.deploy.projectId no comando executado.

    Agora, é possível acessar o aplicativo em https://PROJECT_ID.REGION_ID.r.appspot.com. Use o formulário para enviar mensagens, mas não há garantias de qual instância do seu aplicativo receberá a notificação. É possível enviar várias mensagens e atualizar a página para ver a mensagem recebida.