记一次线上日志堆栈不打印问题排查(附:高并发系统日志打印方案可收藏)

目录

  • 一.线上的日志堆栈不打印了
  • 二.一步一步仔细排查
  • 三.最后搞定
  • 四.聊一聊线上日志到底应该怎么打印
    • 4.1 日志打印的诉求
    • 4.2 常见的系统日志上报方案
      • 4.2.1 ELK 方案
      • 4.2.2 自定义log appender 完成应用日志采集.
    • 4.3 日志常见框架傻傻分不清
    • 4.4 日志在高并发系统中需要注意的 tips
      • 4.4.1 配置合理的日志级别
      • 4.4.2 记录合理的链路
      • 4.4.3 配置异步打印

一.线上的日志堆栈不打印了

线上的报错 error 日志不打印详细的堆栈信息了.本着追根到底的精神.仔细排查了下.目前的日志打印过程.系统和代码虽然是公司的,解决问题都是自己的呀.

正常打印.拥有详细的堆栈信息.

在这里插入图片描述

不正常打印.仅打印Exception className

二.一步一步仔细排查

第一反应是哪个神仙写法导致的.一般场景下不打印线上错误日志有这么几种场景.

  • logger.error(“关键字{}”,e)
    这种场景下 e 只会被 toString() 后打印一些简单的 toString() 方法,如果你的异常是自定义异常.那么相当于需要重写 toString() 方法,最后打印可以按照你的 toString() 方法进行打印.
    一般场景下,只会打印简短的日志信息.
  • logger.error(“关键字”+e.toString())

这种写法其实和上面第一种写法是一样的逻辑.仅仅只是通过手动拼接的逻辑来处理的.

一步两步跟踪代码.

第二步下面的日志打印.

如上第二步真实的日志打印如上.可以发现第二步其实没有什么问题.真实就是直接调用的 logger 的打印方法.

那其实可以发现具体就是在这个方法循环过程中出了问题,没有进入到的循环体中导致无法正确进行拼接,程序员的思维.通过配置发现整体的堆栈深度配置为 1 .先不论 1 是否合适.那么这里有一个判断.

int stackTraceLineNum = stackTraceLineNum > stackTraceElements.length ? 
stackTraceElements.length : stackTraceLineNum;

配置的值大于堆栈的深度 length 则使用stack具体的深度.否则则使用配置的stackTraceLineNum.那么这种情况下就是stackTraceElements.length=0.

那么问题来了什么情况会导致这个length为空呢?.点进去.

巴拉巴拉说了很长.发现有这么一段话.In the extreme case. a virtual machine that has no stack trace information concerning this throwable is permitted to return a zero-length array from this method.平时喜欢学外语的朋友都知道.这段话:在极端场景下.虚拟机考虑到堆栈信息可能被允许返回一个空数组从这个方法.我草,这是什么鬼.一时间发现这还是我写的那个 Java???

线索到这里基本断了.

理了理思路重新梳理了下发现问题的过程,重新将代码部署在预发环境.整体跑了一个遍,并通过 debug 也没哟复现.都是可以正常获取到 stack length.就这样上午一天过去了.并没有什么进展.第二天,脑子稍微清醒了点,确实想的不一样了.再来回想一下线上环境和预发环境的特点,特征.回归原点思考问题.

线上环境:

  • 流量特征:流量场景丰富.流量压力并发高.
  • 机器环境:线上机器一般配置较高.

预发开发等环境:
-流量特征:场景贫乏.流量压力小.
-机器环境:线上机器可能配置较差[可以通过配置升级来抹平]

那么其实还是要磨平线上环境之间的差异.并尝试了批量的压测,最终他出现了.老小子你还是来了.

通过发现每每执行到一段时间堆栈就不打印了,这个是不是就是注释里说的极端情况.联系注释提到的 virtual machine. 次数+vm. 这块你想到了什么. 不知道你想到了什么 .在老早之前总结过 jit 的一些特性.一时间马上检索一下(关键字: jit 堆栈不打印优化).确实有了.

oracle官网: https://www.oracle.com/java/technologies/javase/release-notes-introduction.html

三.最后搞定

马上开搞.

-XX:+OmitStackTraceInFastThrow 

配置上预发压测走起来,搞定.

幸福之余也再次查阅了一些资料.

发现这是 javafast throw 优化,感叹确实 jit 牛哈.通过次数来检测是否进行详细的堆栈打印.返回来也能理解,虚拟机默认在一些次数打印之后就不再打印详细的堆栈.默认开发者已经关注到相关的堆栈信息了.以此来减少性能损耗.主要应对常见的一些 Exception .

