במדריך הזה מוסבר איך לשלב את אפליקציות Java עם ה-feature flags של App Lifecycle Manager. תלמדו איך להשתמש ב-OpenFeature SDK עם הספק flagd כדי להעריך דגלים שמנוהלים על ידי App Lifecycle Manager, וכך לשלוט באופן דינמי בזמינות ובהתנהגות של תכונות בשירותי Java שלכם.
במדריך הזה אנחנו יוצאים מנקודת הנחה שכבר הגדרתם את המשאבים הנדרשים של App Lifecycle Manager (כמו הצעות לאפליקציות, סוגי יחידות, יחידות, דגלים והשקות) על ידי השלמת אחד מהמדריכים למתחילים הבאים:
- מדריך למתחילים: פריסת feature flag באמצעות App Lifecycle Manager (משולב): אם אתם מנהלים את פריסות האפליקציות שלכם באמצעות App Lifecycle Manager.
- מדריך למתחילים: שימוש ב-feature flags באופן עצמאי: אם אתם מנהלים את תשתית האפליקציה באופן עצמאי, אבל רוצים להשתמש ב-App Lifecycle Manager כדי לנהל את ה-feature flags.
דרישות מוקדמות
לפני שמתחילים, חשוב לוודא שהתנאים הבאים מתקיימים:
- Java מותקן: JDK 17 ואילך.
- השלמתם את המדריך למתחילים בנושא Feature flags ב-App Lifecycle Manager:
אימות של
gcloudל-Application Default Credentials (ADC): אפליקציית Java משתמשת ב-ADC כדי לאמת את שירותי Google Cloud . מוודאים שביצעתם אימות בסביבה שלכם:gcloud auth application-default loginהרשאות IAM: הזהות שמריצה את אפליקציית Java צריכה את התפקיד
roles/saasconfig.viewerבניהול הזהויות והרשאות הגישה (IAM) בפרויקט Google Cloud כדי לקרוא הגדרות של דגלים:gcloud projects add-iam-policy-binding YOUR_PROJECT_ID \ --member="user:YOUR_EMAIL_ADDRESS" \ --role="roles/saasconfig.viewer"מחליפים את
YOUR_PROJECT_IDואתYOUR_EMAIL_ADDRESSבהתאם.
הסבר על משתני סביבה מרכזיים
אפליקציית Java מסתמכת על משתני סביבה כדי להתחבר להגדרת הדגל הנכונה.
-
FLAGD_SOURCE_PROVIDER_ID: מציין איזו הגדרה של feature flag צריך לאחזר משירות App Lifecycle Manager. הוא צריך להיות שם המשאב המלא שלFeatureFlagConfigשמשויך ליחידה שלכם.- פורמט:
projects/PROJECT_ID/locations/LOCATION/featureFlagsConfigs/UNIT_ID - לדוגמה:
projects/my-gcp-project/locations/us-central1/featureFlagsConfigs/my-app-instance-01
- פורמט:
הגדרת פרויקט Java
כדי להריץ את האפליקציה, צריך להפעיל את הפרויקט ולהגדיר את יחסי התלות הנדרשים.
יוצרים ספריית פרויקט:
mkdir java-featureflag-app cd java-featureflag-appהוספת יחסי תלות: מגדירים את מערכת ה-build (Maven או Gradle) כך שתכלול את הספריות הבאות. כדי להבטיח תאימות, צריך להשתמש בגרסאות חדשות יותר מ-OpenFeature 1.14.1, flagd 0.11.5 ו-gRPC 1.71.0.
dev.openfeature:javasdk:1.14.1+dev.openfeature.contrib.providers:flagd:0.11.5+io.grpc:grpc-netty-shaded:1.71.0+io.grpc:grpc-auth:1.71.0+com.google.auth:google-auth-library-oauth2-http
יוצרים את קוד האתחול: מוסיפים קובץ בשם
FeatureManagement.javaעם התוכן הבא. המחלקות האלה מגדירות מיירטי gRPC כדי לצרף כותרות של ADC וניתוב אזורי, ומבצעות אתחול שלFlagdProviderבאמצעות רזולוציה בתוך התהליך.import com.google.auth.oauth2.GoogleCredentials; import dev.openfeature.contrib.providers.flagd.Config; import dev.openfeature.contrib.providers.flagd.FlagdOptions; import dev.openfeature.contrib.providers.flagd.FlagdProvider; import dev.openfeature.sdk.OpenFeatureAPI; import io.grpc.*; import io.grpc.auth.MoreCallCredentials; import java.util.ArrayList; import java.util.List; public class FeatureManagement { public static void initialize() throws Exception { // Read the full Unit resource name String flagConfigId = System.getenv("FLAGD_SOURCE_PROVIDER_ID"); if (flagConfigId == null || flagConfigId.isEmpty()) { throw new IllegalStateException("FLAGD_SOURCE_PROVIDER_ID environment variable is not set."); } // Configure gRPC Security and Routing GoogleCredentials credentials = GoogleCredentials.getApplicationDefault(); CallCredentials callCredentials = MoreCallCredentials.from(credentials); List<ClientInterceptor> interceptors = new ArrayList<>(); // Interceptor to inject the Unit name into headers for regional routing interceptors.add(new ClientInterceptor() { @Override public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(MethodDescriptor<ReqT, RespT> method, CallOptions callOptions, Channel next) { return new ForwardingClientCall.SimpleForwardingClientCall<ReqT, RespT>(next.newCall(method, callOptions)) { @Override public void start(Listener<RespT> responseListener, Metadata headers) { headers.put(Metadata.Key.of("x-goog-request-params", Metadata.ASCII_STRING_MARSHALLER), "name=" + flagConfigId); super.start(responseListener, headers); } }; } }); // Interceptor to attach ADC to the gRPC calls interceptors.add(new ClientInterceptor() { @Override public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(MethodDescriptor<ReqT, RespT> method, CallOptions callOptions, Channel next) { return next.newCall(method, callOptions.withCallCredentials(callCredentials)); } }); // Initialize the flagd provider with In-Process resolution FlagdProvider provider = new FlagdProvider( FlagdOptions.builder() .resolverType(Config.Resolver.IN_PROCESS) .host("saasconfig.googleapis.com").port(443) .tls(true) .providerId(flagConfigId) .clientInterceptors(interceptors) .syncMetadataDisabled(true) .deadline(10000) .build() ); // Set the global provider OpenFeatureAPI.getInstance().setProviderAndWait(provider); } }יוצרים את הלוגיקה של האפליקציה: מוסיפים קובץ בשם
Main.javaעם התוכן הבא כדי להריץ את הערכת ההגדרה.import dev.openfeature.sdk.OpenFeatureAPI; import dev.openfeature.sdk.MutableContext; public class Main { public static void main(String[] args) throws Exception { // 1. Get Client var client = OpenFeatureAPI.getInstance().getClient("simple-api"); // 2. Create Evaluation Context var context = new dev.openfeature.sdk.MutableContext(); // 3. Evaluate Flag // Default to false if evaluation fails or service is unreachable boolean isEnhanced = client.getBooleanValue("enhanced-search", false, context); // 4. Execute business logic based on result if (isEnhanced) { System.out.println("Executing enhanced search algorithm..."); } else { System.out.println("Standard search algorithm..."); } } }
הפעלת אפליקציית Java
אתם יכולים להריץ את האפליקציה באופן מקומי באמצעות ההגדרות העצמאיות, או לפרוס אותה כקונטיינר.
הרצה באופן עצמאי (מקומית)
הגדרה של משתני סביבה:
export PROJECT_ID="your-gcp-project-id" export LOCATION_1="us-central1" export UNIT_ID="my-app-instance-01" export FLAGD_SOURCE_PROVIDER_ID="projects/${PROJECT_ID}/locations/${LOCATION_1}/featureFlagsConfigs/${UNIT_ID}"מריצים את האפליקציה: מריצים את הפרויקט באמצעות פקודת כלי ה-build המועדפת (למשל,
mvn compile exec:javaאו./gradlew run).
הפעלה משולבת (בקונטיינרים)
יוצרים קובץ Dockerfile: מגדירים את ה-build של הקונטיינר שכולל את הקובץ הבינארי של Java.
FROM maven:3.9-eclipse-temurin-17 AS builder WORKDIR /app COPY pom.xml . COPY src ./src RUN mvn clean package FROM eclipse-temurin:17-jre WORKDIR /app COPY --from=builder /app/target/java-featureflag-app.jar app.jar ENTRYPOINT ["java", "-jar", "app.jar"]יוצרים את קובץ האימג' ושולחים אותו:
export PROJECT_ID="your-gcp-project-id" docker build -t gcr.io/${PROJECT_ID}/my-java-app:latest . docker push gcr.io/${PROJECT_ID}/my-java-app:latestפריסת השירות: מעדכנים את תוכנית היחידה כך שתפנה אל
gcr.io/${PROJECT_ID}/my-java-app:latestופורסים את הגרסה החדשה באמצעות השקה של App Lifecycle Manager.
אימות השינויים בדגלים
אחרי שהאפליקציה פועלת, צריך לוודא שהיא מעריכה את ה-flags בצורה נכונה.
- בודקים את הערך הראשוני: מוודאים שערך ההערכה שמתאים למצב ההגדרה הראשוני מתועד בפלט של המסוף.
- עדכון הדגל ב-App Lifecycle Manager: משנים את מטען הדגל או את כללי הטירגוט באמצעות Google Cloud console או
gcloud. - מאמתים את הערך המעודכן: מריצים מחדש את ההפעלה המקומית או בודקים את יומני הקונטיינר כדי לאשר את המצב החדש שהוערך.
המאמרים הבאים
- למידע נוסף על הקונספט, קראו את הסקירה הכללית על ה-feature flags של App Lifecycle Manager.
- מידע נוסף על השקות של App Lifecycle Manager
- קוראים את הסקירה הכללית הראשית של App Lifecycle Manager.