【分布式事务1-seata客户端源码分析】

文章目录

  • 启动seata客户端
    • 1.导入依赖
    • 2.自动装配
  • 发送请求的核心方法
  • 客户端开启事务的核心流程
  • 服务端分布式事务的处理机制

启动seata客户端

1.导入依赖

<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.12.RELEASE</version>
    </parent>
    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <!-- 选择SpringCloudAlibaba版本的时候,一定要参考官网的建议,否则会有问题 -->
        <spring-cloud.version>Hoxton.SR12</spring-cloud.version>
        <spring-cloud-alibaba.version>2.2.9.RELEASE</spring-cloud-alibaba.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring-cloud-alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>

    </dependencyManagement>
    <dependencies>
        <!-- nacos服务注册与发现 -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <!--引入seata-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

客户端启动流程图
在这里插入图片描述

2.自动装配

自动装配的核心类
在这里插入图片描述
在SeataAutoConfiguration我们找到对应注入的类GlobalTransactionScanner,通过名称我们应该推算出,他应该是对应@GlobalTransaction进行扫描,然后注入到容器
我们先看下GlobalTransactionScanner类继承的类
在这里插入图片描述
创建的代理类

  protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
        if (!this.doCheckers(bean, beanName)) {
            return bean;
        } else {
            try {
                synchronized(PROXYED_SET) {
                	//如果代理已经存在直接返回bean对象
                    if (PROXYED_SET.contains(beanName)) {
                        return bean;
                    } else {
                        this.interceptor = null;
                        //判断是否是TCC模式
                        if (TCCBeanParserUtils.isTccAutoProxy(bean, beanName, this.applicationContext)) {
                            TCCBeanParserUtils.initTccFenceCleanTask(TCCBeanParserUtils.getRemotingDesc(beanName), this.applicationContext);
                            this.interceptor = new TccActionInterceptor(TCCBeanParserUtils.getRemotingDesc(beanName));
                            ConfigurationCache.addConfigListener("service.disableGlobalTransaction", new ConfigurationChangeListener[]{(ConfigurationChangeListener)this.interceptor});
                        } else {
                            Class<?> serviceInterface = SpringProxyUtils.findTargetClass(bean);
                            Class<?>[] interfacesIfJdk = SpringProxyUtils.findInterfaces(bean);
                       	//判断是否是被注解@globalTransactional或者@GlobalLock代理的类

                            if (!this.existsAnnotation(new Class[]{serviceInterface}) && !this.existsAnnotation(interfacesIfJdk)) {
                                return bean;
                            }
                            //创建globalTransactionalInterceptor拦截器
                            if (this.globalTransactionalInterceptor == null) {
                                this.globalTransactionalInterceptor = new GlobalTransactionalInterceptor(this.failureHandlerHook);
                                ConfigurationCache.addConfigListener("service.disableGlobalTransaction", new ConfigurationChangeListener[]{(ConfigurationChangeListener)this.globalTransactionalInterceptor});
                            }

                            this.interceptor = this.globalTransactionalInterceptor;
                        }

                        LOGGER.info("Bean[{}] with name [{}] would use interceptor [{}]", new Object[]{bean.getClass().getName(), beanName, this.interceptor.getClass().getName()});
                        if (!AopUtils.isAopProxy(bean)) {
                            bean = super.wrapIfNecessary(bean, beanName, cacheKey);
                        } else {
                            AdvisedSupport advised = SpringProxyUtils.getAdvisedSupport(bean);
                            //获取拦截器
                            Advisor[] advisor = this.buildAdvisors(beanName, this.getAdvicesAndAdvisorsForBean((Class)null, (String)null, (TargetSource)null));
                            Advisor[] var8 = advisor;
                            int var9 = advisor.length;

                            for(int var10 = 0; var10 < var9; ++var10) {
                                Advisor avr = var8[var10];
                                int pos = this.findAddSeataAdvisorPosition(advised, avr);
                                advised.addAdvisor(pos, avr);
                            }
                        }

                        PROXYED_SET.add(beanName);
                        return bean;
                    }
                }
            } catch (Exception var14) {
                throw new RuntimeException(var14);
            }
        }
    }

