App全局配置表设计

简介: 运营过程中,我们会碰到需要以App版本为维度,去定制一些App配置变量

概述

运营过程中,我们会碰到需要以App版本为维度,去定制一些App配置变量。如版本更新描述,App最低可用版本等。有时也会需要有动态变更一些配置的能力,比如客诉反馈邮箱,促销活动入口开闭等。

为此,我们设计了App全局配置表模块,即可是满足集中管理App配置,也能满足App配置动态变更的需求。

配置的管理与下发

我们需要为客户端提供一个的服务端API,用于配置表的下发,多为JSON表的形式。

下面是一个简单的实现,客户端上报版本号和请求时间,服务端可以根据版本号来选择下发的配置表。

随着配置表的演进,服务端会把配置迁移到数据库存储,再衍生出后台进行可视化的配置管理。

type AppGlobalConfigRequest struct {
   
    BuildVersion string `json:"build_version"  binding:"required"`
    AppVersion   string `json:"app_version"  binding:"required"`
    Time         string `json:"time"  binding:"required"`
}

func AppGlobalConfig(w http.ResponseWriter, r *http.Request) {
   
  var reqBody map[string]interface{
   }
    if err := json.NewDecoder(r.Body).Decode(&reqBody); err != nil {
   
        log.Printf("AppGlobalConfig reqBody json.NewDecoder: %v", err)
        http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
        return
    }

    var reqParams AppGlobalConfigRequest
    data := reqBody["data"]
    dataJSONString, _ := json.Marshal(data)
    if err := json.Unmarshal([]byte(dataJSONString), &reqParams); err != nil {
   
        log.Printf("AppGlobalConfig reqParams json.Unmarshal: %v", err)
        http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest)
        return
    }

    config := map[string]interface{
   }{
   
        "version":                  2022091901,
        "user_initial_trial_count": 2,
        "create_date":              "2022-09-19T02:58:31Z",
    }
    response := map[string]interface{
   }{
   
        "data": config,
    }
    responseString, _ := json.Marshal(response)
    fmt.Fprintf(w, string(responseString))
}

配置的更新与持久化

配置的更新

为了保证配置的实效性,App初始化时,以及App从后台唤醒时,都需要检测配置的更新。

class AppConfigModule: SpaceportModuleProtocol {
   
    var loaded = false

    static func modulePriority() -> Int {
    return 2895 }

    func loadModule() {
   
        AppConfigManager.shared.fetchGlobalConfig()
    }

    func unloadModule() {
    }

    func applicationWillEnterForeground(notification: Notification) {
   
        AppConfigManager.shared.fetchGlobalConfig()
    }
}

配置表模型

配置表里包含了三个字段,其中userInitialTrialCount是配置信息,configVersioncreateDate均为配置表的描述信息。

本地的配置表需要有默认值。当出现API请求失败,或者API配置表解析错误时,可以用默认配置保证功能正常使用。

private let defaultUserInitialTrialCount = 2
public struct GlobalConfig: Codable {
   
    /// 配置版本号
    let configVersion: Int
    /// 用户初始试用次数
    let userInitialTrialCount: Int
    /// 生成时间 如:2022-09-19T02:58:31Z
    let createDate: String

    enum CodingKeys: String, CodingKey {
   
        case configVersion = "version"
        case userInitialTrialCount = "user_initial_trial_count"
        case createDate = "create_date"
    }

    init() {
   
        self.configVersion = 0
        self.userInitialTrialCount = defaultUserInitialTrialCount
        self.createDate = Date().axv.toISO8601String()
    }
}

配置表持久化

配置表的持久化和一般模型的持久化基本相同,可以选择Sqlite,JSON File,甚至内存缓存的形式,可根据配置表的数据规模和响应要求来选择。

目前我们选用UserDefault来管理配置表的持久化,即用Plist文件存储的配置表信息。

为了避免配置表频繁持久化,需要对配置的版本进行筛选,低于当前环境的版本可以被抛弃。

enum AppConfig: String {
   
    /// App全局配置 GlobalConfig
    case globalConfig
}

private let appConfigUserDefaults = UserDefaultsManager(suiteName: "com.pe.AppConfig").userDefaults

extension AppConfig: UserDefaultPreference {
   
