你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

快速入门:向 Go Gin Web 应用添加功能标志

在本快速入门中,你将在 Azure 应用配置中创建一个功能标志,并使用它在 Go Gin Web 应用中动态控制新网页的可用性,而无需重启或重新部署它。

功能管理支持扩展了应用程序配置中的动态配置功能。 此示例演示如何使用实时更新和条件页面呈现将功能标志集成到 Go Gin Web 应用程序中。

先决条件

创建功能标志

将名为Beta的功能标志添加到应用配置存储中,并将LabelDescription保留为默认值。 有关如何使用 Azure 门户或 CLI 将功能标志添加到商店的信息,请转到 创建功能标志

创建功能标志的屏幕截图。

创建 Go Web 应用程序

  1. 为 Go 项目创建新目录并导航到它:

    mkdir gin-feature-flag-quickstart
    cd gin-feature-flag-quickstart
    
  2. 初始化新的 Go 模块:

    go mod init gin-feature-flag-quickstart
    
  3. 为 Azure 应用配置、Gin Web 框架和功能管理安装所需的 Go 包:

    go get github.com/gin-gonic/gin
    go get github.com/microsoft/Featuremanagement-Go/featuremanagement
    go get github.com/microsoft/Featuremanagement-Go/featuremanagement/providers/azappconfig
    
  4. 为 HTML 模板创建模板目录。

    mkdir templates
    
  5. 为主页创建 HTML 模板。 将以下内容添加到 templates/index.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>{{.title}}</title>
        <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
    </head>
    <body>
        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
            <div class="container">
                <a class="navbar-brand" href="/">TestAppConfig</a>
                <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                        aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
                    <ul class="navbar-nav flex-grow-1">
                        <li class="nav-item">
                            <a class="nav-link text-dark" href="/">Home</a>
                        </li>
                        {{if .betaEnabled}}
                        <li class="nav-item">
                            <a class="nav-link text-dark" href="/beta">Beta</a>
                        </li>
                        {{end}}
                    </ul>
                </div>
            </div>
        </nav>    <div class="container">
            <div class="row justify-content-center">
                <div class="col-md-8 text-center">
                    <h1>Hello from Azure App Configuration</h1>
            </div>
        </div>
    
        <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
    </body>
    </html>
    
  6. 为 beta 页面创建 HTML 模板。 将以下内容添加到 templates/beta.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>{{.title}}</title>
        <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
    </head>
    <body>
        <!-- Navigation -->    <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
            <div class="container">
                <a class="navbar-brand" href="/">TestAppConfig</a>
                <div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
                    <ul class="navbar-nav flex-grow-1">
                        <li class="nav-item">
                            <a class="nav-link text-dark" href="/">Home</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" href="/beta">Beta</a>
                        </li>
                    </ul>
                </div>
            </div>
        </nav>    <div class="container">
            <div class="row justify-content-center">
                <div class="col-md-8 text-center">
                    <h1>This is the beta website.</h1>
                </div>
            </div>
        </div>
    
        <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
    </body>
    </html>
    

