本指南介绍了如何将 Java 应用与 App Lifecycle Manager 功能标志集成。您将了解如何将 OpenFeature SDK 与 flagd 提供程序搭配使用,以评估由 App Lifecycle Manager 管理的标志,从而动态控制 Java 服务中的功能可用性和行为。
本指南假定您已完成以下任一快速入门,设置了必要的 App Lifecycle Manager 资源(例如 SaaS 产品、单元类型、单元、标志和发布):
- 快速入门:使用 App Lifecycle Manager 部署功能标志(集成):如果您使用 App Lifecycle Manager 管理应用部署。
- 快速入门:单独使用功能标志:如果您独立管理应用基础架构,但想要使用 App Lifecycle Manager 进行功能标志管理。
前提条件
在开始之前,请确保您具备以下条件:
- 已安装 Java: JDK 17 或更高版本。
- 已完成 App Lifecycle Manager 功能标志快速入门:
已针对应用默认凭据 (ADC) 进行了
gcloud身份验证: Java 应用使用 ADC 向 Google Cloud 服务进行身份验证。确保您已在环境中进行身份验证:gcloud auth application-default loginIAM 权限: 运行 Java 应用的身份需要对您的 Google Cloud 项目拥有
roles/saasconfig.viewerIdentity and Access Management 角色,才能读取标志配置: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:指定要从 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添加依赖项: 配置构建系统(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}"运行应用: 使用您首选的构建工具命令(例如
mvn compile exec:java或./gradlew run)执行项目。
集成运行(容器化)
创建 Dockerfile: 定义用于打包 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 发布部署新版本。
验证标志更改
应用运行后,请确认其可以正确评估标志。
- 观察初始值: 验证控制台输出是否记录了与初始配置状态对应的评估值。
- 在 App Lifecycle Manager 中更新标志: 使用 Google Cloud 控制台或
gcloud修改标志载荷或定位规则。 - 验证更新后的值: 重新运行本地执行或观察容器日志,以确认新的评估状态。
后续步骤
- 如需了解更多概念详情,请参阅App Lifecycle Manager 功能标志概览。
- 了解 App Lifecycle Manager 发布,以更安全地部署标志。
- 查看 App Lifecycle Manager 主要概览。