重写Sylar基于协程的服务器(2、配置模块的设计)

重写Sylar基于协程的服务器(2、配置模块的设计)

重写Sylar基于协程的服务器系列:

重写Sylar基于协程的服务器(0、搭建开发环境以及项目框架 || 下载编译简化版Sylar)

重写Sylar基于协程的服务器(1、日志模块的架构)

重写Sylar基于协程的服务器(2、配置模块的设计)

重写Sylar基于协程的服务器(3、协程模块的设计)

配置模块存在的必要性

一个服务器软件可能会运行在不同的机器上,机器的配置、网络环境、实际需求等都是千变万化,在服务器软件中,为了适应这些变化,可能就是调整几个变量的值。开发人员不可能每次外在因素的改变就重新编译软件再发布,这明显是不现实的。于是配置模块就在这时发挥它的关键作用,利用好配置模块就不需要再次编译,让配置模块自己加载参数,动态调节就行了。

配置模块的设计与实现

配置模块序列化和反序列化效果(支持std::各种容器

YAML 的基本语法如下:

  1. 大小写敏感。

  2. 利用缩进表示层级关系,缩进只能使用空格,空格的数量不重要。

  3. '#'表示注释。

  4. 数据类型:对象,键值对的集合,即K-V对。数组,一组按次序排列的值。纯量(scalars),单个的、不可再分的值,包括字符串、布尔值、整数、浮点数、Null、时间、日期。

测试配置文件定义了一个key为space,value也是一个map类型的节点,该map有两个kv对,它们的key分别是vec、num,value分别是数组类型和纯量类型。如下

test_config.yml:

space:vec: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]num: 7

测试代码:

void test_logConfig(){// 创建配置变量lunar::ConfigVar<std::vector<int>>::ptr vec = lunar::ConfigVarMgr::GetInstance()->lookUp("space.vec", std::vector<int>(), "vec test");lunar::ConfigVar<int>::ptr num = lunar::ConfigVarMgr::GetInstance()->lookUp("space.num", int(), "num test");// 解析配置文件lunar::ConfigVarMgr::GetInstance()->loadFromFile("test_config.yml");// 反序列化配置 && 输出到控制台LUNAR_LOG_INFO(g_logger) << vec->toString();LUNAR_LOG_INFO(g_logger) << num->toString();
}

解析结果:

[root@localhost build]# ../bin/test_config 
2024-01-31 21:02:02     2433    unknow  4294967295      [INFO]  [system]        /root/workspace/lunar/tests/test_config.cc:53       - 0
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
2024-01-31 21:02:02     2433    unknow  4294967295      [INFO]  [system]        /root/workspace/lunar/tests/test_config.cc:54       7

配置模块类的设计

在Yaml提供的数据类型的基础上,我们的配置文件还需要支持对象类型,所以我们需要通过模板,以泛型编程的方式实现对复杂数据类型的解析,除此之外,我们还要,对各个配置变量进行集中管理,综上所述,类的设计如下:

  1. LexicalCast,对象转换类模板(仿函数),使用C++的模板二次封装Boost库的boost::lexical_cast模板函数,实现基础类型和字符串类型间相互转换。然后对LexicalCast类模板进行偏特化,让其支持C++标准库的容器的序列化与反序列化。所以,我们实现的LexicalCast类模板默认支持基础类型和C++容器,想要支持自定义类型的序列化和反序列化,用户需要自己实现全特化LexicalCast。

  2. ConfigVarBase,配置变量基类,抽象出配置参数共有属性和方法比如变量名、对变量的描述、互斥锁、toString()、fromString()等,方便ConfigVarManager类使用多态对配置变量进行统一的管理。

  3. ConfigVar,配置变量类模板,继承ConfigVarBase类,含有m_value成员变量,利用LexicalCast类模板,实现toString方法将配置变量序列化成Yaml String,实现fromString方法将Yaml String反序列化成配置变量。此外,还支持变更通知,在set方法中调用变更回调,通知引用配置变量的地方更新变量。

  4. ConfigVarManager,配置变量管理类,利用std::map容器管理所有ConfigVar变量,std::map以配置变量名作为key,以配置变量基类智能指针作为value,支持配置变量的查询,用户在查询一条配置变量时,会提供该变量的变量名、默认值、变量描述,如果配置变量不存在,ConfigVarManager还会自动通过new 运算符利用默认值创建一个类型相同的配置变量,然后将<变量名,自动创建的配置变量>插到std::map中并返回给用户,因此ConfigVarManage还有自学习的能力。此外,提供了loadFromYaml函数支持对Yaml文件的解析,通过递归的方式解析Yaml文件中的每个map node节点,因为Yaml文件的map类型就是<key, value>对,这里key,value在配置文件中的含义和成员变量std::map中元素的含义是一致的,所以,取解析到的每个map node节点的key,去查该key是否存在于std::map成员中,如果存在,就调用相应配置变量基类的fronString函数,将map node的value作为参数,反序列化成一个配置变量。