NullPointerException
ArithmeticException
ArrayIndexOutOfBoundsException
ArrayStoreException
ClassCastException

fast throw 本身从 jvmjit 层面来说是一个正向的优化措施,在线上整体的流量还是比较高的场景下,如果一旦将屏蔽优化内容.将徒增很多日志的打印,导致磁盘的 IO 升高以及磁盘利用率升高.所以本次的屏蔽也仅仅是开启了部分分组的配置,即能够保证在指定机器排查问题的场景下完成日志的追踪,也能够包装 fast throw 自带优化能够大部分被利用到.如果你的应用也是这种场景我也是建议使用这种方案.

四.聊一聊线上日志到底应该怎么打印

不止于此通过这次我们正好来聊一聊日志打印的这样一个流程.以及分享目前在搞的一个高并发系统是怎样去打印日志的.

4.1 日志打印的诉求

一般场景下打印日志主要基于以下几种诉求.

目标

  • 技术诉求:排查问题;基于关键字主动告警监测系统异常情况.
  • 业务运营诉求:基于关键字做流量统计,数据分析获取用户的具体产品功能反馈.以期进一步改进产品方案

关键路径

  • 正常业务处理的日志告警关键字打印,需要能将堆栈打印;
  • 支持一些巨量的存储以及结构化复杂查询能力
  • 具备大促高峰流量的降级可配置

4.2 常见的系统日志上报方案

第一步:应用系统所在机器.一般是 Linux 完成系统日志采集.当发生所关心的日志文件变化时.由监听的进程将日志发送这里有很多种选择.常见的如下:

rsyslog:相对性能比较好,久经考验的老战士.配置较为复杂.
filebeat:性能相比没有rsyslog好.但使用相对简单.使用也比较广泛.

第二步:完成服务端日志接收.这里一般是 Logstash.也就是我们常说的ELK里的L.

第三步:完成日志入库.这里的库可以是 message.es.redis.mysql 集成的三方还是比较多的.

第四步:选择合适的工具来完成日志的展示.比如说:kibana

4.2.1 ELK 方案

在这里插入图片描述

一般比较常见的大厂方案基本如此.

  • step1:通过 slf4j 门面完成应用日志文件输出.
  • step2:通过 rsyslog 监听文件变更完成日志文件发送.
  • step3:通过 logstash 完成日志服务端解析发送.支持的插件也比较多.
    具体可参考: https://www.elastic.co/guide/en/logstash/current/output-plugins.html
    -step4:完成 es 数据存储.

一键开箱即用的es存储满足巨量的存储且支持水平扩展.并提供比较友好的查询 kibana 能力.

适用场景:业务系统的日志打印抽取.
优点:完全独立在系统应用之外不影响任何系统性能;日志侧可以做到资源的友好伸缩.
缺点:巨量的日志打印后容易出现资源的浪费

4.2.2 自定义log appender 完成应用日志采集.

在这里插入图片描述

这种自定义appender方案比较适用于一些常见的后台操作.如ERP内部的用户日志记录.如:用户在2024年04月26日17:42:29 完成对租户 101 ,库存 201 的商品
库存调整。

4.3 日志常见框架傻傻分不清

一套日志编写标准.

SLF4J:是一套简易Java日志门面,本身并无日志的实现。(Simple Logging Facade for Java,缩写Slf4j)

以下为一些具体的实现.

  1. Jul (Java Util Logging):JDK中的日志记录工具,也常称为JDKLog、jdk-logging,自Java1.4以来的官方日志实现。
  2. Log4j:Apache Log4j是一个基于Java的日志记录工具。它是由Ceki Gülcü首创的,现在则是Apache软件基金会的一个项目。 Log4j是几种Java日志框架之一。
  3. Log4j2:一个具体的日志实现框架,是Log4j 1的下一个版本,与Log4j 1发生了很大的变化,Log4j 2不兼容Log4j 1。
  4. Logback:一个具体的日志实现框架,和Slf4j是同一个作者,但其性能更好。

4.4 日志在高并发系统中需要注意的 tips

4.4.1 配置合理的日志级别

常见的日志级别.
分别是 all, errorwarninginfodebugtrace

