当前位置: 首页 > news >正文

wordpress页脚设置西安seo培训机构

wordpress页脚设置,西安seo培训机构,wordpress屏蔽广告插件,wordpress推荐新用户博客主页#xff1a;花果山~程序猿-CSDN博客 文章分栏#xff1a;项目日记_花果山~程序猿的博客-CSDN博客 关注我一起学习#xff0c;一起进步#xff0c;一起探索编程的无限可能吧#xff01;让我们一起努力#xff0c;一起成长#xff01; 目录 一#xff0c;项目介…    博客主页花果山~程序猿-CSDN博客 文章分栏项目日记_花果山~程序猿的博客-CSDN博客 关注我一起学习一起进步一起探索编程的无限可能吧让我们一起努力一起成长 目录 一项目介绍 日志插件技术实现 同步日志 异步日志 相关技术补充 C不定参宏 C不定参函数 C不定参函数 设计模式 工厂模式 建造者模式 代理模式 项目模块设计 日志框架设计  日志格式模块(format) 日志落地模块(sink) 日志管理器模块(logger) 扩展 双缓冲区异步任务处理器(Asynlogger) 异步日志器模块 日志宏 性能测试 模块关系图 改bug心得 结语 嗨收到一张超美的图愿你每天都能顺心 一项目介绍 企业开发中对于运行中的程序不适合使用调试器调试。⽣产环境的产品为了保证其稳定性及安全性是不允许开发⼈员附加调试器去排查问题 可以借助⽇志系统来打印⼀些⽇志帮助开发⼈员解决问题。问题无法复现。上线客⼾端的产品出现bug⽆法复现并解决 可以借助⽇志系统打印⽇志并上传到服务端帮助开发⼈员进⾏分析。对于⼀些⾼频操作如定时器、⼼跳包在少量调试次数下可能⽆法触发我们想要的⾏为通过断点的暂停⽅式我们不得不重复操作⼏⼗次、上百次甚⾄更多导致排查问题效率是⾮常低下 可 以借助打印⽇志的⽅式查问题 。在分布式、多线程/多进程代码中 出现bug⽐较难以定位 可以借助⽇志系统打印log帮助定位bug。 本项⽬主要实现⼀个⽇志系统 其主要⽀持以下功能: 支持日志等级选择支持用户(开发人员)日志格式自定义支持日志可靠落地方向如控制台文件滚动文件等支持同步异步模式选择支持多线程程序并发写日志 核心技术 类层次设计继承 多态C(如多线程智能指针等)双缓冲区生产消费者模型设计模式单例工厂建造者代理模式 日志插件技术实现 现在我们日志输出方式主要是3种方式 printfcout等输出函数到控制台对于⼤型商业化项⽬ 为了⽅便排查问题我们⼀般会将⽇志输出到⽂件或者是数据库系统⽅便查询和分析⽇志 主要分为同步⽇志和异步⽇志⽅式 同步日志 同步⽇志是指当输出⽇志时必须等待⽇志输出语句执⾏完毕后才能执⾏后⾯的业务逻辑语句⽇志输出语句与程序的业务逻辑语句将在同⼀个线程运⾏。每次调⽤⼀次打印⽇志API就对应⼀次系统调⽤write写⽇志⽂件异步日志。 缺点 在高并发情况下由于写日志IO的系统操作效率过低同时write操作有可能让线程阻塞无法执行业务逻辑。 异步日志 异步日志就是将日志输出操作分离出让一个线程负责日志输出操作而业务线程只负责在写。业务线程只需要在内存中向日志缓冲区写入日志(日志的生产者)而日志线程就只负责从日志缓冲区中获取日志完成日志的输出操作日志的消费者。这之间的关系就是一个典型的生产-消费者模型。 相关技术补充 C不定参宏 #include stdio.h// 定义一个不定参宏用于打印消息 #define LOG(format, ...) printf(format, __VA_ARGS__)// 项目中通过它来简化接口调用 #define DEBUG(fmt, ...) \RoolLogger()-Debug(__FILE__, __LINE__, fmt, ##__VA_ARGS__)int main() {// 使用不定参宏打印不同数量的参数LOG(Hello, world!\n);LOG(The value of x is %d\n, 42);LOG(x %d, y %d, z %d\n, 10, 20, 30);return 0; } C不定参函数 void Debug(const std::string fmt, ...) {// 1.从不定参中获取字符串char custom_log[1024] {0};va_list v_li; // 本质是 char*va_start(v_li, fmt); // 将记录全部不定参数到v_li中vsnprintf(custom_log, sizeof custom_log, fmt.c_str(), v_li); //通过接口转到char[]中va_end(v_li);print(%s%n, custom_log);} C不定参函数 // 模板函数 func 的定义 template class T void func(const T t) {cout t endl;cout endl; }//非模板函数 func 的定义 void func() {cout 0 endl; }//1. 模板变参函数 func 的定义 templateclass T , class ...Ags //void func(const T t, Ags... args) // 一个一个地解包参数void func(const T t, Ags... args) // {cout t 剩余包数 sizeof...(args) endl ;//func(args...); // 剩余参数包func(forwardAgs(args)...); //...的位置有讲究 }//2. 使用变参为类传参 class MyClass { public:MyClass(int a, int b, char _c) : x(a), y(b), c(_c) {}// 其他成员... private:int x, y;char c; };templete class T, class ...Args void setclass(Args ... args) {return std::make_sharedT(std::forwordArgs(args)...); // 假设 Args 是 int, intchar。不定参展开传参展开示例如下: //auto ptr std::make_sharedMyClass(std::forwardint(10), std::forwardint(20), std::forwordchar(k));int main() {func();func(1, A);func(1, A, hello word);setclassMyClass(10, 20, k); } 设计模式 设计模式是前辈们对代码开发经验的总结是解决特定问题的⼀系列套路。它不是语法规定⽽是⼀套⽤来提⾼代码可复⽤性、可维护性、可读性、稳健性以及安全性的解决⽅案。 设计原则 从整体上来理解六⼤设计原则可以简要的概括为⼀句话⽤抽象构建框架⽤实现扩展细节具体到每⼀条设计原则则对应⼀条注意事项 单⼀职责原则告诉我们实现类要职责单⼀⾥⽒替换原则告诉我们不要破坏继承体系依赖倒置原则告诉我们要⾯向接⼝编程接⼝隔离原则告诉我们在设计接⼝的时候要精简单⼀迪⽶特法则告诉我们要降低耦合开闭原则是总纲告诉我们要对扩展开放对修改关闭。 这里只简单提及所用到的模式详细了解设计模式请自行寻找各模式的例子。 工厂模式 ⼯⼚模式是⼀种创建型设计模式 它提供了⼀种创建对象的最佳⽅式。在⼯⼚模式中我们创建对象时不会对上层暴露创建逻辑⽽是通过使⽤⼀个共同结构来指向新创建的对象以此实现创建-使⽤的分离。 ⼯⼚模式可以分为: 简单⼯⼚模式: 简单⼯⼚模式实现由⼀个⼯⼚对象通过类型决定创建出来指定产品类的实例。假设有个⼯⼚能⽣产出⽔果当客⼾需要产品的时候明确告知⼯⼚⽣产哪类⽔果⼯⼚需要接收⽤⼾提供的类别信息当新增产品的时候⼯⼚内部去添加新产品的⽣产⽅式。 缺点这个模式的结构和管理产品对象的⽅式⼗分简单 但是它的扩展性⾮常差当我们需要新增产品的时候就需要去修改⼯⼚类新增⼀个类型的产品创建逻辑违背了开闭原则。 ⼯⼚⽅法模式: 在简单⼯⼚模式下新增多个⼯⼚多个产品每个产品对应⼀个⼯⼚。假设现在有A、B 两种产品则开两个⼯⼚⼯⼚ A 负责⽣产产品 A⼯⼚ B 负责⽣产产品 B⽤⼾只知道产品的⼯⼚名⽽不知道具体的产品信息⼯⼚不需要再接收客⼾的产品类别⽽只负责⽣产产品。 缺点⼯⼚⽅法模式每次增加⼀个产品时都需要增加⼀个具体产品类和⼯⼚类这会使得系统中类的个数成倍增加在⼀定程度上增加了系统的耦合度。 抽象工厂模式⼯⼚⽅法模式通过引⼊⼯⼚等级结构解决了简单⼯⼚模式中⼯⼚类职责太重的问题但由于⼯⼚⽅法模式中的每个⼯⼚只⽣产⼀类产品可能会导致系统中存在⼤量的⼯⼚类势必会增加系统的开销。 建造者模式 建造者模式是⼀种创建型设计模式 使⽤多个简单的对象⼀步⼀步构建成⼀个复杂的对象能够将⼀个复杂的对象的构建与它的表⽰分离提供⼀种创建对象的最佳⽅式。主要⽤于解决对象的构建过于复杂的问题。 代理模式 代理模式指代理控制对其他对象的访问 也就是代理对象控制对原对象的引⽤。在某些情况下⼀个对象不适合或者不能直接被引⽤访问⽽代理对象可以在客⼾端和⽬标对象之间起到中介的作⽤。 项目模块设计 日志框架设计  ⽇志等级模块对输出⽇志的等级进⾏划分以便于控制⽇志的输出并提供等级枚举转字符串功能。 OFF关闭DEBUG调试调试时的关键信息输出。INFO提⽰普通的提⽰型⽇志信息。WARN警告不影响运⾏但是需要注意⼀下的⽇志。ERROR错误程序运⾏出现错误的⽇志FATAL致命⼀般是代码异常导致程序⽆法继续推进运⾏的⽇志 日志消息模块存储日志必要的信息如时间所在文件行日志等级日志用户自定义部分所在线程ID。 好了我们有了组件日志的”材料“后开始制作日志那我们该怎么将日志数据排列 日志格式模块(format) 功能用户给予日志格式化规则如%d%T[%t]%T[%p]%T[%c]%T%f:%l%T%m%n日志格式器模块会生成的日志格式然后日志依据格式构建日志信息最后返回日志字符串。 设计模式简单工厂模式 设计思想 抽象出一个格式化子类的基类同时声明虚函数fomat为子类形成日志的共同方法由子类重写。基于基类派生出 时间所在文件行日志等级等必要信息的子类并重写format接口。创建formatter 工厂类根据用户规定的日志格式化规则形成日志信息构建流水线(vectorformat)实现方法通过基类指针就能调用各个子类对象的fomat函数 向外部提供获取日志字符串接口(GetResult)。 在外部构造日志时直接调用formatter工厂类由工厂类对外交互。 关系图 format模块代码 Log-Project/logs/format.hpp · 逆光/标准日志插件项目 - 码云 - 开源中国 (gitee.com) 日志落地模块(sink) 功能用户给予一段日志信息日志落地模块根据日志输出等级将日志信息落地到输出到控制台文件滚动文件甚至是数据库。 设计模式简单工厂模式 设计思路 抽象出一个log落地基类并同时声明log虚函数让子类重写。基于log基类派生出控制台文件滚动文件(文件超过一定大小自动创建新文件)等其他方向的子类并根据落地方向不同重写log函数。支持落地扩展。用户可以自己添加相应的落地方向模块而工厂类创建不用修改。创建logSink工厂类向外部提供一个创建落地对象的接口createlogsink用户即可通过传入落地方向的类进行创建具体对象让创建与表示分离。 代码 Log-Project/logs/sink.hpp · 逆光/标准日志插件项目 - 码云 - 开源中国 (gitee.com) 日志管理器模块(logger) 功能整合日志格式模块 日志管理器模块向外提供根据日志等级输出的接口。 设计模式工厂模式  管理成员 日志器名称(日志器唯一标识符在全局日志器中会对日志器进行管理)日志格式化模块对象日志落地方向对象数组日志落地方向可能存在多个日志落地操作锁在多线程情况下保证日志写操作线程安全避免日志交叉日志最小输出等级小于该等级日志则不输出 管理函数 debuginfowarnfatal等级的日志输出操作根据传入日志message使用日志格式化对象形成日志然后调用日志落地接口log完成日志落地抽象日志落地log 实现方式 抽象logger基类派生出 同步日志器 异步日志器 子类由于同步日志器异步日志器之间的区别是落地操作log的不同因此我们将落地操作log抽象出来在子类完成不同落地操作。最后通过logger基类指针来调用不同日志器派生类重写的log操作。 代码 Log-Project/logs/logger.hpp · 逆光/标准日志插件项目 - 码云 - 开源中国 (gitee.com) 扩展 功能设计一个建造者类简化用户设置日志参数和用户使用日志器的复杂度。 设计模式建造者模式 管理成员由于是建造者类其将管理成员为日志管理器的管理成员 管理函数 对外提供设置日志器名称日志器格式化规则日志等级创建日志落地方向等接口一步步构造日志器部件。 实现方式 抽象builderlogger类提供日志器初始化部件接口派生出 局部日志器建造者 全局日志器建造者 子类局部日志器与全局(单例)日志器建造者区别在于前者无法突破作用域而全局可以在程序的任一位置访问并给予查看管理建造日志器。因此我们需要将builderlogger类中build抽象出来让派生类来完成各自创建操作。全局日志器建造者类需要使用单例模式同时需要维护一个以名称查找的日志器unorder_map容器以便于管理全局的日志器。 代码 Log-Project/logs/builder.hpp · 逆光/标准日志插件项目 - 码云 - 开源中国 (gitee.com) 双缓冲区异步任务处理器(Asynlogger) 异步日志器相比与同步日志器线程在调用日志器输出日志时异步将日志信息存放在内存中然后继续业务逻辑并不直接调用系统接口进行IO操作存在在内存中的日志信息会由异步日志落地线程专门来将日志信息落地。  设计思想异步处理线程 数据池 使⽤者将需要完成的任务添加到任务池中由异步线程来完成任务的实际执⾏操作。 任务池的设计思想双缓冲区阻塞数据池 优势避免了空间的频繁申请释放且尽可能的减少了⽣产者与消费者之间锁冲突的概率提⾼了任务处理效率。 问题为什么不采用任务队列的方式处理日志 答: 1. 任务队列锁冲突频繁逻辑复杂。假设使用同一个任务队列生产者写日志线程与生产者写日志线程存在锁冲突生产者写日志线程与消费者落地线程存在锁冲突锁冲突概率高。 2. 任务队列一般采用链表的方式这样存在频繁的控制申请释放空间无法复用。 ⽽双缓冲区不同双缓冲区是处理器将⼀个缓冲区中的任务全部处理完毕后然后交换两个缓冲区重新对新的缓冲区中的任务进⾏处理虽然同时多线程写⼊也会冲突但 是冲突并不会像每次只处理⼀条的时候频繁⽣产者与消费者之间的锁冲突也只有交换缓冲区时会有锁冲突且不涉及到空间的频繁申请释放所带来的消耗。 缓冲区类设计 功能提供缓冲区交换接口; 支持多日志一次落地; 支持缓冲区动态扩容 代码 Log-Project/logs/buffer.hpp · 逆光/标准日志插件项目 - 码云 - 开源中国 (gitee.com) 异步日志器模块 异步⽇志器类继承⾃⽇志器类 并在同步⽇志器类上拓展了异步消息处理器。当我们需要异步输出⽇志的时候 需要创建异步⽇志器和消息处理器 调⽤异步⽇志器的log、error、info、fatal等函数输出不同级别⽇志。 相对与同步日志器异步日志器需要实现 重写log函数让日志信息写入到缓冲区中。 提供默认异步日志线程的缓冲区交换读取缓冲区最终完成日志落地功能逻辑的回调函数 代码 Log-Project/logs/logger.hpp · 逆光/标准日志插件项目 - 码云 - 开源中国 (gitee.com) 日志宏 提供全局的⽇志器获取接⼝。 使⽤代理模式通过全局函数或宏函数来代理Logger类的log、debug、info、warn、error、fatal等接 ⼝以便于控制源码⽂件名称和⾏号的输出控制简化⽤⼾操作。 当仅需标准输出⽇志的时候可以通过主⽇志器来打印⽇志。 且操作时只需要通过宏函数直接进⾏输出即可。(简化用户使用复杂度) // 定义宏用于自动获取文件名和行号并且可以接受任意的日志记录器对象名,方便用户不用操作全局日志器 #define LOG_DEBUG(logger_name, fmt, ...) \GetLogger(logger_name)-Debug(__FILE__, __LINE__, fmt, ##__VA_ARGS__)#define LOG_INFO(logger_name, fmt, ...) \GetLogger(logger_name)-Info(__FILE__, __LINE__, fmt, ##__VA_ARGS__)#define LOG_FAIL(logger_name, fmt, ...) \GetLogger(logger_name)-Fail(__FILE__, __LINE__, fmt, ##__VA_ARGS__)#define LOG_WARN(logger_name, fmt, ...) \GetLogger(logger_name)-Warn(__FILE__, __LINE__, fmt, ##__VA_ARGS__) 详尽代码 Log-Project/logs/log.h · 逆光/标准日志插件项目 - 码云 - 开源中国 (gitee.com) 性能测试 下⾯对⽇志系统做⼀个性能测试测试⼀下平均每秒能打印多少条⽇志消息到⽂件。 主要的测试⽅法是每秒能打印⽇志数 打印⽇志条数 / 总的打印⽇志消耗时间 主要测试要素同步/异步 单线程/多线程。 测试项目 1000w条指定⻓度的⽇志输出所耗时间每秒可以输出多少条⽇志每秒可以输出多少MB⽇志 测试环境 CPU: Intel(R) Xeon(R) Gold 6278C CPU 2.60GHz(2 核) RAM: 4G OS : CentOS Linux release 7.6.1810 (Core) 测试代码 Log-Project/bench/bench.cxx · 逆光/标准日志插件项目 - 码云 - 开源中国 (gitee.com) 测试结果打印相同日志数量异步多线程最快其次是同步多线程 模块关系图 、 改bug心得 出错原因对formatter功能理解有问题。 formatter功能是根据用户给出的格式化规则通过解析函数(pase_pattern)形成一个构造日志队列。 就好像formatter是工厂通过pase_pattern自定义化形成一个构造日志流水线。 问题出在我是如何理解这个流水线是临时的错误还是持久化的正确。 首先从此次出错的问题在多线程场景中我的日志构造线的_items出现段错误。 出现问题思考解决思路 刚开始时我通过cout定位到了出错点同时也发现新线程来使用_items时出错。我刚开始意识到这个_items出现线程安全我后面甚至还想要不将_items从成员变量做成临时变量好让每次不用考虑加锁解锁。但这样做每发一个日志就创建一个_items流水线工具然后就丢弃这样会有很大的性能浪费在这里想就有问题就没往这边想了。差点在错误的路上一路狂奔 最后发现我应该将构造日志流水线做成持久化。从上到下讲作为一个日志插件用户在初始化日志器后日志输出格式也应该确定了日志构造流水线也应处于被只读的情况没有线程安全一说。 因此解析日志操作不能出现在日志器构造日志中应在初始化操作中。 结语 本小节就到这里了感谢小伙伴的浏览如果有什么建议欢迎在评论区评论如果给小伙伴带来一些收获请动动你发财的小手点个免费的赞你的点赞和关注永远是博主创作的动力源泉。
http://www.hkea.cn/news/14256900/