ConfigVarManager的伪代码如下:

伪代码

yaml配置文件解析的核心代码如下:

    // 递归枚举每一个类型为map的节点。static void __ListAllYamlNode(std::string prefix,const YAML::Node& node,std::vector<std::pair<std::string, YAML::Node>>& output){output.push_back(std::make_pair(prefix, node));if(node.IsMap()){for(auto it = node.begin(); it != node.end(); it++){__ListAllYamlNode((prefix.empty() ? prefix :prefix + ".") + it->first.Scalar(), it->second, output);}}}void ConfigVarManager::loadFromFile(const std::string& val){std::vector<std::pair<std::string, YAML::Node>> nodes;YAML::Node root = YAML::LoadFile(val);__ListAllYamlNode("", root, nodes);for(auto it = nodes.begin(); it != nodes.end(); it++){ConfigVarBase::ptr var = lookUpConfigVarBaseByName(it->first);if(var != nullptr){ // 有配置变量就解析该节点std::stringstream ss("");ss << it->second;var->fromString(ss.str());// for debug//LUNAR_LOG_DEBUG(LUNAR_LOG_NAME("system")) << var->toString();}}}

关于yaml-cpp的使用可以参考官方文档:https://github.com/jbeder/yaml-cpp/wiki/Tutorial。

感兴趣的同学,可以阅读一下本文实现的源码:https://github.com/LunarStore/lunar


本章完结

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/250262.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【PostgresSQL系列】 ltree简介及基于SpringBoot实现 ltree数据增删改查

本文将对PostgresSQL中的ltree进行相关概念介绍&#xff0c;并以示例代码讲解ltree数据增删改查功能的实现。 作者&#xff1a;后端小肥肠 目录 1.前言 2. 基础概念 2.1. ltree 2.2. lquery 2.3. ltxtquery 2.4. ltree函数及操作符 2.4.1. ltree函数 2.4.2. ltree操作符…

软考 系统分析师系列知识点之需求管理(3)

接前一篇文章&#xff1a;软考 系统分析师系列知识点之需求管理&#xff08;2&#xff09; 所属章节&#xff1a; 第11章. 软件需求工程 第8节. 需求管理 11.8.4 需求跟踪 根据IEEE的定义&#xff0c;可跟踪性包含两个层面的含义&#xff1a;一个是开发过程的两个或多个产品之…

统计图表在线配置服务-百度 SugarBI的学习笔记

最近&#xff0c;有个产品要支持统计图表在线可配置&#xff0c;这样&#xff0c;当用户有新增统计指标的需求时&#xff0c;运维人员通过界面化配置&#xff0c;就可以增加统计指标了&#xff0c;不用开发写代码&#xff0c;画页面了。 上网查了下相关的组件&#xff0c;感觉…

OSPF排错

目录 实验拓扑图 实验要求 实验排错 故障一 故障现象 故障分析 故障解决 故障二 故障现象 故障分析 故障解决 故障三 故障现象 故障分析 故障解决 故障四 故障现象 故障分析 故障解决 故障五 故障现象 故障分析 故障解决 故障六 故障现象 故障分析 …

Linux服务详解

如有错误或有补充&#xff0c;以及任何改进的意见&#xff0c;请在评论区留下您的高见&#xff0c;同时文中给出大部分命令的示例&#xff0c;即是您暂时无法在Linux中查看&#xff0c;您也可以知道各种操作的功能以及输出 如果觉得本文写的不错&#xff0c;不妨点个赞&#x…

曲线拟合、多项式拟合、最小二乘法

最近在做自车轨迹预测的工作&#xff0c;遇到 曲线拟合、多项式拟合、最小二乘法这些概念有点不清晰&#xff0c; 做一些概念区别的总结&#xff1a; 曲线拟合用于查找一系列数据点的“最佳拟合”线或曲线。 大多数情况下&#xff0c;曲线拟合将产生一个函数&#xff0c;可用于…

[嵌入式软件][启蒙篇][仿真平台] STM32F103实现SPI控制OLED屏幕

上一篇&#xff1a; [嵌入式软件][启蒙篇][仿真平台] STM32F103实现LED、按键 [嵌入式软件][启蒙篇][仿真平台] STM32F103实现串口输出输入、ADC采集 [嵌入式软件][启蒙篇][仿真平台]STM32F103实现定时器 [嵌入式软件][启蒙篇][仿真平台] STM32F103实现IIC控制OLED屏幕 文章目…

Git 怎么设置用户的权限

