במדריך הזה מוסבר איך להתאים אישית כמה מההיבטים המתקדמים יותר של ספריית הלקוח ב-Java. דפוס נפוץ הוא שהרבה מהתכונות האלה מסתמכות על Callable הבסיסי ולא על השיטות הנוחות הרגילות. האובייקט הניתן לקריאה הוא בדרך כלל מקום טוב לחפש בו תכונות אחרות לכל RPC שלא מתועדות כאן.
חסימה זמנית
ספריית Java מספקת ממשק להגדרת זמנים קצובים לתפוגה ברמת הקריאה.
ערך ברירת המחדל נקבע על סמך ההגדרה method_config/timeout ב-googleads_grpc_service_config.json. אם אתם צריכים לאכוף מגבלה קצרה יותר על הזמן המקסימלי לקריאה ל-API, הגדירו ערך נמוך יותר.
כדי להשתמש בתכונה הזו, צריך להפעיל את האובייקט Callable ישירות. לדוגמה, כשמפעילים את GoogleAdsService.searchStream(), מגדירים את הזמן הקצוב לתפוגה באופן הבא:
try (GoogleAdsServiceClient googleAdsServiceClient =
googleAdsClient.getLatestVersion().createGoogleAdsServiceClient()) {
// Constructs the SearchGoogleAdsStreamRequest.
SearchGoogleAdsStreamRequest request =
SearchGoogleAdsStreamRequest.newBuilder()
.setCustomerId(Long.toString(customerId))
.setQuery("SELECT campaign.id, campaign.name FROM campaign")
.build();
// Executes the API call with a timeout of 5 minutes.
ServerStream<SearchGoogleAdsStreamResponse> stream =
googleAdsServiceClient
.searchStreamCallable()
.call(
request,
GrpcCallContext.createDefault()
.withTimeout(Duration.of(5, ChronoUnit.MINUTES)));
for (SearchGoogleAdsStreamResponse response : stream) {
// Processes the response rows.
}
}
אפשר להגדיר את הזמן הקצוב לתפוגה לשעתיים או יותר, אבל יכול להיות שעדיין יחול זמן קצוב לתפוגה ב-API לבקשות ארוכות במיוחד, ותוחזר השגיאה DEADLINE_EXCEEDED.
אם זה קורה, בדרך כלל הכי טוב לפצל את השאילתה ולהריץ את החלקים במקביל. כך אפשר להימנע ממצב שבו בקשה ארוכה נכשלת והדרך היחידה לשחזר אותה היא להפעיל אותה שוב מההתחלה.
הגדרות לניסיון חוזר
בספריית Java יש גם ממשק להגדרת ניסיונות חוזרים ברמת הקריאה. כדי להשתמש בתכונה הזו, צריך להפעיל את האובייקט Callable ישירות. לדוגמה, כשקוראים ל-GoogleAdsService.searchStream(), מגדירים את הגדרות הניסיון החוזר באופן הבא:
try (GoogleAdsServiceClient googleAdsServiceClient =
googleAdsClient.getLatestVersion().createGoogleAdsServiceClient()) {
SearchGoogleAdsStreamRequest request =
SearchGoogleAdsStreamRequest.newBuilder()
.setCustomerId(Long.toString(customerId))
.setQuery("SELECT campaign.id, campaign.name FROM campaign")
.build();
// 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());
// Issues the streaming search request.
ServerStream<SearchGoogleAdsStreamResponse> stream =
googleAdsServiceClient.searchStreamCallable().call(request, context);
for (SearchGoogleAdsStreamResponse response : stream) {
// Processes the response rows.
}
}
אופטימיזציה של ביצועי זמן ההפעלה
יכול להיות שיהיה עיכוב קל בפעם הראשונה שנוצר מכונה של GoogleAdsClient. הסיבה לכך היא הממשק השוטף לשירותים (GoogleAdsClient.getLatestVersion()), שטוען את מחלקות השירות של ה-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 (ApiException ex) { // Do nothing, we're expecting this to fail. } } }
צריך להריץ את בקשות החימום רק פעם אחת לכל תהליך. בכל יצירה של לקוח שירות לאחר מכן, המערכת משתמשת באופן אוטומטי במחלקות שנטענו מראש.
שימוש חוזר בלקוח השירות
מומלץ להשתמש שוב במופעים של לקוחות שירות כשאפשר, כי כל קריאה ל-GoogleAdsClient.getLatestVersion().createYYYServiceClient() (או ל-accessor ספציפי לגרסה כמו getVersion26()) יוצרת חיבור בסיסי חדש ומשאבים משויכים.
חשוב לסגור את לקוח השירות כשכבר לא צריך אותו. אפשר לעשות את זה בבלוק try-with-resources או באמצעות קריאה ל-close() בלקוח השירות.
אם תנסו להשתמש בלקוח שירות סגור כדי לשלוח בקשות API, ה-method של לקוח השירות תגרום לשגיאה java.util.concurrent.RejectedExecutionException.
אי אפשר לפרוס את App Engine אם קובץ ה-JAR גדול מ-32MB
ב-App Engine יש מכסה של 32MB לכל קובץ שמעלים. קובץ ה-JAR של google-ads גדול בהרבה, במיוחד כשמשתמשים בפריסות של קובצי JAR מסוג shade או shadow. אם פורסים קובצי JAR באופן ידני, יכול להיות שיופיעו שגיאות כמו:
ERROR: (gcloud.app.deploy) Cannot upload file [<your-app>/WEB-INF/lib/google-ads-48.1.0.jar],
which has size [66095767] (greater than maximum allowed size of [33554432])
במקום זאת, צריך לפרוס באמצעות הפלאגין של Gradle או הפלאגין של Maven ב-App Engine. כל פלאגין מספק אפשרות enableJarSplitting שמפצלת כל קובץ JAR לחלקים של 10MB ומעלה אותם במקום זאת.
יחסי תלות של צל
אם בפרויקט יש יחסי תלות שמתנגשים עם יחסי התלות של הספרייה, בודקים את היררכיית יחסי התלות של הפרויקט באמצעות אחת מהפקודות הבאות, ואז משנים את יחסי התלות של הפרויקט לפי הצורך (או משתמשים ב-Bill of Materials):
Maven
mvn dependency:treeGradle
./gradlew dependenciesאם אי אפשר לפתור את ההתנגשויות בין יחסי התלות, אפשר להסתמך במקום זאת על הגרסה המוצללת של הספרייה:
Maven
<dependency> <groupId>com.google.api-ads</groupId> <artifactId>google-ads-shadowjar</artifactId> <version>48.1.0</version> </dependency>
Gradle
implementation 'com.google.api-ads:google-ads-shadowjar:48.1.0'