Google Cloud Run pubsub拉取监听器应用程序无法启动

问题描述

我仅使用此示例Java代码的侦听器部分在Cloud Run上测试pubsub“ pull”订阅服务器(SubscribeAsyncExample ...略作修改以适合我的SpringBoot应用程序): https://cloud.google.com/pubsub/docs/quickstart-client-libraries#java_1 它在部署期间无法启动...但是在尝试启动时,它确实从pubsub队列中提取了项目。最初,我在不同的pubsub主题上有一个HTTP“ push”接收器(@RestController),并且工作正常。有什么建议?我是Cloud Run的新手。谢谢。

deploying...
  Creating Revision... Cloud Run error: Container Failed to start. Failed to start and then listen on the port defined
  by the PORT environment variable. Logs for this revision might contain more @R_39_4045@ion....Failed
Deployment Failed
In logs:
2020-08-11 18:43:22.688 INFO 1 --- [ main] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 4606 ms
2020-08-11T18:43:25.287759Z Listening for messages on projects/ce-cxmo-dev/subscriptions/AndySubscriptionPull:
2020-08-11T18:43:25.351650801Z Container SandBox: Unsupported syscall setsockopt(0x18,0x29,0x31,0x3eca02dfd974,0x4,0x28). It is very likely that you can safely ignore this message and that this is not the cause of any error you might be troubleshooting. Please,refer to https://gvisor.dev/c/linux/amd64/setsockopt for more @R_39_4045@ion.
2020-08-11T18:43:25.351770555Z Container SandBox: Unsupported syscall setsockopt(0x18,0x12,0x3eca02dfd97c,refer to https://gvisor.dev/c/linux/amd64/setsockopt for more @R_39_4045@ion.
2020-08-11 18:43:25.680 WARN 1 --- [ault-executor-0] i.g.n.s.i.n.u.internal.MacAddressUtil : Failed to find a usable hardware address from the network interfaces; using random bytes: ae:2c:fb:e7:92:9c:2b:24
2020-08-11T18:45:36.282714Z Id: 1421389098497572
2020-08-11T18:45:36.282763Z Data: We be pub-sub'n in pull mode2!!
nothing else after this and the app stops running.

@Component
public class AndyTopicpullRecv {
  
  public AndyTopicpullRecv() 
  {
    subscribeAsyncExample("ce-cxmo-dev","AndySubscriptionPull");
  }
  
  public static void subscribeAsyncExample(String projectId,String subscriptionId) {
    ProjectSubscriptionName subscriptionName =
        ProjectSubscriptionName.of(projectId,subscriptionId);

    // Instantiate an asynchronous message receiver.
    MessageReceiver receiver =
        (PubsubMessage message,AckReplyConsumer consumer) -> {
          // Handle incoming message,then ack the received message.
          System.out.println("Id: " + message.getMessageId());
          System.out.println("Data: " + message.getData().toStringUtf8());
          consumer.ack();
        };

    Subscriber subscriber = null;
    try {
      subscriber = Subscriber.newBuilder(subscriptionName,receiver).build();
      // Start the subscriber.
      subscriber.startAsync().awaitRunning();
      System.out.printf("Listening for messages on %s:\n",subscriptionName.toString());
      // Allow the subscriber to run for 30s unless an unrecoverable error occurs.
      // subscriber.awaitTerminated(30,TimeUnit.SECONDS);
      subscriber.awaitTerminated();
      System.out.printf("Async subscribe terminated on %s:\n",subscriptionName.toString());
    // } catch (TimeoutException timeoutException) {
    } catch (Exception e) {
      // Shut down the subscriber after 30s. Stop receiving messages.
      subscriber.stopAsync();
      System.out.printf("Async subscriber exception: " + e); 
    }
  }
}

解决方法

科尔班问题非常重要!!使用共享的代码,我想说“不”。 Cloud Run contract很清楚:

  • 您的服务必须回答HTTP请求。超出请求,您无需支付任何费用,并且没有CPU专用于您的实例(当没有请求正在处理时,该实例就像一个守护程序)
  • 您的服务必须是无状态的(不是您的情况,我不会花时间在此事上)

如果您要撤消PubSub订阅,请在code with a Rest controller中创建一个终结点。在处理此请求时,请运行您的拉取机制并处理消息。

Cloud Scheduler可以定期调用此终结点,以保持进程正常。

请注意,您有a max request processing timeout at 15 minutes(今天,可能会在不久的将来发生变化)。因此,您的过程不能超过15分钟。使其具有弹性,使其能够失败,并将您的调度程序设置为每15分钟调用一次服务