在团队协作的软件开发中&#xff0c;对于版本控制系统Git来说&#xff0c;确保代码与数据的安全性至关重要。为了实现这一目标&#xff0c;Git提供了灵活且可定制的用户权限管理机制。下面将简单的探讨一下Git如何设置用户的权限&#xff0c;以及如何保护代码和数据。 用户身份…

提高 NFS Azure 文件共享性能

本文内容 适用于增加预读大小以提高读取吞吐量Nconnect另请参阅 本文介绍如何提高 NFS Azure 文件共享的性能。 适用于 展开表 文件共享类型SMBNFS标准文件共享 (GPv2)、LRS/ZRS 标准文件共享 (GPv2)、GRS/GZRS 高级文件共享 (FileStorage)、LRS/ZRS 增加预读大…

Spring Boot集成Redisson详细介绍

Redisson是一个用于Java的分布式和高可用的Java对象的框架&#xff0c;它基于Redis实现。在Spring Boot应用程序中集成Redisson可以帮助我们更轻松地实现分布式锁、分布式对象、分布式集合等功能。本文将介绍如何在Spring Boot项目中集成Redisson&#xff0c;并展示一些基本用法…

git远程仓库基本操作

目录 gitremote &#xff08;查看远程仓库&#xff09; git remote add [仓库名] [url] git clone [url]&#xff08;克隆远程仓库到本地&#xff09; git push [名][分支名]&#xff08;提交到远程仓库&#xff09;​编辑 git pull [名][分支名]从远程仓库拉取​编辑 注意操作…

混乱字母排序——欧拉路数论

题目描述 小明接到一个神秘的任务&#xff1a;对于给定的 n 个没有顺序的字母对&#xff08;无序代表这两个字母可以前后顺序颠倒&#xff0c;区分大小写&#xff09;。请构造一个有 (n1) 个字母的混乱字符串使得每个字母对都在这个字符串中出现。 输入输出格式 输入格式 第…

three.js CSS2DRenderer、CSS2DObject渲染HTML标签

有空的老铁关注一下我的抖音&#xff1a; 效果&#xff1a; <template><div><el-container><el-main><div class"box-card-left"><div id"threejs" style"border: 1px solid red;position: relative;"><…

SpringCloud_学习笔记_1

SpringCloud01 1.认识微服务 随着互联网行业的发展&#xff0c;对服务的要求也越来越高&#xff0c;服务架构也从单体架构逐渐演变为现在流行的微服务架构。这些架构之间有怎样的差别呢&#xff1f; 1.0.学习目标 了解微服务架构的优缺点 1.1.单体架构 单体架构&#xff…

FairGuard游戏加固入选《CCSIP 2023中国网络安全行业全景册(第六版)》

2024年1月24日&#xff0c; FreeBuf咨询正式发布《CCSIP 2023中国网络安全行业全景册(第六版)》。本次发布的全景图&#xff0c;共计展示20个一级分类、108个细分安全领域&#xff0c;旨在为广大企业提供网络安全产品选型参考&#xff0c;帮助企业了解中国网络安全技术与市场的…

一道sql注入的ctf题目致使用phpmyadmin上传 webshell 拿后台权限

以下均为靶场测试环境渗透&#xff0c;非正式环境。 遇见登录框&#xff0c;直接万能密码’or(11)or’/1 直接登录成功并返回结果: 既然存在sql注入&#xff0c;那就用sqlmap跑一下吧&#xff1a; 输出所有的数据库&#xff1a; sqlmap -u <目标URL> --dbs 要输出数据库…

docker中三种常用的持久化数据的方式

文章目录 介绍1.docker run -v2.volumes3.bind mounts 介绍 “前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。” 在Docker中&#xff0c;有以下三种常用的持久化数据的方式&#xff0c;可…

Kotlin快速入门系列10

Kotlin的委托 委托模式是常见的设计模式之一。在委托模式中&#xff0c;有两个对象参与处理同一个请求&#xff0c;接受请求的对象将请求委托给另一个对象来处理。与Java一样&#xff0c;Kotlin也支持委托模式&#xff0c;通过关键字by。 类委托 类的委托即一个类中定义的方…

2024美赛数学建模A题思路分析 - 资源可用性和性别比例

1 赛题 问题A&#xff1a;资源可用性和性别比例 虽然一些动物物种存在于通常的雄性或雌性性别之外&#xff0c;但大多数物种实质上是雄性或雌性。虽然许多物种在出生时的性别比例为1&#xff1a;1&#xff0c;但其他物种的性别比例并不均匀。这被称为适应性性别比例的变化。例…

【Javaweb程序】【C00155】基于SSM的旅游旅行管理系统(论文+PPT)

基于SSM的旅游旅行管理系统&#xff08;论文PPT&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于SSM的旅游旅行管理系统 本系统分为前台系统模块、管理员模块、用户模块以及商家模块 其中前台系统模块的权限为&#xff1a;当游客打开系统的网址后…