首页 > 解决方案 > 启动时创建任务时的 DeadlineExceededException

问题描述

我在 Google Cloud Run 上部署了一个 Spring Boot 2.4.5 应用程序(使用 Jib 创建的图像)。启动时我想创建一个云任务,但我得到一个DeadlineExceededException.

如果我运行任务创建代码但由 HTTP 请求触发,则创建任务。并且应该在启动时创建的任务也被创建。就像启动时缺少某些东西一样,阻止了任务的创建。

启动事件

@EventListener(ApplicationReadyEvent.class)
public void doSomethingAfterStartup()  {
    LOGGER.info("ApplicationReadyEvent");
    String message = "GCP New Instance Start " + Instant.now();
    cloudTasksService.createTask("xxxx", "us-central1", "xxxx", message, 60);
}

任务创建代码

public void createTask(String projectId, String locationId, String queueId, String message, Integer delay) throws IOException {
    try (CloudTasksClient client = CloudTasksClient.create()) {
        LOGGER.info("Client created");
        String url = "xxxxxxxxx";
        String payload = String.format("{ \"text\": \"%s\"}", message);

        String queuePath = QueueName.of(projectId, locationId, queueId).toString();
        Instant eta = Instant.now().plusSeconds(delay);
        Task.Builder taskBuilder =
                Task.newBuilder()
                        .setScheduleTime(Timestamp.newBuilder().setSeconds(eta.getEpochSecond()).build())
                        .setHttpRequest(
                                HttpRequest.newBuilder()
                                        .setBody(ByteString.copyFrom(payload, Charset.defaultCharset()))
                                        .setUrl(url)
                                        .setHttpMethod(HttpMethod.POST)
                                        .build());
        LOGGER.info("TaskBuilder ready");
        Task task = client.createTask(queuePath, taskBuilder.build());
        LOGGER.info("Task created: {}", task.getName());
    }
}

HTTP 端点

@GetMapping("/tasks")
public ResponseEntity<Void> task(@RequestParam Integer delay) throws IOException {
    cloudTasksService.createTask("xxxx", "us-central1", "xxxx", "using HTTP request", delay);
    return ResponseEntity.accepted().build();
}

例外

com.google.api.gax.rpc.DeadlineExceededException: io.grpc.StatusRuntimeException: DEADLINE_EXCEEDED: Deadline exceeded after 5.200272920s. 
    at com.google.api.gax.rpc.ApiExceptionFactory.createException(ApiExceptionFactory.java:51)
    at com.google.api.gax.grpc.GrpcApiExceptionFactory.create(GrpcApiExceptionFactory.java:72)
    at com.google.api.gax.grpc.GrpcApiExceptionFactory.create(GrpcApiExceptionFactory.java:60)
    at com.google.api.gax.grpc.GrpcExceptionCallable$ExceptionTransformingFuture.onFailure(GrpcExceptionCallable.java:97)
    at com.google.api.core.ApiFutures$1.onFailure(ApiFutures.java:68)
    at com.google.common.util.concurrent.Futures$CallbackListener.run(Futures.java:1074)
    at com.google.common.util.concurrent.DirectExecutor.execute(DirectExecutor.java:30)
    at com.google.common.util.concurrent.AbstractFuture.executeListener(AbstractFuture.java:1213)
    at com.google.common.util.concurrent.AbstractFuture.addListener(AbstractFuture.java:724)
    at com.google.common.util.concurrent.ForwardingListenableFuture.addListener(ForwardingListenableFuture.java:45)
    at com.google.api.core.ApiFutureToListenableFuture.addListener(ApiFutureToListenableFuture.java:52)
    at com.google.common.util.concurrent.Futures.addCallback(Futures.java:1047)
    at com.google.api.core.ApiFutures.addCallback(ApiFutures.java:63)
    at com.google.api.gax.grpc.GrpcExceptionCallable.futureCall(GrpcExceptionCallable.java:67)
    at com.google.api.gax.rpc.UnaryCallable$1.futureCall(UnaryCallable.java:126)
    at com.google.api.gax.tracing.TracedUnaryCallable.futureCall(TracedUnaryCallable.java:75)
    at com.google.api.gax.rpc.UnaryCallable$1.futureCall(UnaryCallable.java:126)
    at com.google.api.gax.rpc.UnaryCallable.futureCall(UnaryCallable.java:87)
    at com.google.api.gax.rpc.UnaryCallable.call(UnaryCallable.java:112)
    at com.google.cloud.tasks.v2.CloudTasksClient.createTask(CloudTasksClient.java:1915)
    at com.google.cloud.tasks.v2.CloudTasksClient.createTask(CloudTasksClient.java:1885)
    at com.sps.playground.CloudTasksService.createTask(CloudTasksService.java:55)

标签: google-cloud-platformgoogle-cloud-run

解决方案


当任务排队时,工作人员似乎还没有准备好。我建议在启动时创建任务,因为这种情况经常发生,因为工作人员在处理任务时没有通过就绪检查,然后它就失败了。这也解释了为什么任务在由 HTTP 触发时正常运行。

您可以按照建议减少启动时间来解决这个问题。此外,当您将 Java 与 Springboot 一起使用时,可能也值得检查减少启动任务建议。


推荐阅读