事务管理器TM,资源管理器RM初始化实在实例化之后进行这个是在GlobalTransactionScanner
继承的InitializingBean的afterPropertiesSet方法中实现InitializingBean接口的使用
实现InitializingBean接口的bean,在Spring容器初始化并设置所有bean属性后,会调用其afterPropertiesSet()方法。这通常用于在bean的属性全部设置完毕后需要进行的一些自定义初始化工作,例如验证属性或建立资源连接。


    public void afterPropertiesSet() {
    //判断是否开启事务
        if (this.disableGlobalTransaction) {
            if (LOGGER.isInfoEnabled()) {
                LOGGER.info("Global transaction is disabled.");
            }
			//添加监听器  
          ConfigurationCache.addConfigListener("service.disableGlobalTransaction", new ConfigurationChangeListener[]{this});
        } else {
        //CAS将初始化置换成True
            if (this.initialized.compareAndSet(false, true)) {
            	//初始化客户端
                this.initClient();
            }

        }
    }

初始化客户端的代码

private void initClient() {
        if (LOGGER.isInfoEnabled()) {
            LOGGER.info("Initializing Global Transaction Clients ... ");
        }

        if ("my_test_tx_group".equals(this.txServiceGroup)) {
            LOGGER.warn("the default value of seata.tx-service-group: {} has already changed to {} since Seata 1.5, please change your default configuration as soon as possible and we don't recommend you to use default tx-service-group's value provided by seata", "my_test_tx_group", "default_tx_group");
        }

        if (!StringUtils.isNullOrEmpty(this.applicationId) && !StringUtils.isNullOrEmpty(this.txServiceGroup)) {
        	//初始化TM客户端
            TMClient.init(this.applicationId, this.txServiceGroup, accessKey, secretKey);
            if (LOGGER.isInfoEnabled()) {
                LOGGER.info("Transaction Manager Client is initialized. applicationId[{}] txServiceGroup[{}]", this.applicationId, this.txServiceGroup);
            }
			//初始化RM客户端
            RMClient.init(this.applicationId, this.txServiceGroup);
            if (LOGGER.isInfoEnabled()) {
                LOGGER.info("Resource Manager is initialized. applicationId[{}] txServiceGroup[{}]", this.applicationId, this.txServiceGroup);
            }

            if (LOGGER.isInfoEnabled()) {
                LOGGER.info("Global Transaction Clients are initialized. ");
            }

            this.registerSpringShutdownHook();
        } else {
            throw new IllegalArgumentException(String.format("applicationId: %s, txServiceGroup: %s", this.applicationId, this.txServiceGroup));
        }
    }

TM和RM底层都是用的Netty进行的通讯
TM的初始化

    public static void init(String applicationId, String transactionServiceGroup, String accessKey, String secretKey) {
        TmNettyRemotingClient tmNettyRemotingClient = TmNettyRemotingClient.getInstance(applicationId, transactionServiceGroup, accessKey, secretKey);
        tmNettyRemotingClient.init();
    }

RM的初始化

    public static void init(String applicationId, String transactionServiceGroup) {
        RmNettyRemotingClient rmNettyRemotingClient = RmNettyRemotingClient.getInstance(applicationId, transactionServiceGroup);
        rmNettyRemotingClient.setResourceManager(DefaultResourceManager.get());
        rmNettyRemotingClient.setTransactionMessageHandler(DefaultRMHandler.get());
        rmNettyRemotingClient.init();
    }

发送请求的核心方法