日常开发中,我们需要选择恰当的日志级别

  • all: 所有日志级别打印.
  • fatal :无法修复的程序异常
  • error :错误日志,指比较严重的错误,对正常业务有影响,需要运维配置监控的;通常我们会在throw异常时进行打印。
  • warn :警告日志,一般的错误,对业务影响不大,但是需要开发关注。
  • info :信息日志,记录排查问题的关键信息,通常我们会在方法入口和出口打印出入参信息等。
  • debug :用于开发DEBUG的,关键逻辑里面的运行时数据。通常我们用来调试关键程序,例如我们可以将SQL的日志级别调为debug,在本地或者测试环境调试时,可以看到具体SQL。
  • trace :最详细的信息,一般这些信息只记录到日志文件中。

对于一些流量比较高的场景线上尽量不打印非error级别日志.无差别打印所有级别日志将会对磁盘的造成性能损耗,很可能就会将磁盘打爆,进而影响正常的系统的业务IO

4.4.2 记录合理的链路

基于上一点我们总会有排查一些线上问题的时候,这无可避免。这时候如果要打印 用以排查问题的日志(非error级别),对于这种场景还是秉着尽可能少打印的原则。
比如说:保证能够做到随机抽量打印或者业务id过滤后打印,这个就视具体的业务类型而定。
如:库存,商品支持商品id来进行过滤;订单,售后支持订单id来进行过滤;

具备日志白名单(用户 id or pin )后查阅用户链路

4.4.3 配置异步打印

  • 添加依赖
<dependency>
         <groupId>com.lmax</groupId>
         <artifactId>disruptor</artifactId>
         <version>3.3.4</version>
</dependency>
  • 配置AsyncLogger

AsyncLogger是log4j2 的重头戏,也是官方推荐的异步方式。它可以使得调用Logger.log返回的更快,可以有两种选择:全局异步和混合异步。

    • 全局异步:所有的日志都异步的记录,在配置文件上不用做任何改动,只需要添加一个
      log4j2.component.properties 配置
      Log4jContextSelector=org.apache.logging.log4j.core.async.AsyncLoggerContextSelector
    • 混合异步:可以在应用中同时使用同步日志和异步日志,这使得日志的配置方式更加灵活
<Loggers>
         <AsyncLogger name="com.baixiu.aynclogger" level="trace" includeLocation="false" additivity="false">
                   <AppenderRef ref="file"/>
         </AsyncLogger>
        <Root level="info" includeLocation="true">
                   <AppenderRef ref="file"/>
         </Root>
</Loggers>

附完成的日志文件配置.

