במדריך הזה מוסבר איך להתאים אישית כמה מההיבטים המתקדמים יותר של ספריית הלקוח ב-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() (או לשיטת גישה ספציפית לגרסה כמו 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.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>48.0.0</version> </dependency>
Gradle
implementation 'com.google.api-ads:google-ads-shadowjar:48.0.0'