在这里插入图片描述

 public Object invoke(final MethodInvocation methodInvocation) throws Throwable {
 		//利用AOP获取代理类
        Class<?> targetClass = methodInvocation.getThis() != null ? AopUtils.getTargetClass(methodInvocation.getThis()) : null;
        //获取代理的方法
        Method specificMethod = ClassUtils.getMostSpecificMethod(methodInvocation.getMethod(), targetClass);
        if (specificMethod != null && !specificMethod.getDeclaringClass().equals(Object.class)) {
            Method method = BridgeMethodResolver.findBridgedMethod(specificMethod);
            //判断此方法是否被@GlobalTranscation修饰
            GlobalTransactional globalTransactionalAnnotation = (GlobalTransactional)this.getAnnotation(method, targetClass, GlobalTransactional.class);
            //判断此方法是否被注解@GlobalLock修饰
            GlobalLock globalLockAnnotation = (GlobalLock)this.getAnnotation(method, targetClass, GlobalLock.class);
            boolean localDisable = this.disable || degradeCheck && degradeNum >= degradeCheckAllowTimes;
            if (!localDisable) {
                if (globalTransactionalAnnotation != null || this.aspectTransactional != null) {
                    AspectTransactional transactional;
                    if (globalTransactionalAnnotation != null) {
                        transactional = new AspectTransactional(globalTransactionalAnnotation.timeoutMills(), globalTransactionalAnnotation.name(), globalTransactionalAnnotation.rollbackFor(), globalTransactionalAnnotation.rollbackForClassName(), globalTransactionalAnnotation.noRollbackFor(), globalTransactionalAnnotation.noRollbackForClassName(), globalTransactionalAnnotation.propagation(), globalTransactionalAnnotation.lockRetryInterval(), globalTransactionalAnnotation.lockRetryTimes());
                    } else {
                        transactional = this.aspectTransactional;
                    }
	//被@GlobalTranstional修饰的方法进入此方法
                    return this.handleGlobalTransaction(methodInvocation, transactional);
                }
	//被@GlobalLock修饰的方法进入此类
                if (globalLockAnnotation != null) {
                    return this.handleGlobalLock(methodInvocation, globalLockAnnotation);
                }
            }
        }

        return methodInvocation.proceed();
    }

事务的核心方法TransactionalTemplate的excute方法

 public Object execute(TransactionalExecutor business) throws Throwable {
 	//获取事务信息
        TransactionInfo txInfo = business.getTransactionInfo();
        //如果为空直接抛异常
        if (txInfo == null) {
            throw new ShouldNeverHappenException("transactionInfo does not exist");
        } else {
        	//创建或者获取全局事务标志xid
            GlobalTransaction tx = GlobalTransactionContext.getCurrent();
            //获取事务的传播机制
            Propagation propagation = txInfo.getPropagation();
            SuspendedResourcesHolder suspendedResourcesHolder = null;

            try {
                Object var6;
                switch(propagation) {
                case NOT_SUPPORTED:
                    if (this.existingTransaction(tx)) {
                        suspendedResourcesHolder = tx.suspend();
                    }

                    var6 = business.execute();
                    return var6;
                case REQUIRES_NEW:
                    if (this.existingTransaction(tx)) {
                        suspendedResourcesHolder = tx.suspend();
                        tx = GlobalTransactionContext.createNew();
                    }
                    break;
                case SUPPORTS:
                    if (this.notExistingTransaction(tx)) {
                        var6 = business.execute();
                        return var6;
                    }
                case REQUIRED:
                    break;
                case NEVER:
                    if (this.existingTransaction(tx)) {
                        throw new TransactionException(String.format("Existing transaction found for transaction marked with propagation 'never', xid = %s", tx.getXid()));
                    }

                    var6 = business.execute();
                    return var6;
                case MANDATORY:
                    if (this.notExistingTransaction(tx)) {
                        throw new TransactionException("No existing transaction found for transaction marked with propagation 'mandatory'");
                    }
                    break;
                default:
                    throw new TransactionException("Not Supported Propagation:" + propagation);
                }
				//如果事务的xid为空,则重新创建一个新的
                if (tx == null) {
                    tx = GlobalTransactionContext.createNew();
                }
				//获取全局锁配置
                GlobalLockConfig previousConfig = this.replaceGlobalLockConfig(txInfo);

                try {
                	//开启全局事务
                    this.beginTransaction(txInfo, tx);

                    Object rs;
                    Object ex;
                    try {
                        rs = business.execute();
                    } catch (Throwable var17) {
                        ex = var17;
                        this.completeTransactionAfterThrowing(txInfo, tx, var17);
                        throw var17;
                    }

                    this.commitTransaction(tx);
                    ex = rs;
                    return ex;
                } finally {
                    this.resumeGlobalLockConfig(previousConfig);
                    this.triggerAfterCompletion();
                    this.cleanUp();
                }
            } finally {
                if (suspendedResourcesHolder != null) {
                    tx.resume(suspendedResourcesHolder);
                }

            }
        }
    }

客户端开启事务的核心流程