<?xml version='1.0' encoding="UTF-8" ?>
<Configuration status="DEBUG" monitorInterval="60">

    <Properties>
        <!-- 在当前目录下创建名为log目录做日志存放的目录 -->
        <Property name="LOG_FILE_PREFIX" value="/xxx/applicationName" />
        <!-- 日志文件大小,超过这个大小将被压缩 -->
        <Property name="LOG_FILE_MAX_SIZE" value="512 MB" />
        <!-- 触发rollover时最大计数 -->
        <Property name="REQUEST_MAX_HISTORY" value="2" />
        <Property name="MAIN_MAX_HISTORY" value="3" />
        <Property name="RPC_MAX_HISTORY" value="2" />
        <Property name="ERROR_MAX_HISTORY" value="3" />
        <Property name="FILE_LOG_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss}  %5level [%t] %logger{50} - [%X{PFTID}] - %msg%n"/>
        <Property name="LOG_ERROR_PATTERN" value="%d{yyyy-MM-dd HH:mm:ss} %5level [%t] %logger{50} - [%X{PFTID}] - %m%throwable{10}%n"    />
    </Properties>

    <Appenders>

        <Console name="CONSOLE" target="SYSTEM_OUT">
            <PatternLayout pattern="[%7r] %6p - %30.30c - %m \n"/>
        </Console>
        <RollingRandomAccessFile name="info" fileName="${LOG_FILE_PREFIX}/info.log"
                                 filePattern="${LOG_FILE_PREFIX}/info.%d{yyyy-MM-dd}_%i.log"
                                 immediateFlush="false">

            <Filters>
                <!-- 此Filter意思是,只输出ERROR级别的数据
                   DENY,日志将立即被抛弃不再经过其他过滤器;
                   NEUTRAL,有序列表里的下个过滤器过接着处理日志;
                   ACCEPT,日志会被立即处理,不再经过剩余过滤器。 -->
                <ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/>
            </Filters>

            <PatternLayout pattern="${FILE_LOG_PATTERN}"/>
            <Policies>
                <!-- 如果启用此配置,则日志会按文件名生成新文件,
                    即如果filePattern配置的日期格式为 %d{yyyy-MM-dd HH}
                   ,则每小时生成一个压缩文件, 如果filePattern配置的日期格式为 %d{yyyy-MM-dd} ,则天生成一个压缩文件,默认为1 -->
                <TimeBasedTriggeringPolicy modulate="true" interval="1"/>
                <SizeBasedTriggeringPolicy size="${LOG_FILE_MAX_SIZE}"/>
            </Policies>
            <!--文件夹下最多的文件个数-->
            <DefaultRolloverStrategy max="${MAIN_MAX_HISTORY}"/>
        </RollingRandomAccessFile>

        <RollingFile name="warning" fileName="${LOG_FILE_PREFIX}/warning.log"
                     filePattern="${LOG_FILE_PREFIX}/warning.%d{yyyy-MM-dd}_%i.log"
                     immediateFlush="false">
            <Filters>
                <ThresholdFilter level="ERROR" onMatch="ACCEPT" onMismatch="DENY"/>
            </Filters>
            <PatternLayout pattern="${LOG_ERROR_PATTERN}"/>
            <Policies>
                <TimeBasedTriggeringPolicy modulate="true" interval="1"/>
                <SizeBasedTriggeringPolicy size="${LOG_FILE_MAX_SIZE}"/>
            </Policies>
            <DefaultRolloverStrategy max="${ERROR_MAX_HISTORY}"/>
        </RollingFile>


   

        <RollingRandomAccessFile name="debug"
                                 fileName="${LOG_FILE_PREFIX}/debug.log"
                                 filePattern="${LOG_FILE_PREFIX}/flowLimit.%d{yyyy-MM-dd}.log">
            <PatternLayout pattern="${FILE_LOG_PATTERN}"/>
            <Policies>
                <TimeBasedTriggeringPolicy/>
                <SizeBasedTriggeringPolicy size="${LOG_FILE_MAX_SIZE}"/>
            </Policies>
            <DefaultRolloverStrategy>
                <Delete basePath="${LOG_FILE_PREFIX}" maxDepth="1">
                    <IfFileName glob="flowLimit.*.log" />
                    <IfAccumulatedFileCount exceeds="5" />
                </Delete>
            </DefaultRolloverStrategy>
        </RollingRandomAccessFile>

             <RollingFile name="error" fileName="${LOG_FILE_PREFIX}/error.log"
                     filePattern="${LOG_FILE_PREFIX}/error.%d{yyyy-MM-dd}_%i.log"
                     immediateFlush="false">
            <Filters>
                <ThresholdFilter level="INFO" onMatch="ACCEPT" onMismatch="DENY"/>
            </Filters>
            <PatternLayout pattern="${FILE_LOG_PATTERN}"/>
            <Policies>
                <TimeBasedTriggeringPolicy modulate="true" interval="1"/>
                <SizeBasedTriggeringPolicy size="${LOG_FILE_MAX_SIZE}"/>
            </Policies>
            <DefaultRolloverStrategy max="${REQUEST_MAX_HISTORY}"/>
        </RollingFile>

        <RollingRandomAccessFile name="customLog"
                                 fileName="${LOG_FILE_PREFIX}/customLog.log"
                                 filePattern="${LOG_FILE_PREFIX}/customLog.%d{yyyy-MM-dd}.log">
            <PatternLayout pattern="${FILE_LOG_PATTERN}"/>
            <Policies>
                <TimeBasedTriggeringPolicy/>
                <SizeBasedTriggeringPolicy size="${LOG_FILE_MAX_SIZE}"/>
            </Policies>
            <DefaultRolloverStrategy>
                <Delete basePath="${LOG_FILE_PREFIX}" maxDepth="1">
                    <IfFileName glob="timeoutException.*.log" />
                    <IfAccumulatedFileCount exceeds="5" />
                </Delete>
            </DefaultRolloverStrategy>
        </RollingRandomAccessFile>

    </Appenders>

    <Loggers>

        <AsyncLogger name="INFO" level="INFO" additivity="false">
            <AppenderRef ref="info"/>
        </AsyncLogger>

        <AsyncLogger name="WARN" level="WARN" additivity="false">
            <AppenderRef ref="warning"/>
        </AsyncLogger>

        <AsyncLogger name="debug" level="DEBUG" additivity="false">
            <AppenderRef ref="debug"/>
        </AsyncLogger>

        <AsyncLogger name="error" level="ERROR" additivity="false">
            <AppenderRef ref="error"/>
        </AsyncLogger>

        <AsyncRoot level="INFO" includeLocation="false">
        </AsyncRoot>

    </Loggers>