相关文章:

  • 校园二手网站开发的意义公司网站建设教程
  • php制作网站江西南昌网站开发
  • 为何建设银行网站无法登陆wordpress 全局变量
  • 暴雪战网官方网站入口网站建设飠金手指排名十二
  • 平度168网站建设探测网站是什么程序做的
  • 免费个人网站制作在线网站建设制作经验足
  • 北京建行网站网站制作的文章
  • 一个网站需要哪些备案服务器上网站建设
  • 做资讯类网站需要特殊资质吗仿搜狐视频网站源码
  • 成都三合一网站建设昆明公司做网站
  • 网站维护运行建设报告帮公司做网站赚钱吗
  • 教资报名网站设置广西南宁相亲网
  • 微信官方网站下载安装建设网站可选择的方案
  • 武昌网站制作公司网络推广的策略方法
  • 移动网站建设的基本流程图什么是网络营销传播
  • 网页设计与制作是什么意思沈阳网站优化培训
  • 重庆企业网站推广费用wordpress访问显示502
  • 为网站开发android客户端wordpress博客怎么搜索
  • 做美工的网站小说网站搭建教程
  • 气象服务网站建设绿色商城网站模板
  • 网站建设 合优企业上海自贸区注册公司在哪里
  • 莱芜网站优化公司网站建设全包
  • 可以做3d电影网站软件合集
  • 网站制作的企业有哪些运城网站开发
  • 网站后台管理系统使用手册杭州网页设计培训机构
  • 织梦网站修改教程视频教程珠海市网站建设的公司
  • 成品网站源码在线重庆公司法人变更流程
  • oppo官方网站做类似交易猫的网站
  • 营销型网站如何策划长沙自助建站平台
  • 梧州市网站建设html网页制作模板代码