在这里插入图片描述

    private void beginTransaction(TransactionInfo txInfo, GlobalTransaction tx) throws ExecutionException {
        try {
        	//执行开启事务前的操作
            this.triggerBeforeBegin();
            //开启事务
            tx.begin(txInfo.getTimeOut(), txInfo.getName());
            //执行开启事务后的操作
            this.triggerAfterBegin();
        } catch (TransactionException var4) {
            throw new ExecutionException(tx, var4, Code.BeginFailure);
        }
    }
 public void begin(int timeout, String name) throws TransactionException {
 		//判断当前的角色是不是Launcher
        if (this.role != GlobalTransactionRole.Launcher) {
        	//不是判断当前的xid是否为null
            this.assertXIDNotNull();
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("Ignore Begin(): just involved in global transaction [{}]", this.xid);
            }

        } else {
        	//不是判断当前的xid是否为null
            this.assertXIDNull();
            String currentXid = RootContext.getXID();
            if (currentXid != null) {
                throw new IllegalStateException("Global transaction already exists, can't begin a new global transaction, currentXid = " + currentXid);
            } else {
            	//开启事务,请求后台服务,返回xid
                this.xid = this.transactionManager.begin((String)null, (String)null, name, timeout);
                //将事务状态置为开启
                this.status = GlobalStatus.Begin;
                //绑定xid
                RootContext.bind(this.xid);
                if (LOGGER.isInfoEnabled()) {
                    LOGGER.info("Begin new global transaction [{}]", this.xid);
                }

            }
        }
    }

服务端分布式事务的处理机制

在这里插入图片描述

 protected void doGlobalBegin(GlobalBeginRequest request, GlobalBeginResponse response, RpcContext rpcContext)
            throws TransactionException {
        /**
         * 调用core.begin开启事务,并持久化
         * 给response设置全局事务编号XID*/
        response.setXid(core.begin(rpcContext.getApplicationId(), rpcContext.getTransactionServiceGroup(),
                request.getTransactionName(), request.getTimeout()));
        if (LOGGER.isInfoEnabled()) {
            LOGGER.info("Begin new global transaction applicationId: {},transactionServiceGroup: {}, transactionName: {},timeout:{},xid:{}",
                    rpcContext.getApplicationId(), rpcContext.getTransactionServiceGroup(), request.getTransactionName(), request.getTimeout(), response.getXid());
        }
    }
    public String begin(String applicationId, String transactionServiceGroup, String name, int timeout)
        throws TransactionException {
        //key1:创建全局会话,这里面已经创建了全局事务Id
        GlobalSession session = GlobalSession.createGlobalSession(applicationId, transactionServiceGroup, name,
            timeout);
        MDC.put(RootContext.MDC_KEY_XID, session.getXid());
        // 添加事务生命周期监听器
        session.addSessionLifecycleListener(SessionHolder.getRootSessionManager());
        //2、 开启事务,这里有事务持久话的一个机制
        session.begin();

        // transaction start event
        //  发送事务开启事件
        MetricsPublisher.postSessionDoingEvent(session, false);
        // 返回全局事务ID
        return session.getXid();
    }
    @Override
    public void begin() throws TransactionException {
        this.status = GlobalStatus.Begin;
        this.beginTime = System.currentTimeMillis();
        this.active = true;
        for (SessionLifecycleListener lifecycleListener : lifecycleListeners) {
            // 在这里处理
            lifecycleListener.onBegin(this);
        }
    }
private void writeSession(LogOperation logOperation, SessionStorable sessionStorable) throws TransactionException {
        // 将事务信息写入数据库
        if (!transactionStoreManager.writeSession(logOperation, sessionStorable)) {
            if (LogOperation.GLOBAL_ADD.equals(logOperation)) {
                throw new GlobalTransactionException(TransactionExceptionCode.FailedWriteSession,
                    "Fail to store global session");
            } else if (LogOperation.GLOBAL_UPDATE.equals(logOperation)) {
                throw new GlobalTransactionException(TransactionExceptionCode.FailedWriteSession,
                    "Fail to update global session");
            } else if (LogOperation.GLOBAL_REMOVE.equals(logOperation)) {
                throw new GlobalTransactionException(TransactionExceptionCode.FailedWriteSession,
                    "Fail to remove global session");
            } else if (LogOperation.BRANCH_ADD.equals(logOperation)) {
                throw new BranchTransactionException(TransactionExceptionCode.FailedWriteSession,
                    "Fail to store branch session");
            } else if (LogOperation.BRANCH_UPDATE.equals(logOperation)) {
                throw new BranchTransactionException(TransactionExceptionCode.FailedWriteSession,
                    "Fail to update branch session");
            } else if (LogOperation.BRANCH_REMOVE.equals(logOperation)) {
                throw new BranchTransactionException(TransactionExceptionCode.FailedWriteSession,
                    "Fail to remove branch session");
            } else {
                throw new BranchTransactionException(TransactionExceptionCode.FailedWriteSession,
                    "Unknown LogOperation:" + logOperation.name());
            }
        }
    }

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

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