    var userDefaults: UserDefaults {
    return appConfigUserDefaults }
}

class AppConfigManager {
   
    public static let shared = AppConfigManager()
    private init() {
   }

    lazy var globalConfig: GlobalConfig = {
   
        guard let config = AppConfig.globalConfig.codableObject(GlobalConfig.self) else {
   
            return GlobalConfig()
        }
        return config
    }() {
   
        didSet {
   
            AppConfig.globalConfig.save(codableObject: globalConfig)
        }
    }

    /// 获取配置
    func fetchGlobalConfig() {
   
        Task {
   
            do {
   
                if let config = try await GlobalConfigRequest().request() {
   
                    if config.configVersion > globalConfig.configVersion {
   
                        globalConfig = config
                        logDebug("GlobalConfig Updated: \(globalConfig)", tag: .kLogTag)
                    }
                }
            } catch {
   
                logWarn("got error: \(error)", tag: .kLogTag)
            }
        }
    }
}

总结

配置表下发是一种常用的App配置动态管理方案。

设计方案时需要满足快速的响应速度,便捷的存取API,方便维护的模型,以及对机能的低消耗。

根据业务场景的不同,还可以扩展出配置表版本管理,多级配置表的关联使用,配置信息变更通知等不同的不同的功能点。

目录
相关文章
|
2月前
|
移动开发 开发框架 小程序
uni-app:demo&媒体文件&配置全局的变量(三)
uni-app 是一个使用 Vue.js 构建多平台应用的框架,支持微信小程序、支付宝小程序、H5 和 App 等平台。本文档介绍了 uni-app 的基本用法,包括登录示例、媒体文件处理、全局变量配置和 Vuex 状态管理的实现。通过这些示例,开发者可以快速上手并高效开发多平台应用。
|
4月前
【Azure 应用服务】Web App Service 中的 应用程序配置(Application Setting) 怎么获取key vault中的值
【Azure 应用服务】Web App Service 中的 应用程序配置(Application Setting) 怎么获取key vault中的值
|
4月前
|
Java 应用服务中间件 Windows
【应用服务 App Service】App Service 中部署Java项目,查看Tomcat配置及上传自定义版本
【应用服务 App Service】App Service 中部署Java项目,查看Tomcat配置及上传自定义版本
|
3月前
【Azure Logic App】使用Event Hub 连接器配置 Active Directory OAuth 认证无法成功连接到中国区Event Hub的解决之法
An exception occurred while retrieving properties for Event Hub: logicapp. Error Message: 'ClientSecretCredential authentication failed: AADSTS90002: Tenant 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' not found. Check to make sure you have the correct tenant ID and are signing into the correct cloud. Che
|
4月前
|
开发框架 .NET Windows
【App Service】在App Service中配置Virtual applications and directories,访问目录中的静态文件报错404
【App Service】在App Service中配置Virtual applications and directories,访问目录中的静态文件报错404
|
4月前
|
C++
【Azure Logic App】使用Event Hub 连接器配置 Active Directory OAuth 认证无法成功连接到中国区Event Hub
【Azure Logic App】使用Event Hub 连接器配置 Active Directory OAuth 认证无法成功连接到中国区Event Hub
|
4月前
|
Java 应用服务中间件 开发工具
[App Service for Windows]通过 KUDU 查看 Tomcat 配置信息
[App Service for Windows]通过 KUDU 查看 Tomcat 配置信息
|
4月前
|
Java 应用服务中间件 Windows
【App Service for Windows】为 App Service 配置自定义 Tomcat 环境
【App Service for Windows】为 App Service 配置自定义 Tomcat 环境
|
4月前
|
Java
【Azure 应用服务】如何查看App Service Java堆栈JVM相关的参数默认配置值?
【Azure 应用服务】如何查看App Service Java堆栈JVM相关的参数默认配置值?
【Azure 应用服务】如何查看App Service Java堆栈JVM相关的参数默认配置值?
|
4月前
|
Linux C++ Docker
【Azure Developer】在Github Action中使用Azure/functions-container-action@v1配置Function App并成功部署Function Image
【Azure Developer】在Github Action中使用Azure/functions-container-action@v1配置Function App并成功部署Function Image

热门文章

最新文章