0
votes

I'm testing pubsub "pull" subscriber on Cloud Run using just listener part of this sample java code (SubscribeAsyncExample...reworked slightly to fit in my SpringBoot app): https://cloud.google.com/pubsub/docs/quickstart-client-libraries#java_1 It fails to startup during deploy...but while it's trying to start, it does pull items from the pubsub queue. Originally, I had an HTTP "push" receiver (a @RestController) on a different pubsub topic and that worked fine. Any suggestions? I'm new to Cloud Run. Thanks.

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 information....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 information.
2020-08-11T18:43:25.351770555Z Container Sandbox: Unsupported syscall setsockopt(0x18,0x29,0x12,0x3eca02dfd97c,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 information.
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); 
    }
  }
}
1
What does your subscriber code do after logging the message data? Is it immediately trying to ack the message? It would be helpful if you could determine where exactly your app is crashing.Lauren
Are you actually listening and responding to the REST request that triggers the app? You might have to post a link to your code.Kolban
Thanks, I added the code to the description above.Andy M

1 Answers

1
votes

Kolban question is very important!! With the shared code, I would like to say "No". The Cloud Run contract is clear:

  • Your service must answer to HTTP request. Out of request, you pay nothing and no CPU is dedicated to your instance (the instance is like a daemon when no request is processing)
  • Your service must be stateless (not your case here, I won't take time on this)

If you want to pull your PubSub subscription, create an endpoint in your code with a Rest controller. While you are processing this request, run your pull mechanism and process messages.

This endpoint can be called by Cloud Scheduler regularly to keep the process up.

Be careful, you have a max request processing timeout at 15 minutes (today, subject to change in a near future). So, you can't run your process more than 15 minutes. Make it resilient to fail and set your scheduler to call your service every 15 minutes