高并发高性能接口中,异步打印并采集业务日志的实现方案

一、背景

高并发接口中,为了提高接口的高性能,在需要保存审计及操作记录的时候,往往有以下常见方案:

  • 保存到redis数据库
  • 异步保存到mysql/mongodb/es等数据库
  • logger打印业务日志,采集与展示则交由elk模块

对于第一种方案,接口的高性能依赖于redis的性能;第二种方案的关键在于异步,可以是基于事件驱动机制,常见的CQRS设计就是例子;
本文则是介绍第三种方案,不同的是,我们的数据展示是在业务管理后台,而非kibana。

另外,生产环境,我们的应用程序是部署在k8s容器。

二、设计方案

在这里插入图片描述

  • 1、服务打印日志,持久化到nfs
  • 2、filebeat先挂载nfs,再配置采集日志
  • 3、kafka作为数据采集的削峰填谷的角色
  • 4、Logstash读取kafka的数据,解析并存储到指定es数据库
  • 5、管理后台连接并读取es数据库,展示数据

三、打印业务日志

使用logback使用不同的Logger对象,区分普通的jvm日志,把业务日志输出到指定的日志文件。

  • logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<!--该日志将日志级别不同的log信息保存到不同的文件中 -->
<configuration><include resource="org/springframework/boot/logging/logback/defaults.xml"/><springProperty scope="context" name="springAppName"source="spring.application.name"/><springProperty scope="context" name="log_dir" source="logging.login.path" defaultValue="../logs"/><!-- 日志输出位置 --><property name="LOG_FILE" value="${log_dir}/${springAppName}-login"/><!-- 文件的日志输出样式 --><property name="FILE_LOG_PATTERN"value="%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}} ${LOG_LEVEL_PATTERN:-%5p} ${PID:- } --- [%t] %-40.40logger{39} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}"/><!-- 为logstash输出的JSON格式的Appender --><appender name="logstash"class="ch.qos.logback.core.rolling.RollingFileAppender"><file>${LOG_FILE}.log</file><rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"><!--日志文件输出的文件名 --><fileNamePattern>${LOG_FILE}.log.%d{yyyy-MM-dd}.%i.gz</fileNamePattern><timeBasedFileNamingAndTriggeringPolicyclass="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"><maxFileSize>20MB</maxFileSize></timeBasedFileNamingAndTriggeringPolicy><!--日志文件保留天数 --><MaxHistory>15</MaxHistory></rollingPolicy><!-- 日志输出编码 --><encoder><pattern>${FILE_LOG_PATTERN}</pattern><charset>utf8</charset></encoder></appender><logger name="com.xxx.event.handler.LoginLogEventHandler" level="INFO" additivity="false"><appender-ref ref="logstash"/></logger>
</configuration>

普通的jvm日志选择输出在console控制台,然后将流重定向到指定的日志文件里。

  • console
<!-- 控制台的日志输出样式 --><property name="CONSOLE_LOG_PATTERN"value="%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/><!-- 控制台输出 --><appender name="console" class="ch.qos.logback.core.ConsoleAppender"><filter class="ch.qos.logback.classic.filter.ThresholdFilter"><level>INFO</level></filter><!-- 日志输出编码 --><encoder><pattern>${CONSOLE_LOG_PATTERN}</pattern><charset>utf8</charset></encoder></appender><!-- 日志输出级别 --><root level="INFO"><appender-ref ref="console"/></root>

对于业务应用程序来说,所做的事情只需要打印一条日志即可,其高性能可想而知。

四、flebeat采集日志

申请一台机器,专门采集日志,而非在每个Pod容器里使用sidecar边车模式部署filebeat容器。

当然,这台机器必须要先挂载nfs。(nfs是购买的阿里云“文件存储NAS”服务)

在这里插入图片描述

下面是filebeat.yml示例:

# cat /etc/filebeat/filebeat.yml
filebeat.prospectors:
- input_type: logpaths:- /login_output_service/auth-service.logmultiline.pattern: '^[0-9]{4}-[0-9]{2}-[0-9]{2}'multiline.negate: truemultiline.match: afterdocument_type: login_out_logsoutput.kafka:enabled: truehosts: ["xxx.alikafka.aliyuncs.com:9092","yyy.alikafka.aliyuncs.com:9092","zzz.alikafka.aliyuncs.com:9092"]topic: 'login_out_logs'

五、kafka中间件

当然,它作为数据采集的中间件,所起的作用是削峰填谷,可以说,在整个链路中不是必须的。

建议你采用mq作为数据采集的过渡。

这里插一句,我们可以通过kafka的消息内容,反查出filebeat所在的机器。

原本的思路是想通过文件存储NAS查找ECS的挂载详情,可惜没找到入口。(也就是说,无法得到哪些ECS挂载了NFS,只能选择通过Kafka)

忘记了filebeat是部署在哪个机器,好在我们知道kafka,因为购买的是阿里云服务。

进入“消息队列Kafka版”

在这里插入图片描述
查看消息体内容:

在这里插入图片描述

{“@timestamp”:“2024-04-01T20:26:24.956Z”,“beat”:{“hostname”:“iZbp12202mumv2j30jv6l8Z”,“name”:“iZbp12202mumv2j30jv6l8Z”,“version”:“5.6.9”},“input_type”:“log”,“message”:“2024-04-02 04:25:18.486 INFO [auth-service,] 8 — [AuthService_EventPool_757886445] c.x.s.a.i.e.h.LoginLogEventHandler : LoginLogEventHandler - writeLoginLog - 登录登出日志 [id=1774895838313730083\tdate=20240402042518\tosVersion= 13]”,“offset”:10016,“source”:“/opt/server/auth-service.log”,“type”:“login_out_logs”}

从这里可以看到,filebeat机器hostname是iZbp12202mumv2j30jv6l8Z,注意需要转换,实际上是“i-bp12202mumv2j30jv6l8”。

另外从source字段,可以知道日志的源文件在哪。

  • 根据hostname查找ecs所在地

进入“云服务器ECS”

在这里插入图片描述
通过这两步,我们就通过kafka消息中间件,反查得到filebeat所在机器。关于filebeat在上一步已介绍,下面将介绍logstash的配置。

六、logstash存储业务日志

Logstash主要是用来解析业务日志,先读取kafka的数据,然后存储到es数据库。

另外logstash支持多个配置文件,建议你分开配置并加载。

