本指南介绍了如何将 Go 应用与 App Lifecycle Manager 功能标志集成。您将了解如何将 OpenFeature SDK 与 flagd 提供方搭配使用,以评估由 App Lifecycle Manager 管理的标志,从而动态控制 Go 服务中的功能可用性和行为。
本指南假定您已通过完成以下其中一个快速入门指南设置了必要的 App Lifecycle Manager 资源(例如 SaaS 产品、单元类型、单元、标志和发布):
- 快速入门:使用 App Lifecycle Manager 部署功能标志(集成):如果您使用 App Lifecycle Manager 管理应用部署。
- 快速入门:单独使用功能标志:如果您独立管理应用基础架构,但想要使用 App Lifecycle Manager 进行功能标志管理。
前提条件
在开始之前,请确保您具备以下条件:
- 已安装 Go: 1.23 版或更高版本。
- 已完成 App Lifecycle Manager 功能标志快速入门:
已针对应用默认凭据 (ADC) 进行了
gcloud身份验证: Go 应用使用 ADC 向 Google Cloud 服务进行身份验证。如果在本地运行(用于独立使用或本地 Docker 测试),请确保您已在环境中进行身份验证:gcloud auth application-default loginIAM 权限: 运行 Go 应用的身份需要拥有项目上的
roles/saasconfig.viewerIdentity and Access Management 角色,才能读取标志配置: Google Cloudgcloud projects add-iam-policy-binding YOUR_PROJECT_ID \ --member="user:YOUR_EMAIL_ADDRESS" \ --role="roles/saasconfig.viewer"请相应地替换
YOUR_PROJECT_ID和YOUR_EMAIL_ADDRESS。
了解关键环境变量
您的 Go 应用依赖于环境变量来连接到正确的标志配置并评估预期标志。
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
- 格式:
设置 Go 项目
在运行应用之前,请先初始化模块,并添加必要的初始化和评估逻辑。
创建项目目录:
mkdir go-featureflag-app cd go-featureflag-app go mod init go-featureflag-app创建应用代码: 添加一个名为
main.go的文件,其中包含以下内容,以初始化提供程序并评估标志。package main import ( "context" "fmt" "log" "os" flagd "github.com/open-feature/go-sdk-contrib/providers/flagd/pkg" "github.com/open-feature/go-sdk/openfeature" "google.golang.org/grpc" "google.golang.org/grpc/credentials" "google.golang.org/grpc/credentials/oauth" "google.golang.org/grpc/metadata" ) // GetNewFlagdProvider initializes a flagd provider configured for App Lifecycle Manager func GetNewFlagdProvider(ctx context.Context) (*flagd.Provider, error) { providerID := os.Getenv("FLAGD_SOURCE_PROVIDER_ID") if providerID == "" { return nil, fmt.Errorf("FLAGD_SOURCE_PROVIDER_ID environment variable is not set") } creds, err := oauth.NewApplicationDefault(ctx) if err != nil { return nil, err } // Interceptor to inject the Unit name into headers for regional routing routingInterceptor := func(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) { md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("name=%s", providerID)) ctx = metadata.NewOutgoingContext(ctx, md) return streamer(ctx, desc, cc, method, opts...) } options := []flagd.ProviderOption{ flagd.WithHost("saasconfig.googleapis.com"), flagd.WithPort(443), flagd.WithInProcessResolver(), flagd.WithProviderID(providerID), flagd.WithGrpcDialOptionsOverride([]grpc.DialOption{ grpc.WithTransportCredentials(credentials.NewTLS(nil)), grpc.WithPerRPCCredentials(creds), grpc.WithStreamInterceptor(routingInterceptor), }), } return flagd.NewProvider(options...) } // InitializeFeatureManagement registers the provider globally func InitializeFeatureManagement(ctx context.Context) error { provider, err := GetNewFlagdProvider(ctx) if err != nil { return err } openfeature.SetProvider(provider) return nil } func main() { ctx := context.Background() InitializeFeatureManagement(ctx); // 1. Get Client client := openfeature.NewClient("simple-api") // 2. Create Evaluation Context evalCtx := openfeature.NewEvaluationContext() // 3. Evaluate Flag // Default to false if evaluation fails isEnhanced, err := client.BooleanValue(context.Background(), "enhanced-search", false, evalCtx) if err != nil { log.Printf("Flag evaluation failed: %v", err) } // 4. Return response if isEnhanced { fmt.Println("Enhanced search feature is enabled.") } else { fmt.Println("Enhanced search feature is disabled.") } }创建 go.mod: 使用特定版本可确保稳定性。
module go-featureflag-app go 1.23 require ( github.com/open-feature/go-sdk v1.15.1 github.com/open-feature/go-sdk-contrib/providers/flagd v0.3.0 google.golang.org/grpc v1.74.2 golang.org/x/oauth2 v0.22.0 )获取依赖项:
go mod tidy go mod download
运行 Go 应用
您可以在本地使用独立配置执行应用,也可以将其部署为容器。
独立运行(在本地)
设置环境变量:
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}"运行应用:
go run main.go
集成运行(容器化)
创建 Dockerfile:
FROM golang:1.23 as builder WORKDIR /app COPY go.mod go.sum ./ RUN go mod download COPY . . RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o /go-featureflag-app . FROM gcr.io/distroless/static-debian11 WORKDIR / COPY --from=builder /go-featureflag-app /go-featureflag-app ENTRYPOINT ["/go-featureflag-app"]构建并推送映像:
export PROJECT_ID="your-gcp-project-id" docker build -t gcr.io/${PROJECT_ID}/my-go-app:latest . docker push gcr.io/${PROJECT_ID}/my-go-app:latest部署服务: 更新单元蓝图以引用
gcr.io/${PROJECT_ID}/my-go-app:latest,并使用 App Lifecycle Manager 发布部署新版本。
验证标志更改
应用运行后,请确认其可以正确评估标志。
- 观察初始值: 验证输出是否记录了与初始状态对应的值。
- 在 App Lifecycle Manager 中更新标志: 使用 Google Cloud 控制台或
gcloud修改标志行为。 - 验证更新后的值: 重新运行本地编译或观察容器日志,以查看更新后的结果。
后续步骤
- 如需了解更多概念详情,请参阅App Lifecycle Manager 功能标志概览。
- 了解 App Lifecycle Manager 发布,以便更安全地部署标志。
- 查看 App Lifecycle Manager 主要概览。