使用功能标志

  1. options更新以在上一步中启用功能标志。

        options := &azureappconfiguration.Options{
            FeatureFlagOptions: azureappconfiguration.FeatureFlagOptions{
                Enabled: true,
                RefreshOptions: azureappconfiguration.RefreshOptions{
                    Enabled: true,
                },
            },
        }
    

    小窍门

    当在 FeatureFlagOptions 中未指定选择器时,它会加载应用配置存储库中所有无标签的功能开关。 功能标志的默认刷新间隔为 30 秒。 可以通过 RefreshOptions 参数自定义此行为。 例如,以下代码片段仅加载键名以“TestApp:”开头的,并具有标签“dev”的功能标志。 该代码还将刷新间隔时间更改为 5 分钟。 请注意,此刷新间隔时间与常规键值的刷新间隔时间不同。

    FeatureFlagOptions{
        Enabled: true,
        Selectors: []azureappconfiguration.Selector{
            {
                KeyFilter:   "TestApp:*",
                LabelFilter: "dev",
            },
        },
        RefreshOptions: azureappconfiguration.RefreshOptions{
            Enabled: true,
            Interval: 5 * time.Minute,
        },
    }
    
  2. 创建包含以下内容的文件 main.go

    package main
    
    import (
        "context"
        "fmt"
        "log"
        "net/http"
        "os"
    
        "github.com/Azure/AppConfiguration-GoProvider/azureappconfiguration"
        "github.com/gin-gonic/gin"
        "github.com/microsoft/Featuremanagement-Go/featuremanagement"
        "github.com/microsoft/Featuremanagement-Go/featuremanagement/providers/azappconfig"
    )
    
    type WebApp struct {
        featureManager *featuremanagement.FeatureManager
        appConfig      *azureappconfiguration.AzureAppConfiguration
    }
    
    func (app *WebApp) refreshMiddleware() gin.HandlerFunc {
        return func(c *gin.Context) {
            go func() {
                ctx := context.Background()
                if err := app.appConfig.Refresh(ctx); err != nil {
                    log.Printf("Error refreshing configuration: %v", err)
                }
            }()
            c.Next()
        }
    }
    
    func (app *WebApp) featureMiddleware() gin.HandlerFunc {
        return func(c *gin.Context) {
            // Check if Beta feature is enabled
            betaEnabled, err := app.featureManager.IsEnabled("Beta")
            if err != nil {
                log.Printf("Error checking Beta feature: %v", err)
                betaEnabled = false
            }
    
            // Store feature flag status for use in templates
            c.Set("betaEnabled", betaEnabled)
            c.Next()
        }
    }
    
    func (app *WebApp) setupRoutes(r *gin.Engine) {
        r.Use(app.refreshMiddleware())
        r.Use(app.featureMiddleware())
    
        // Load HTML templates
        r.LoadHTMLGlob("templates/*.html")
    
        // Routes
        r.GET("/", app.homeHandler)
        r.GET("/beta", app.betaHandler)
    }
    
    // Home page handler
    func (app *WebApp) homeHandler(c *gin.Context) {
        betaEnabled := c.GetBool("betaEnabled")
    
        c.HTML(http.StatusOK, "index.html", gin.H{
            "title":       "Feature Management Example App",
            "betaEnabled": betaEnabled,
        })
    }
    
    // Beta page handler
    func (app *WebApp) betaHandler(c *gin.Context) {
        betaEnabled := c.GetBool("betaEnabled")
    
        if !betaEnabled {
            return
        }
    
        c.HTML(http.StatusOK, "beta.html", gin.H{
            "title": "Beta Page",
        })
    }
    
    func main() {
        ctx := context.Background()
    
        // Load Azure App Configuration
        appConfig, err := loadAzureAppConfiguration(ctx)
        if err != nil {
            log.Fatalf("Error loading Azure App Configuration: %v", err)
        }
    
        // Create feature flag provider
        featureFlagProvider, err := azappconfig.NewFeatureFlagProvider(appConfig)
        if err != nil {
            log.Fatalf("Error creating feature flag provider: %v", err)
        }
    
        // Create feature manager
        featureManager, err := featuremanagement.NewFeatureManager(featureFlagProvider, nil)
        if err != nil {
            log.Fatalf("Error creating feature manager: %v", err)
        }
    
        // Create web app
        app := &WebApp{
            featureManager: featureManager,
            appConfig:      appConfig,
        }
    
        // Set up Gin with default middleware (Logger and Recovery)
        r := gin.Default()
    
        // Set up routes
        app.setupRoutes(r)
    
        // Start server
        fmt.Println("Starting server on http://localhost:8080")
        fmt.Println("Open http://localhost:8080 in your browser")
        fmt.Println("Toggle the 'Beta' feature flag in Azure portal to see changes")
        fmt.Println()
    
        if err := r.Run(":8080"); err != nil {
            log.Fatalf("Failed to start server: %v", err)
        }
    }
    

运行 Web 应用程序

  1. 设置身份验证的环境变量并运行应用程序。

    go mod tidy
    go run .
    
  2. 打开浏览器窗口,然后转到 http://localhost:8080。 浏览器应显示类似于下图的页面。

    启用功能标志之前 gin Web 应用的屏幕截图。

  3. 登录到 Azure 门户。 选择“所有资源”,然后选择先前创建的应用程序配置存储

  4. 选择“功能管理器”并找到“Beta”功能标志。 通过选中“已启用”下的复选框来启用该标志

  5. 多次刷新浏览器。 刷新间隔时间窗口通过时,页面会显示更新的内容:

    启用功能标志后 gin Web 应用的屏幕截图。

  6. 请注意, Beta 菜单项现在显示在导航栏中。 单击它以访问 beta 页面:

    gin Web 应用 beta 页面的屏幕截图。

清理资源

如果不想继续使用本文中创建的资源,请删除此处创建的资源组以避免产生费用。

重要

删除资源组的操作不可逆。 将永久删除资源组以及其中的所有资源。 请确保不要意外删除错误的资源组或资源。 如果在包含要保留的其他资源的资源组中创建了本文的资源,请从相应的窗格中单独删除每个资源,而不是删除该资源组。

  1. 登录到 Azure 门户,然后选择“资源组”。
  2. 按名称筛选框中,输入资源组的名称。
  3. 在结果列表中,选择资源组名称以查看概述。
  4. 选择“删除资源组”。
  5. 系统会要求确认是否删除资源组。 重新键入资源组的名称进行确认,然后选择“删除”。

片刻之后,将会删除该资源组及其所有资源。

后续步骤

在本快速入门中,你在 Azure 应用配置中创建一个功能标志,并在 Go Gin Web 应用程序中使用它。 功能管理 Go 库提供与 Azure 应用配置无缝集成的功能标志功能。有关更多功能,请继续阅读以下文档。

虽然使用功能标志可以在应用中激活或停用功能,但你可能希望根据应用的逻辑自定义功能标志。 使用功能筛选器可以按条件启用功能标志。 有关详细信息,请继续阅读以下教程。

Azure 应用程序配置提供了内置的功能筛选器,使你可以仅在特定的时段或者仅对应用的特定目标受众激活功能标志。 有关详细信息,请继续阅读以下教程。