# 默认配置
logstash -f /usr/share/logstash/pipeline/logstash.conf# 修改为通配符*.conf
logstash -f /usr/share/logstash/pipeline/*.conf
  • auth.conf 详情
# cat /usr/local/logstash-6.8.23/config/auth.confinput {kafka {bootstrap_servers => "xxx.alikafka.aliyuncs.com:9092","yyy.alikafka.aliyuncs.com:9092","zzz.alikafka.aliyuncs.com:9092"codec => "json"type => "_doc"topics => "login_out_logs"}
}filter {grok {match => {"message"=>"%{JAVA_DATE:logdate}\s+%{XHJVM_VALUE:logType}\s.*登录登出日志\s+\[id=(%{FIELD_VALUE:id}?\s+)date=(%{FIELD_VALUE:date}?\s+)osVersion=(%{FIELD_VALUE:osVersion}?)\]"}}# 增加采集时间戳,去掉一些非必要的字段date {match => ["logdate", "yyyy-MM-dd HH:mm:ss.SSS"]target => "@timestamp"remove_field => [ "logdate", "logType", "host", "@version", "@timestamp", "path", "message", "beat", "source", "input_type", "offset"]}}output{elasticsearch{# es的地址hosts => ["10.xxx.xxx.126:9200"]index => "auth_login_out_logs_write"codec => line { format => "%{message}"}document_type => "_doc"# es的用户名user => "{username}"# es的密码password => "{password}"document_id => "%{id}"}
}

还好无意中找到了logstash所在机器,要不然,要找出logstash还真是麻烦。。。

因为这里把很多“无用”的字段remove掉了,所以在es数据库中也无法得到采集的链路详情。

七、总结

本文试着通过另外一个解决方案来保证高并发接口的高性能,顺便介绍了如何找回filebeat所在机器的过程。同时提醒我们,在采集数据的时候,或者程序开发的时候,特别是当你的链路很长的时候,把每个环节的主体信息记录下来是多么的重要。

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

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

相关文章

OpenLayers6实战,OpenLayers实现鼠标拖拽方式绘制平行四边形

专栏目录: OpenLayers实战进阶专栏目录 前言 本章介绍如何使用OpenLayers在地图上使用实现鼠标拖拽方式绘制平行四边形。 二、依赖和使用 "ol": "^6.15.1"使用npm安装依赖npm install ol@6.15.1使用Yarn安装依赖yarn add olvue中如何使用: vue项目…

初学SSRF总结

什么是SSRF SSRF是由攻击者构造通过服务端发起请求的安全漏洞。通常情况下&#xff0c;SSRF的攻击对象是外部无法访问的内网&#xff08;因为是由服务端发起的请求所以攻击能够访问到内部系统&#xff09; 由于服务端提供了从其它服务器获取数据的功能&#xff0c;但是有没有…

SPLD论文笔记

SLPD论文笔记 题目&#xff1a;SLPD: Slide-Level Prototypical Distillation for WSIs 摘要 提高特征表示能力是许多全玻片病理图像 &#xff08;WSI&#xff09; 任务的基础。最近的工作在病理特异性自我监督学习&#xff08;SSL&#xff09;方面取得了巨大成功。然而&…

C++初阶:反向迭代器

reverse_iterator的封装实现 Reverse_Iterator.h namespace xx {// 所有容器的反向迭代器// 迭代器适配器template<class Iterator, class Ref, class Ptr>struct Reverse_iterator{Iterator _it;typedef Reverse_iterator<Iterator, Ref, Ptr> Self;Reverse_iter…

Vue中如何使用Tailwind CSS样式?多次引用不成功?具体步骤怎么做?

一、安装Tailwind CSS和依赖 在你的Vue项目中安装Tailwind CSS及其依赖。你可以使用npm或yarn来安装。 npm install tailwindcsslatest postcsslatest autoprefixerlatest # 或者yarn add tailwindcsslatest postcsslatest autoprefixerlatest 二、初始化Tailwind CSS np…

Linux系统中MySQL数据库大小写敏感

问题描述 最近把网站向一台新的CentOS服务器中做迁移&#xff0c;把MySQL数据库和前后端站点全都部署完成后&#xff0c;网站启动之后一直在报表名不存在的错误。 开始略微疑惑&#xff0c;以为是做数据库备份的时候漏了表&#xff0c;检查后发现并不是这么回事。 略一思索&a…

ETL工具-nifi干货系列 第九讲 处理器EvaluateJsonPath,根据JsonPath提取字段

1、其实这一节课本来按照计划一起学习RouteOnAttribute处理器&#xff08;相当于java中的ifelse&#xff0c;switch case 控制语句&#xff09;&#xff0c;但是在学习的过程中遇到了一些问题。RouteOnAttribute 需要依赖处理器EvaluateJsonPath&#xff0c;所以本节课我们一起…

一天300收入打底,​一个适合任何人的创业项目!

共享旅游卡项目&#xff0c;一天300收入打底&#xff0c;一个适合任何人的创业项目&#xff01; 只要你不懒&#xff0c;生活总过得不会太差。只要你不贪&#xff0c;就算不能大富大贵&#xff0c;至少不会负债累累。 人性最难戒掉的两个字&#xff1a;一个是懒&#xff0c;另…

编译原理 学习笔记

1、代码&#xff1a; (1 2) * 3 2、词法解析&#xff1a; 3、抽象语法树&#xff1a; 4、语法树递归下降求值&#xff1a; 先Current_Node是根节点乘号&#xff0c;乘号&#xff0c;是中缀运算符&#xff0c;找左子节点&#xff0c;是加号&#xff0c;加号是中缀表达式&…

220 基于matlab的考虑直齿轮热弹耦合的动力学分析

基于matlab的考虑直齿轮热弹耦合的动力学分析&#xff0c;输入主动轮、从动轮各类参数&#xff0c;考虑润滑油温度、润滑油粘度系数等参数&#xff0c;输出接触压力、接触点速度、摩擦系数、对流传热系数等结果。程序已调通&#xff0c;可直接运行。 220直齿轮热弹耦合 接触压力…

MATLAB有限元结构动力学分析与工程应用-徐斌|【PDF电子书+配套Matlab源码】

专栏导读 作者简介&#xff1a;工学博士&#xff0c;高级工程师&#xff0c;专注于工业软件算法研究本文已收录于专栏&#xff1a;《有限元编程从入门到精通》本专栏旨在提供 1.以案例的形式讲解各类有限元问题的程序实现&#xff0c;并提供所有案例完整源码&#xff1b;2.单元…

【fiddler】弱网测试

目录 一、测试目的 二、步骤 2.1打开弱网模式 ​ 2.2设置网络参数 &#xff08;1&#xff09;打开Rules→Customize Rules&#xff1b; &#xff08;2&#xff09;找到下面框出的代码&#xff0c;在这里设置弱网参数值&#xff1b; &#xff08;3&#xff09;设置完成后&a…

软件行业之选:CRM系统如何赋能业务增长?

“CRM系统从整合营销渠道、自动化营销流程、强化客户全周期管理、增强服务能力、完善企业内部流程、开展数字化决策六个方面赋能软件行业。” 软件行业由于存在较高的技术壁垒&#xff0c;很多时候销售与客户沟通不顺畅&#xff0c;实施与客户沟通有难度&#xff0c;售后服务周…

Java代码基础算法练习-统计学生成绩-2024.04.11

任务描述&#xff1a; 编写程序&#xff0c;输入n个(0<n<50)学生的成绩(输入-1结束)&#xff0c;要求统计并输出优秀(大任务描述:于85)、及格(60~84)和不及格(小于60)的学生人数。(成绩取值范围0~100) 任务要求&#xff1a; 代码示例&#xff1a; /*** 这个程序用于统计…

android 11修改通知栏电池信息的字体颜色

如图为红色。 对应文件为BatteryMeterView loadPercentView之后执行&#xff1a; mBatteryPercentView.setTextColor(Color.RED);

缓存穿透、缓存雪崩、缓存击穿的区别

缓存三兄弟&#xff08;穿透、雪崩、击穿&#xff09; 缓存穿透 定义 查询一个redis和数据库都不存在的值&#xff0c;数据库不存在则不会将数据写入缓存&#xff0c;所以这些请求每次都达到数据库。 解决办法是缓存空对象&#xff0c;如果数据库不存在则将空对象存入缓存&…

【SpringBoot】SpringBoot项目快速搭建

本文将介绍Springboot项目的快速搭建 快速创建SpringBoot项目 打开IDEA在File->New->Project中新建项目 点击左侧的Spring Initializr 输入以下信息&#xff1a; Name 项目名称Group 根据公司域名来&#xff0c;或者默认com.example【倒序域名】Package Name 包名&am…

SpringCloudAlibaba-整合sleuth和zipkin(六)

目录地址&#xff1a; SpringCloudAlibaba整合-CSDN博客 一、整合sleuth 1.引入依赖 在需要追踪的微服务中引入依赖&#xff0c;user、order、product <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter…

数字档案馆升级改造的意义

数字档案馆升级改造的意义在于提升档案管理的效率和质量&#xff0c;更好地满足各方面的需求&#xff0c;并为数字时代的档案管理提供更好的支持和保障。具体意义包括&#xff1a; 1. 提高档案存储、检索和利用效率&#xff1a;玖拓智能数字化档案馆可以实现电子存储和快速检索…

前端vue2中的excel导出功能-file-saver,xlsx,xlsx-style的使用

文章目录 概要整体架构流程技术名词解释技术细节小结 概要 今天遇到了一个技术点.前端的excel的纯导出功能,不和后端交互,只用前端导出数据 整体架构流程 vue2 element-ui 技术名词解释 在网上看了很多帖子,最后我选择了xlsx , file-saver , xlsx-style 这个三个插件完成…