本指南简要介绍了如何自定义 Java 客户端库的几个高级方面。一个常见的模式是,其中许多功能依赖于底层 Callable
,而不是标准方法。通常,可调用对象是查找此处未记录的其他 RPC 级功能的好地方。
超时
Java 库提供了一个接口,用于在每次调用级别设置超时。默认值是根据 googleads_grpc_service_config.json 中的 method_config/timeout
设置设置的。如果您需要对 API 调用的最长时间强制执行更短的限制,请设置较低的值。
如需使用此功能,您应直接使用可调用对象。例如,如果调用 GoogleAdsService.searchStream()
,超时设置如下所示:
try (GoogleAdsServiceClient googleAdsServiceClient =
googleAdsClient.getLatestVersion().createGoogleAdsServiceClient()) {
// Constructs the SearchGoogleAdsStreamRequest.
SearchGoogleAdsStreamRequest request = ...
// Executes the API call, with a timeout of 5 minutes.
ServerStream<SearchGoogleAdsStreamResponse> result = googleAdsServiceClient
.searchStreamCallable()
.call(request,
GrpcCallContext.createDefault().withTimeout(Duration.of(5, ChronoUnit.MINUTES)));
}
您可以将超时设置为 2 小时或更长时间,但 API 可能仍会超时处理运行时间极长的请求,并返回 DEADLINE_EXCEEDED
错误。如果这成为一个问题,通常最好将查询拆分并并行执行各个分块;这样可以避免长时间运行的请求失败,而唯一的恢复方法是从头开始再次触发请求。
重试设置
Java 库还提供了一个接口,用于在每次调用级别配置重试设置。如需使用此功能,您应直接使用可调用对象。例如,如果调用 GoogleAdsService.searchStream()
,则重试设置将配置如下:
// Creates a context object with the custom retry settings.
GrpcCallContext context = GrpcCallContext.createDefault()
.withRetrySettings(RetrySettings.newBuilder()
.setInitialRetryDelay(Duration.ofMillis(10L))
.setMaxRetryDelay(Duration.ofSeconds(10L))
.setRetryDelayMultiplier(1.4)
.setMaxAttempts(10)
.setLogicalTimeout(Duration.ofSeconds(30L))
.build());
// Creates and issues a search Google Ads stream request.
ServerStream<SearchGoogleAdsStreamResponse> stream =
googleAdsServiceClient.searchStreamCallable().call(request, context);
启动时间性能优化
您可能会注意到,首次创建 GoogleAdsClient
实例时会出现一小段延迟。这是因为服务的流畅界面 (GoogleAdsClient.getVersionXX()
) 会一次加载所有 API 类,以便提供更便捷的服务类构建机制。
如果首次请求性能是应用的关键路径,您应按以下步骤操作:
在启动时(在处理用户请求之前)创建
GoogleAdsClient
。在该进程首次启动时,向 Google Ads API 发送一些预热请求。例如:
// Runs some warm-up requests. try (GoogleAdsServiceClient googleAdsServiceClient = googleAdsClient.getLatestVersion().createGoogleAdsServiceClient()) { // Runs 5 warm-up requests. In our profiling we see that 90% of performance // loss is only experienced on the first API call. After 3 subsequent calls we // saw a negligible improvement in performance. for (int i = 0; i < 5; ++i) { // Warm-up queries are run with a nonexistent CID so the calls will fail. If // you have a CID that you know will be accessible with the OAuth // credentials provided you may want to provide that instead and avoid the // try-catch. try { googleAdsServiceClient.search("-1", "Warm-up query"); } catch (GoogleAdsException ex) { // Do nothing, we're expecting this to fail. } } }
每个进程只需运行一次预热请求。之后每次创建服务客户端时,都会自动重用预加载的类。
重复使用服务客户端
您应在可行的情况下重复使用服务客户端实例,因为对 GoogleAdsClient.getVersionXXX().createYYYServiceClient()
的每次调用都会创建新的 TCP 连接。
您必须确保在不再需要客户端时关闭客户端。这可以在 try-with-resources 块中完成,也可以通过对服务客户端调用 close()
来完成。
如果您尝试使用已关闭的服务客户端发出 API 请求,服务客户端方法将抛出 java.util.concurrent.RejectedExecutionException
。
如果 JAR 大于 32 MB,App Engine 将无法部署
App Engine 对每个上传的文件的配额为 32 MB。google-ads
的 JAR 将比这大得多,使用 shade/shadow jar 部署时更是如此。如果您手动部署 jar 文件,可能会收到如下错误:
ERROR: (gcloud.app.deploy) Cannot upload file [<your-app>/WEB-INF/lib/google-ads-34.0.0.jar],
which has size [66095767] (greater than maximum allowed size of [33554432])
请改用 App Engine Gradle 插件或 Maven 插件进行部署。每个 jar 都有一个 enableJarSplitting
选项,该选项会将每个 jar 拆分为 10 MB 的块,并改为上传这些块。
阴影依赖项
如果您的项目存在与库冲突的依赖项,您应使用以下某个命令检查项目的依赖项,然后根据需要修改项目的依赖项。
Maven
mvn dependency:tree
Gradle
./gradlew dependencies
如果无法解决依赖项冲突,您可以改为依赖于库的阴影版本。
Maven
<dependency> <groupId>com.google.api-ads</groupId> <artifactId>google-ads-shadowjar</artifactId> <version>34.0.0</version> </dependency>
Gradle
implementation 'com.google.api-ads:google-ads-shadowjar:34.0.0'