首页 > 其他分享 >新手教学系列——简单的服务配置项集中管理

新手教学系列——简单的服务配置项集中管理

时间:2024-07-17 22:55:39浏览次数:15  
标签:__ key self value 教学 mgr 集中管理 新手 config

前言

在开发和运维过程中,配置管理是一个非常重要但经常被忽视的环节。常用的配置文件格式包括env、ini和yaml等,它们非常适合模块级别的系统配置,尤其是一些敏感信息的配置,例如数据库连接字符串和密码等。但是,对于系统业务级别的配置,通常要求不需要重启服务即可更新,这就是我们今天要介绍的简单配置管理模块的意义所在。

系统配置表

首先,我们需要一个数据库表来存储配置项。这个表包括配置名称、配置值和配置描述等信息。以下是一个使用SQLAlchemy定义的配置表模型:

from sqlalchemy import (
    TEXT,
    TIMESTAMP,
    Column,
    Integer,
    String,
    func,
)

from app.models.base import Base, BaseMixin

class SysConfig(Base, BaseMixin):
    __tablename__ = 'sys_configs'
    __table_args__ = {"comment": "系统配置表"}

    id = Column(Integer, primary_key=True, autoincrement=True, comment='ID')
    cfg_name = Column(String(128), nullable=False, unique=True, comment='配置名称')
    cfg_value = Column(TEXT, nullable=True, comment='配置值')
    cfg_desc = Column(String(128), nullable=True, comment='配置描述')
    updated = Column(
        TIMESTAMP, index=True, server_default=func.now(), onupdate=func.now(), nullable=False, comment='更新时间'
    )

配置管理类

接下来,我们需要一个配置管理类来加载和更新配置。这个类将会以单例模式运行,确保所有地方使用的配置都是一致的,并且在首次创建实例时自动加载所有配置项。我们使用异步操作来确保数据库操作的高效性。

import json
from typing import Any, Dict, Optional, Type, TypeVar, Callable

import orjson
from app.models.sys_config import SysConfig

T = TypeVar('T')

# 获取配置管理单例
async def get_config_manager():
    config_mgr = ConfigManager()
    if not config_mgr.initialized:
        await config_mgr.load_configs()
    return config_mgr

# 配置管理类
class ConfigManager:
    _instance = None

    def __new__(cls, *args, **kwargs):
        if cls._instance is None:
            cls._instance = super(ConfigManager, cls).__new__(cls)
        return cls._instance

    def __init__(self):
        self.configs: Dict[str, str] = {}
        self.initialized = False

    async def load_configs(self):
        cfg_rows = await SysConfig.get_all_async()
        for row in cfg_rows:
            self.configs[row['cfg_name']] = row['cfg_value']
        self.initialized = True
        print("Configurations loaded into memory.")

    async def update_config(self, key: str, value: str, description: str = '', write_to_db=True):
        self.configs[key] = value
        if write_to_db:
            record = {'cfg_name': key, 'cfg_value': value}
            if description:
                record['cfg_desc'] = description
            await SysConfig.upsert_async(records=[record], update_keys=['cfg_name'])
        print(f"Configuration updated: {key} = {value}")

    def _convert(self, key: str, type_: Type[T], default_value: Optional[T] = None) -> T:
        value = self.configs.get(key, default_value)
        if value is None:
            raise KeyError(f"Configuration key '{key}' not found and no default value provided.")
        try:
            if type_ == bool:
                return type_(value.lower() in ['true', '1', 'yes'])
            elif type_ == dict or type_ == list:
                return orjson.loads(value)
            return type_(value)
        except (ValueError, TypeError, json.JSONDecodeError) as e:
            raise ValueError(f"Error converting configuration value '{value}' to type {type_.__name__}: {e}")

    def __getattr__(self, item: str) -> Callable[[str, Optional[Any]], Any]:
        supported_types = {
            'int': int,
            'float': float,
            'bool': bool,
            'str': str,
            'dict': dict,
            'list': list,
            'json': dict,
        }
        if item in supported_types:
            def method(key: str, default_value: Optional[Any] = None) -> Any:
                return self._convert(key, supported_types[item], default_value)
            return method
        raise AttributeError(f"'ConfigManager' object has no attribute '{item}'")

使用示例

现在,我们已经有了一个完整的配置管理模块,让我们看一下如何在实际应用中使用它。以下是一个示例代码,展示了如何获取配置管理器并使用它来获取和更新配置项。

from app.services import config_services

async def main():
    # 获取配置管理器单例
    config_mgr = await config_services.get_config_manager()

    # 更新配置
    await config_mgr.update_config('max_connections', '100', '最大连接数')
    await config_mgr.update_config('enable_feature', 'true', '启用新功能')
    await config_mgr.update_config('custom_dict', '{"key": "value"}', '自定义字典')
    await config_mgr.update_config('custom_list', '["item1", "item2"]', '自定义列表')

    # 获取并转换配置值
    try:
        max_connections = config_mgr.int('max_connections', 10)
        print(f"Max Connections: {max_connections}")
        
        enable_feature = config_mgr.bool('enable_feature', False)
        print(f"Enable Feature: {enable_feature}")
        
        custom_dict = config_mgr.dict('custom_dict', {})
        print(f"Custom Dict: {custom_dict}")
        
        custom_list = config_mgr.list('custom_list', [])
        print(f"Custom List: {custom_list}")
        
    except (KeyError, ValueError) as e:
        print(e)