</Configuration>

如上配置: com.baixiu.aynclogger 日志是异步的,root 日志是同步的

赠人玫瑰 手有余香 我是柏修 一名持续更新的晚熟程序员
期待您的点赞,关注加收藏,加个关注不迷路,感谢
您的鼓励是我更新的最大动力
↓↓↓↓↓↓

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

神仙级Python入门教程,手把手教你从0到精通,学不会算我输!

亲爱的朋友们&#xff0c;你是否对编程充满好奇&#xff0c;却觉得它遥不可及&#xff1f; 你是否想学习一门强大的编程语言&#xff0c;却不知从何下手&#xff1f; 那么&#xff0c;这篇“神仙级”Python入门教程就是为你量身打造的&#xff01;不论你是编程小白还是有一定…

linux笔记4--shell命令1

文章目录 一. 目录1.说明2.盘符3.linux根目录(以Ubuntu为例)①说明②根目录下一些文件夹的解析/home/root/mnt/media/var/cdrom/etc/lib (/lib32--32位的&#xff0c;/lib64-64位的)/lostfound/boot/proc/bin/sbin/snap/srv/usr/opt/dev/run/tmp 二. ls命令--操作文件夹1.说明2…

探索阿里巴巴商品详情API接口:开启电商数据之旅

阿里巴巴商品详情API接口是阿里巴巴开放平台提供的一项服务&#xff0c;它允许开发者通过调用接口获取指定商品的详细信息&#xff0c;包括商品标题、价格、库存、描述、图片等。这些数据对于电商从业者来说具有极高的价值&#xff0c;可以帮助他们更好地了解市场动态&#xff…

层次分析法(AHP)计算原理解释

AHP层次分析法是一种解决多目标复杂问题的定性和定量相结合进行计算决策权重的研究方法。该方法将定量分析与定性分析结合起来&#xff0c;用决策者的经验判断各衡量目标之间能否实现的标准之间的相对重要程度&#xff0c;并合理地给出每个决策方案的每个标准的权数&#xff0c…

vue下载文件时显示进度条

1.单个下载&#xff08;开始是导出按钮 下载显示进度条&#xff09; html <el-button click.stop"exportReport(scope.row, scope.index)" v-if"!scope.row.schedule" icon"el-icon-download"size"small" type"text"styl…

Linux第十五章

&#x1f436;博主主页&#xff1a;ᰔᩚ. 一怀明月ꦿ ❤️‍&#x1f525;专栏系列&#xff1a;线性代数&#xff0c;C初学者入门训练&#xff0c;题解C&#xff0c;C的使用文章&#xff0c;「初学」C&#xff0c;linux &#x1f525;座右铭&#xff1a;“不要等到什么都没有了…

系统思考—企业辅导咨询

从2004年、2014年到2024年&#xff0c;国九条政策的发布与变迁不仅影响了行业趋势&#xff0c;更深刻地改变了企业的风险预估和策略辅导。彼得杜鲁克曾经说过&#xff1a;“必须系统地抛弃旧知识。”这不仅是企业领导者的挑战&#xff0c;也是我们每个人的难题。难点不在于我们…

GITEE 基于OAuth2的API V5版本

为了构建更好的码云生态环境&#xff0c;我们推出了基于OAuth2的API V5版本。 API V5接口使用方式以及Url都参照GitHub&#xff0c;为了各位开发者更好的兼容已经存在的第三方应用。 API 使用条款 OSCHINA 用户是资源的拥有者&#xff0c;需尊重和保护用户的权益。不能在应用…

Spring AI 抢先体验,5 分钟玩转 Java AI 应用开发

作者&#xff1a;刘军 Spring AI 是 Spring 官方社区项目&#xff0c;旨在简化 Java AI 应用程序开发&#xff0c;让 Java 开发者像使用 Spring 开发普通应用一样开发 AI 应用。 Spring Cloud Alibaba AI 以 Spring AI 为基础&#xff0c;并在此基础上提供阿里云通义系列大模…

XY_RE复现(二)

一&#xff0c;何须相思煮余年 0x55 0x8b 0xec 0x81 0xec 0xa8 0x0 0x0 0x0 0xa1 0x0 0x40 0x41 0x0 0x33 0xc5 0x89 0x45 0xfc 0x68 0x9c 0x0 0x0 0x0 0x6a 0x0 0x8d 0x85 0x60 0xff 0xff 0xff 0x50 0xe8 0x7a 0xc 0x0 0x0 0x83 0xc4…

编译Qt6.5.3LTS版本(Mac/Windows)的mysql驱动(附带编译后的全部文件)

文章目录 0 背景1 编译过程2 福利参考 0 背景 因为项目要用到对MYSQL数据库操作&#xff0c;所以需要连接到MYSQL数据库。但是连接需要MYSQL驱动&#xff0c;但是Qt本身不自带MYSQL驱动&#xff0c;需要自行编译。网上有很多qt之前版本的mysql驱动&#xff0c;但是没有找到qt6…

SiO2杂化纳米纤维膜

SiO2杂化纳米纤维膜是一种结合了二氧化硅&#xff08;SiO2&#xff09;纳米颗粒和其他材料&#xff08;如聚合物&#xff09;的复合纳米纤维膜。这种膜材料结合了SiO2的良好性能&#xff08;如高硬度、高耐磨性、热稳定性等&#xff09;和其他材料的特性&#xff08;如柔韧性、…

【XR806开发板试用】基于XR806实现智能小车

一、实验功能&#xff1a; 1、 基于XR806实现WIFI连接路由器 2、 XR806设备创建TCP socket服务器&#xff0c;局域网内通过PC端TCP客服端连接XR806 TCP服务器进行指令控制小车运行&#xff08;指令&#xff21;&#xff1a;前进、&#xff22;&#xff1a;后退、&#xff23;&…

等保测评有那些流程?为什么要做等保

根据《网络安全法》规定&#xff0c;网络运营者应当按照国家的网络安全技术标准和要求&#xff0c;采取技术措施保障网络安全&#xff0c;避免网络安全事件的发生。而等保测评是国家对企事业单位进行信息系统安全等级评定的一项重要制度&#xff0c;通过等级测评&#xff0c;可…

五一出去玩,随身WiFi纽曼和格行,哪个更值得选择?2024随身WiFi大流量全国通用,2024随身WiFi推荐第一名

临近五一&#xff0c;有太多的朋友需要出去游玩&#xff0c;但是会面临网络差&#xff0c;流量不够用等问题&#xff0c;从而选择随身WiFi。那么有非常多的朋友就纠结了&#xff0c;作为老牌企业的格行和纽曼到底选择哪个呢&#xff1f;下面我们将会从网速、续航、售后、客户评…

鸿蒙OpenHarmony【标准系统 烧录】(基于RK3568开发板)

烧录 烧录是指将编译后的程序文件下载到芯片开发板上的动作&#xff0c;为后续的程序调试提供基础。DevEco Device Tool提供一键烧录功能&#xff0c;操作简单&#xff0c;能快捷、高效的完成程序烧录&#xff0c;提升烧录的效率。 RK3568的镜像烧录通过Windows环境进行烧录&…

齐鲁制药集团李伯涛:40年不忘初心,助推企业高质量发展

一个成功的企业&#xff0c;离不开一个思想超前的优秀引领者&#xff0c;齐鲁制药亦是如此。在过去几十年的发展中&#xff0c;在董事长李伯涛的带领下&#xff0c;齐鲁制药研发出一系列领先的药品&#xff0c;不断占据国内、国际医药市场&#xff0c;逐渐成长为具有国际影响力…

Qt QLineEdit详解

1.简介 QLineEdit是一个单行文本编辑器。 行编辑允许用户使用一组有用的编辑功能输入和编辑单行纯文本&#xff0c;包括撤消和重做、剪切和粘贴以及拖放。 通过更改行编辑的echoMode&#xff0c;它也可以用作“只写”字段&#xff0c;用于密码等输入。 文本的长度可以限制为ma…

Web 服务器解析漏洞 原理以及修复方法

漏洞名称 &#xff1a;Web服务器解析漏洞 漏洞描述&#xff1a; 服务器相关中间件存在一些解析漏洞&#xff0c;攻击者可通过上传一定格式的文件&#xff0c;被服务器的中间件进行了解析&#xff0c;这样就对系统造成一定危害。常见的服务器解析漏洞涉及的中间件有IIS&#x…

详解CCF-CSP 202312-3 树上搜索

详解CCF-CSP 202312-3 树上搜索 原题连接 202312-3 树上搜索 代码及详细注释 //一个树形结构的处理程序&#xff0c;主要用于处理一些权重相关的查询 #include <iostream> #include <vector> #include <set>//定义全局变量 //好处&#xff1a; //&#…