相关文章

NoSQL-Tidis支持分布式事务,兼容redis协议,使用tikv存储引擎,可水平扩展

项目repo地址 GitHub - yongman/tidis: Distributed transactional NoSQL database, Redis protocol compatible using tikv as backend Tidis是分布式数据库,支持redis协议,多种数据结构支持,编写语言为golang。 Tidis工作角色类似于TIDB,提供协议转换和数据结构计算,底…

软件设计不是CRUD(22):在流式数据处理系统中进行业务抽象落地——设计思考

(接上文《软件设计不是CRUD(21):在流式数据处理系统中进行业务抽象落地——需求分析》) 那么思考到这里我们就能做一些关于设计思路的总结: 每一个独立的数据处理流,就是数据采集系统中的一个功能。这个功能具备一个静态的控制逻辑(当然控制逻辑也可以是动态的,本文不…

Python学习笔记12:进阶篇(二),类的继承与组合

类的继承 我们在编写一系列的类的时候&#xff0c;会发现这些类很相似&#xff0c;但是又有各自的特点和行为。在编写这些类的时候&#xff0c;我们可以把相同的部分抽象成一个基类&#xff0c;然后根据其他不同的特点和行为&#xff0c;抽象出子类&#xff0c;继承这个基类。…

DY-48电压继电器 板前接线导轨安装 约瑟JOSEF

DY-40系列导轨式电压继电器是用于继电保护线路中&#xff0c;作为过电压保护或低电压闭锁的动作元件1。 电压继电器用于继电保护线路中&#xff0c;作为过电压保护或低电压闭锁的动作元件。其主要特点如下1&#xff1a; 动作范围&#xff1a;过电压继电器&#xff1a;1.212倍…

移植案例与原理 - build lite配置目录全梳理

命令行工具hb(HarmonyOS|OpenHarmony Build 编译构建系统的缩写)都很熟悉了。这是一个基于gn和ninja的构建系统&#xff0c;以支持OpenHarmony组件化开发为目标&#xff0c;提供以下基本功能&#xff1a; 支持按组件拼装产品并编译。 独立构建芯片解决方案厂商源码。 独立构建…

自杀行为的神经生物学认识

自杀行为的神经生物学认识 编译 李升伟 隐藏在自杀行为背后的大脑生化机制正引领人类对自杀的认识从黑暗步入光明。科学家希望未来这些机制能带来更好的治疗和预防策略。 基斯 • 范希林根&#xff08;Cornelis Van Heeringen&#xff09;第一次遇见瓦莱丽&#xff08; Va…

oracle12c到19c adg搭建(二)oracle12c数据库软件安装

运行安装程序 不勾选 只安装软件 选择单实例安装 选择语言 企业版 确认目录 产品目录 用户组 开始安装 执行root脚本 [rooto12u19p software]# /u01/app/oraInventory/orainstRoot.sh Changing permissions of /u01/app/oraInventory. Adding read,write permissions for gro…

操作系统笔记(自用随笔)

如有错误&#xff0c;欢迎指正&#xff01;&#xff01;&#xff01;

Chromium 开发指南2024 Mac篇-Xcode安装(二)

1.引言 在开始编译和开发 Chromium 之前&#xff0c;确保开发环境的正确配置是至关重要的。对于 Mac 用户来说&#xff0c;Xcode 是不可或缺的工具&#xff0c;因为它不仅提供了必需的编译器和工具链&#xff0c;还包含了与 macOS 系统深度整合的开发资源。在本系列指南的第一…

深度学习(十)——神经网络:非线性激活

一、Padding Layers简介 nn.ZeroPad2d&#xff1a;在输入的tensor数据类型周围用0进行填充 nn.ConstantPad2d&#xff1a;在输入的tensor数据类型周围用常数进行填充 这个函数的主要作用是对输入的图像进行填充&#xff0c;但里面所有功能都能用nn.Conv2d实现。 二、Non-li…

HTB Editorial

Editorial User Nmap ┌──(kali㉿kali)-[~/…/machine/SeasonV/linux/Editorial] └─$ nmap -A 10.129.24.67 -T 4 Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-06-16 21:54 EDT Nmap scan report for 10.129.2…

03-ES6新语法

1. ES6 函数 1.1 函数参数的扩展 1.1.1 默认参数 function fun(name,age17){console.log(name","age); } fn("张美丽",18); // "张美丽",18 fn("张美丽",""); // "张美丽" fn("张美丽"); // &…

嵌入式技术学习——c51单片机——蜂鸣器

一、蜂鸣器介绍 蜂鸣器时一种将电信号转化成声音信号的器件&#xff0c;常用来产生设备的按键音&#xff0c;报警音等提示信号。 蜂鸣器分为有源蜂鸣器&#xff0c;无源蜂鸣器 。 有源蜂鸣器&#xff1a;内部自带震荡源&#xff0c;将正负极街上直流电压即可持续发声&#x…

Windows系统部署本地SQL_Server指引

Windows系统部署本地SQL_Server指引 此指引文档环境为Windows10系统&#xff0c;部署SQL_Server 2019为例&#xff0c;同系列系统软件安装步骤类似。 一、部署前准备&#xff1b; 下载好相关镜像文件&#xff1b;设备系统启动后&#xff0c;将不必要的软件停用&#xff0c;避…

全开源版人才招聘系统源码 小程序运营级平台源码 类似58同城招聘、智联招聘平台

在当今数字化时代&#xff0c;人才招聘与平台运营成为了企业发展的重要环节。分享一套功能全面、易于二次开发的人才招聘系统源码小程序运营级平台源码。这些源码基于类似58同城招聘、智联招聘等大型招聘平台的设计理念&#xff0c;旨在为企业提供高效、便捷的人才招聘与平台运…

HCIP认证笔记(填空)

1、为防止攻击者伪造BGP报文对设备进行攻击,可以通过配置GTSM功能检测IP报文中的TTL值的范围来对设备进行保护。如果某台设备配置了“peer x.x.x.x valid-ttl-hops 100",则被检测的报文的TTL值的有效范围为【(156),255】; 解析: peer {group-name | ipv4-address…

排序——快速排序

目录 思想 演示 代码实现 解释 优化 三数取中 小区间优化 补充 挖坑法 双指针法 非递归实现 思想 快速排序是一种二叉树结构的交换排序方法。 基本思想为&#xff1a;任取待排序元素序列中的某元素作为基准值&#xff0c;按照该排序码将待排序集合分割成两子序列&am…

[渗透测试学习] SolarLab-HackTheBox

SolarLab-HackTheBox 信息搜集 nmap扫描端口 nmap -sV -v 10.10.11.16扫描结果如下 PORT STATE SERVICE VERSION 80/tcp open http nginx 1.24.0 135/tcp open msrpc Microsoft Windows RPC 139/tcp open netbios-ssn Microsoft Windows n…

【漏洞复现】致远互联FE协作办公平台 ncsubjass SQL注入

0x01 产品简介 致远互联FE协作办公平台是一款为企业提供全方位协同办公解决方案的产品。它集成了多个功能模块&#xff0c;旨在帮助企业实现高效的团队协作、信息共享和文档管理。 0x02 漏洞概述 致远互联FE协作办公平台 ncsubjass.jsp接口处存在SQL注入漏洞,未经身份验证的…

1.4k star 项目 CMakeTutorial 阅读和点评

1.4k star 项目 CMakeTutorial 阅读和点评 文章目录 1.4k star 项目 CMakeTutorial 阅读和点评0. 概要1. CUDA 目录2. FindPackage 目录3. Installation 目录4. PackageManage 目录5. PythonExtension 目录6. ImportExternalProject 目录总结 0. 概要 在 github 搜索关键字 CM…