# 运行异步主函数
import asyncio
asyncio.run(main())

结语

通过上述代码示例,我们展示了如何创建一个简单而有效的配置管理模块,它能够动态加载和更新配置,支持多种数据类型的转换,并且在设计上注重高效和安全性。这个模块对于需要频繁更改业务逻辑配置而不希望重启服务的应用场景特别有用。

欢迎关注【程序员的开发手册】,我们将继续分享更多实用的开发技巧和工具,让您的开发之路更加顺畅。

标签:__,key,self,value,教学,mgr,集中管理,新手,config
From: https://blog.csdn.net/weixin_41701856/article/details/140478712

相关文章

  • 新手学习AIGC的步骤与图谱
    学习人工智能和生成式对话模型(ArtificialIntelligenceandGenerativeConversationalModels)是一项令人兴奋且具有挑战性的任务!以下是一些我认为可行的学习步骤和路径:初学者学习AIGC的步骤:掌握基础知识:学习基本的编程语言,如Python,这是人工智能领域中最常用的语言之......
  • Stable Diffusion新手快速入门教程
    关于Ai绘画,很多人在体验了Midjourney(以下简称MJ)之后,发现它创意能力很强,但可控性比较弱,不便应用,于是转向StableDiffussion(以下简称SD),但又发现SD貌似很复杂。我在后台收得比较多的留言,都是一些很基础的问题咨询,这是这篇文章的写作背景。Ai绘画的算法工具,如果要做一个不一定......
  • Mac新手教程:程序坞里的启动台图标消失了如何解决?
    启动台是Mac系统里放应用程序的地方,用户可以通过启动台打开软件列表。一般为了方便使用会把它放在程序坞,但一些用户程序坞里的启动台的图标不见了,如何找回呢?1、打开Mac上的访达应用程序,2、点击访达窗口左边的“应用程序”,3、在应用程序里,找到启动台,4、将启动台图标拖动到程序坞,......
  • 时间序列模型!(新手教程,特征工程讲解,两个模型通用代码)
    Timeisrelative. Yourbodyhasn'tevenhittheflooryet. I'vespentsomanyyears...peeringthroughtime...lookingatthisexactmoment. ButIcan'tseepastit.简介:(新手向)    时间序列模型在生活中的各个部分都参了一脚,从股票走势到商品销售额的......
  • 【新手硬件工程师学习日记】之电容的九大作用
    1、隔直流隔直流电容作用:阻止直流通过而让交流通过。2、旁路(去耦)高频旁路电容器作用:为交流电路中某些并联的组件提供低阻抗通路。3、耦合耦合电容电路模型作用:作为两个电路之间的连接,允许交流信号通过并传输到下一级电路。......
  • 新手入门 Git 开发
    Git的三个概念提交:commit仓库repository分支branch注意:downloadzip与指令行:gitclone的区别:gitclone是从仓库里下载下来的,会含有一个.git的文件夹,而downloadzip则没有这样的文件夹一些命令操作指令克隆仓库:gitclone初始化仓库:gitinit添加文件到暂存区:gitad......
  • 新手打 XSS-level(1-13) 靶场心得和总结
    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档文章目录前言二、解题思路第一关:无过虑机制第二关:闭合标签第三关:单引号闭合+添加事件第四关:双引号闭合+添加事件第五关:不同标签的尝试(新建标签)第六关:大小写绕过第七关:直接将script关键字过滤掉(双写绕过)第......
  • Python学习 - 字典篇 新手小白也能懂
    目录一、字典的定义二、字典的声明1.用{}声明2.dict()三、字典的键与值四、字典的常见操作1.in成员运算符2.可迭代(三种遍历类型)第一种第二种第三种3.get4.添加或修改元素5.删除6.更新字典五、结语一、字典的定义在Python中,字典是一种无序的、可变的数......
  • Spring Boot Vue 毕设系统讲解 11【协同过滤方法教学】
    目录1.基础知识用户基于的协同过滤(User-basedCF)物品基于的协同过滤(Item-basedCF)优缺点实际应用2.项目功能实战1.基础知识协同过滤(CollaborativeFiltering,CF)是一种广泛应用于推荐系统中的算法,它通过分析和利用用户与物品之间的交互信息来发现用户可能感兴趣......
  • Java计算机毕业设计教学资料管理系统(开题+源码+论文)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景:在教育信息化的大潮中,教学资料作为知识传播的重要载体,其管理与利用效率直接影响到教学质量与学生学习效果。传统的教学资料管理方式多依赖于纸质文档......