במדריך הזה מוסבר איך להתאים אישית כמה מההיבטים המתקדמים יותר של ספריית הלקוח של Java. דפוס נפוץ הוא שרבות מהתכונות האלה מסתמכות על Callable הבסיסי ולא על שיטות הנוחות הרגילות. בדרך כלל, הפונקציה 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() (או לשיטת גישה ספציפית לגרסה כמו getVersion25()) יוצרת חיבור בסיסי חדש ומשאבים משויכים.
חשוב לסגור את לקוח השירות כשאין בו יותר צורך. אפשר לעשות את זה בבלוק try-with-resources או על ידי קריאה ל-close() בלקוח השירות.
אם תנסו להשתמש בלקוח שירות סגור כדי לשלוח בקשות API, ה-method של לקוח השירות יחזיר java.util.concurrent.RejectedExecutionException.
הפריסה ב-App Engine נכשלת אם קובץ ה-JAR גדול מ-32MB
ב-App Engine, כל קובץ שמעלים יכול להיות בגודל של עד 32MB. קובץ ה-JAR של google-ads
גדול משמעותית, במיוחד כשמשתמשים בפריסות של shade או shadow JAR. אם פורסים קובצי JAR באופן ידני, יכול להיות שתקבלו שגיאות כמו:
ERROR: (gcloud.app.deploy) Cannot upload file [<your-app>/WEB-INF/lib/google-ads-47.0.0.jar],
which has size [66095767] (greater than maximum allowed size of [33554432])
במקום זאת, אפשר לפרוס באמצעות התוסף Gradle או התוסף Maven של App Engine. כל פלאגין מספק אפשרות enableJarSplitting
לפצל כל JAR לחלקים של 10MB ולהעלות אותם במקום זאת.
יחסי תלות של צללים
אם בפרויקט יש תלויות שמתנגשות עם התלויות של הספרייה, בודקים את היררכיית התלויות של הפרויקט באמצעות אחת מהפקודות הבאות, ואז משנים את התלויות של הפרויקט לפי הצורך (או משתמשים ברשימת החומרים):
Maven
mvn dependency:treeGradle
./gradlew dependenciesאם אי אפשר לפתור את הבעיות שנובעות מהתלות, אפשר להסתמך על הגרסה המוצללת של הספרייה:
Maven
<dependency> <groupId>com.google.api-ads</groupId> <artifactId>google-ads-shadowjar</artifactId> <version>47.0.0</version> </dependency>
Gradle
implementation 'com.google.api-ads:google-ads-shadowjar:47.0.0'