从安装 Seata 开始的分布式事务之旅 springboot集成seata

从安装 Seata 开始的分布式事务之旅

  • 介绍
    • 什么是 Seata?
  • 安装 Seata Server
    • 下载 Seata Server 发行版
    • 配置Seata
      • 解压文件
      • 配置Seata的yml文件
      • 把配置文件config.txt加载到nacos上
        • 修改config.txt文件
        • 加载到nacos上
    • 启动Seata服务
      • 正常启动
        • 查看启动日志
        • 打开控制台页面
      • 启动时遇到的坑
        • 无法解析${console.user.username}的值
        • 无法解析${seata.security.secretKey}的值
        • 数据库连接问题
  • 在 Spring Boot 项目中集成 Seata
    • 工作环境
    • cloud、boot、alibaba环境
    • 添加依赖
    • 配置yml
    • 业务代码中集成 Seata
      • 使用 `@GlobalTransactional` 注解管理全局事务
      • 演示 AT(自动补偿)模式和 TCC(两阶段提交)模式
        • 使用 AT(自动补偿)模式
        • 使用 TCC(两阶段提交)模式
    • 集成Seata踩的坑
      • Table 'ddz.undo_log' doesn't exist
      • no available service 'null' found, please make sure registry config correct
      • 分布式事务未生效
      • dynamic-datasource can not find primary datasource
      • Communications link failure
  • 总结
  • 参考资料

在这里插入图片描述

介绍

什么是 Seata?

在现代应用程序开发中,分布式系统的应用越来越广泛。然而,随着系统的复杂性增加,处理分布式事务变得愈发困难。这就是 Seata 出现的背景。Seata(Simple Extensible Autonomous Transaction Architecture)是一种开源的分布式事务解决方案,旨在解决分布式系统中的事务一致性和协调性问题。
在传统的单体应用中,通常使用关系型数据库来管理事务,保证数据的一致性。但在分布式系统中,由于涉及多个独立的服务,事务管理变得复杂。分布式事务的要求是:所有涉及的服务要么都成功提交,要么都回滚,以保持数据的一致性。

Seata 提供了两种主要的事务模式:

  1. AT 模式(自动补偿模式):在 AT 模式中,Seata会自动补偿事务,无需手动编写补偿逻辑。Seata会将事务的所有操作编排成一个全局的事务,然后执行各个分支的 try 操作,在出现异常时执行相应的补偿操作。

  2. TCC 模式(两阶段提交模式):TCC 模式要求开发者手动编写 Try、Confirm 和 Cancel 三个阶段的逻辑。在 TCC 模式中,Seata负责协调全局事务的提交和回滚,而各个分支的 try、confirm 和 cancel 操作则由开发者来实现。

Seata 还提供了可扩展的注册中心和存储支持,使其适用于各种不同的场景。

总的来说,Seata 是一个强大的分布式事务解决方案,可以帮助开发者解决分布式事务的难题,确保分布式系统中数据的一致性和可靠性。通过集成 Seata,开发者可以更加轻松地构建复杂的分布式应用,提升系统的稳定性和性能。

安装 Seata Server

下载 Seata Server 发行版

您可以从 Seata 官方网站下载最新的 Seata Server 发行版,并解压到指定目录;有源码和二进制版本,我们这里选择安装二进制文件下载。我的版本是1.7.0 (2023-07-11,推荐版本)
在这里插入图片描述

配置Seata

解压文件

在这里插入图片描述
下载下来的是zip文件,解压后是上面文件夹,默认文件夹名字是seata。

配置Seata的yml文件

进入seata/conf目录下,这里有两个配置文件; 我们需要把application.yml 随意修改一个名字;然后再 application.example.yml修改成application.yml 作为主要配置文件。
在这里插入图片描述
修改 application.yml文件,我这里使用的nacos作为注册中心,所以需要修改的地方有:

  1. seata:config:type
  2. seata:registry:type
  3. store:mode
  4. store:session:mode
  5. store: lock:mode
  6. store:db 数据库的配置修改成自己的

配置文件:

server:
  port: 7091

spring:
  application:
    name: seata-server

logging:
  config: classpath:logback-spring.xml
  file:
    path: ${user.home}/logs/seata
  extend:
    logstash-appender:
      destination: 127.0.0.1:4560
    kafka-appender:
      bootstrap-servers: 127.0.0.1:9092
      topic: logback_to_logstash
# 这里是主要的配置文件
seata:
  config:
    # support: nacos 、 consul 、 apollo 、 zk  、 etcd3
    type: nacos
    nacos:
      server-addr: 127.0.0.1:8848
      # 如果在nacos上添加了命名空间,则配置命令空间ID
      namespace:
      # 配置分组
      group: SEATA_GROUP
      username:
      password:
      context-path:
      ##if use MSE Nacos with auth, mutex with username/password attribute
      #access-key:
      #secret-key:
      data-id: seataServer.properties
  registry:
    # support: nacos 、 eureka 、 redis 、 zk  、 consul 、 etcd3 、 sofa
    type: nacos
    preferred-networks: 30.240.*
    nacos:
      application: seata-server
      server-addr: 127.0.0.1:8848
      group: SEATA_GROUP
      namespace:
      cluster: default
      username:
      password:
      context-path:
      ##if use MSE Nacos with auth, mutex with username/password attribute
      #access-key:
      #secret-key:
  server:
    service-port: 8091 #If not configured, the default is '${server.port} + 1000'
    max-commit-retry-timeout: -1
    max-rollback-retry-timeout: -1
    rollback-retry-timeout-unlock-enable: false
    enable-check-auth: true
    enable-parallel-request-handle: true
    retry-dead-threshold: 130000
    xaer-nota-retry-timeout: 60000
    enableParallelRequestHandle: true
    recovery:
      committing-retry-period: 1000
      async-committing-retry-period: 1000
      rollbacking-retry-period: 1000
      timeout-retry-period: 1000
    undo:
      log-save-days: 7
      log-delete-period: 86400000
    session:
      branch-async-queue-size: 5000 #branch async remove queue size
      enable-branch-async-remove: false #enable to asynchronous remove branchSession
  store:
    # support: file 、 db 、 redis
    mode: db
    session:
      mode: db
    lock:
      mode: db
    db:
      datasource: druid
      db-type: mysql
      driver-class-name: com.mysql.jdbc.Driver
      url: jdbc:mysql://127.0.0.1:3306/seata?rewriteBatchedStatements=true
      user: mysql
      password: mysql
      min-conn: 10
      max-conn: 100
      global-table: global_table
      branch-table: branch_table
      lock-table: lock_table
      distributed-lock-table: distributed_lock
      query-limit: 1000
      max-wait: 5000
  metrics:
    enabled: false
    registry-type: compact
    exporter-list: prometheus
    exporter-prometheus-port: 9898
  transport:
    rpc-tc-request-timeout: 15000
    enable-tc-server-batch-send-response: false
    shutdown:
      wait: 3
    thread-factory:
      boss-thread-prefix: NettyBoss
      worker-thread-prefix: NettyServerNIOWorker
      boss-thread-size: 1

把配置文件config.txt加载到nacos上

修改config.txt文件

config.txt文件在seata/script/config-center目录下;我们需要修改的地方有:

  1. store.mode=db
  2. store.lock.mode=db
  3. store.session.mode=db
  4. store.db 数据库的配置修改成自己的,和上面yml文件里面的一样

加载到nacos上

进入seata/script/config-center/nacos 目录下执行nacos-config.sh文件。

sh nacos-config.sh -h 121.37.228.169 -p 8848 -g SEATA_GROUP -t 0af6e97b-a684-4647-b696-7c6d42aecce7 -u nacos -w nacos
  • -h: Nacos IP地址
  • -p: Nacos端口号
  • -g: Group分组名
  • -t: 命名空间ID,没有则默认public
  • -u: 用户名
  • -w:密码
    执行完成时候登录我们的Nacos配置管理就能查看到加载好的数据:
    在这里插入图片描述

启动Seata服务

正常启动

进入seata/bin 目录下,执行命令:

sh seata-server.sh 

在这里插入图片描述

这里我启动的时候可以会遇到报异常的情况,下面我出了几种我在启动时遇到的一些坑。可以移步到 启动时遇到的坑

查看启动日志

我的是Mac系统所有是open打开日志文件,其他的系统需要根据系统来执行命令,或者直接进入seata/logs目录下查看start.out文件。

open /Users/ddz/Downloads/seata/logs/start.out

在这里插入图片描述
能看到日志输出地址说明启动成功了。

打开控制台页面

控制台页面,默认账号密码是 seata/seata。
在这里插入图片描述

启动时遇到的坑

这里是我在部署Seata中遇到的一些坑,可能和有不同的地方只做为参考。

无法解析${console.user.username}的值

异常信息: Could not resolve placeholder ‘console.user.username’ in value “${console.user.username}”
在这里插入图片描述
解决方法:需要把之前修改成其他名称的yml文件中console下的所有配置信息复制到现在的application.yml下。这里就是设置我们登录控制台页面的账号密码。

无法解析${seata.security.secretKey}的值

异常信息:Could not resolve placeholder ‘seata.security.secretKey’ in value “${seata.security.secretKey}”
在这里插入图片描述
解决方法:需要把之前修改成其他名称的yml文件中seata.security下的所有配置信息复制到现在的application.yml下。

数据库连接问题

异常信息:com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
在MySQL5.7之前的版本,安全性较低,存在任何用户都可以连接上数据库,所以官方在5.7版本加大了对隐私的保护。并且采用了默认 useSSL = true值防止对数据库的随意修改,到了8.0版本,仍然保留了SSL,并且默认值为 true。
在这里插入图片描述

解决方法:在数据库配置url后追加&useSSL=false;需要检查yml配置文件和Nacos上配置列表中store.db.url
在这里插入图片描述

在 Spring Boot 项目中集成 Seata

上面我们介绍了如何在本地安装seata服务端,接下来介绍一下我们Spring Boot项目中集成seata;这里我只单纯的用一个demo来介绍,可根据自己的业务逻辑来进行实现。

工作环境

  • MySQL 5.7.28
  • Maven 3.5.4
  • JDK 1.8
  • Mybatis 3.4.1
  • dynamic 3.4.1

cloud、boot、alibaba环境

   <spring-boot.version>2.3.7.RELEASE</spring-boot.version>
   <spring-cloud.version>Hoxton.SR9</spring-cloud.version>
   <spring-cloud-alibaba.version>2.2.6.RELEASE</spring-cloud-alibaba.version>

添加依赖

	<!--    MySQL    -->
	<dependency>
	    <groupId>mysql</groupId>
	    <artifactId>mysql-connector-java</artifactId>
	</dependency>
	<!--    Mybatis    -->
	<dependency>
	    <groupId>com.baomidou</groupId>
	    <artifactId>mybatis-plus-boot-starter</artifactId>
	    <version>3.4.1</version>
	</dependency>
	<!--    多数据源    -->
	<dependency>
	    <groupId>com.baomidou</groupId>
	    <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
	    <version>3.4.1</version>
	</dependency>
	<!--    Seata分布式事务    -->
	<dependency>
	    <groupId>com.alibaba.cloud</groupId>
	    <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
	</dependency>

配置yml

server:
  port: 7001
spring:
  application:
    name: ddz-user
  cloud:
    nacos:
      discovery:
        # 服务分组
        group: ddz
        server-addr: 121.37.228.111:8848
        # 必须填命名空间的ID
#        namespace: 9ebef975-dcc0-4430-9c63-1c62d8a86d82
  datasource:
    dynamic:
      # 开启seata分布式事务
      seata: true
      strict: false
      primary: master
      datasource:
        master:
          url: jdbc:mysql://121.37.228.111:3306/ddz?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&rewriteBatchedStatements=true
          username: ddz
          password: ddz2023
        local:
          url: jdbc:mysql://127.0.0.1:3306/ddz?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&rewriteBatchedStatements=true
          username: root
          password: ddz2023

# MyBatis Plus配置
mybatis-plus:
  # 搜索指定包别名
  typeAliasesPackage: com.ddz.**.entity
  # 配置mapper的扫描,找到所有的mapper.xml映射文件
  mapperLocations: classpath*:mapper/**/*.xml
  global-config:
    db-config:
      id-type: auto
  configuration:
    # 开启驼峰,开启后,只要数据库字段和对象属性名字母相同,无论中间加多少下划线都可以识别
    map-underscore-to-camel-case: true

# Seata 配置
seata:
  application-id: seata-server
  # 是否启用数据源bean的自动代理
  enable-auto-data-source-proxy: false
  tx-service-group: default_tx_group  # 必须和服务器配置一样
  registry:
    type: nacos
    nacos:
      # Nacos 服务地址
      server-addr: 121.37.228.111:8848
      group: SEATA_GROUP
#      namespace: 9ebef975-dcc0-4430-9c63-1c62d8a86d82
      application: seata-server # 必须和服务器配置一样
      #      username:
      #      password:
      cluster: default
  config:
    type: nacos
    nacos:
      server-addr: 121.37.228.111:8848
      group: SEATA_GROUP
#      namespace: 9ebef975-dcc0-4430-9c63-1c62d8a86d82
  service:
    vgroup-mapping:
      default_tx_group: default # 必须和服务器配置一样
    disable-global-transaction: false
  client:
    rm:
      # 是否上报成功状态
      report-success-enable: true
      # 重试次数
      report-retry-count: 5

业务代码中集成 Seata

我们根据两个数据源创建两个mapper类然后再controller中测试;我这里方便测试就省略了业务层。

使用 @GlobalTransactional 注解管理全局事务

在这里插入图片描述

演示 AT(自动补偿)模式和 TCC(两阶段提交)模式

使用 AT(自动补偿)模式

在 AT 模式中,Seata会自动补偿事务,无需手动编写补偿逻辑。首先,我们来演示一个简单的转账场景,将资金从一个账户转移到另一个账户,并保证事务的一致性。

  1. 添加 @GlobalTransactional 注解
    在转账服务的方法上添加 @GlobalTransactional 注解来标记全局事务:
@Service
public class TransferService {
    
    @GlobalTransactional
    public void transfer(String fromAccount, String toAccount, double amount) {
        // 扣除转出账户金额
        deductAmount(fromAccount, amount);

        // 增加转入账户金额
        addAmount(toAccount, amount);
    }

    // 实现扣除金额逻辑
    // ...

    // 实现增加金额逻辑
    // ...
}
  1. 测试 AT 模式
    编写测试用例来验证 AT 模式的事务管理:
@RunWith(SpringRunner.class)
@SpringBootTest
public class TransferServiceTest {

    @Autowired
    private TransferService transferService;

    @Test
    public void testTransfer() {
        // 假设从账户 A 转账 100 到账户 B
        transferService.transfer("accountA", "accountB", 100.0);
    }
}

运行测试用例,观察转账是否成功,并查看日志确认 Seata 是否自动补偿了事务。

使用 TCC(两阶段提交)模式

在 TCC 模式中,我们需要手动编写 Try、Confirm 和 Cancel 三个阶段的逻辑,以确保事务的正确执行。下面我们来演示一个简单的订单创建场景,包括下单、扣减库存和创建订单三个阶段。

  1. 实现 TCC 接口
    创建一个 TCC 接口并实现 Try、Confirm 和 Cancel 三个阶段的逻辑:
public interface OrderTccService {

    @GlobalTransactional
    boolean createOrder(OrderDTO orderDTO);

    @TwoPhaseBusinessAction(name = "orderTccService", commitMethod = "confirmOrder", rollbackMethod = "cancelOrder")
    boolean tryCreateOrder(OrderDTO orderDTO);

    boolean confirmOrder(OrderDTO orderDTO);

    boolean cancelOrder(OrderDTO orderDTO);
}
  1. 实现 TCC 逻辑
    在实现类中编写 TCC 逻辑:
@Service
public class OrderTccServiceImpl implements OrderTccService {

    @Override
    public boolean tryCreateOrder(OrderDTO orderDTO) {
        // 预留库存逻辑
        // ...
        return true;
    }

    @Override
    public boolean confirmOrder(OrderDTO orderDTO) {
        // 确认创建订单逻辑
        // ...
        return true;
    }

    @Override
    public boolean cancelOrder(OrderDTO orderDTO) {
        // 取消创建订单逻辑
        // ...
        return true;
    }
}
  1. 测试 TCC 模式
    编写测试用例来验证 TCC 模式的事务管理:
@RunWith(SpringRunner.class)
@SpringBootTest
public class OrderTccServiceTest {

    @Autowired
    private OrderTccService orderTccService;

    @Test
    public void testCreateOrder() {
        // 创建一个订单
        OrderDTO orderDTO = new OrderDTO();
        // 设置订单信息
        // ...

        orderTccService.createOrder(orderDTO);
    }
}

运行测试用例,观察订单的创建是否成功,并查看日志确认 TCC 模式的 Try、Confirm 和 Cancel 阶段是否正确执行。

集成Seata踩的坑

这里是我在集成过程中遇到的一些坑,可能和有不同的地方只做为参考。

Table ‘ddz.undo_log’ doesn’t exist

异常信息:process connectionProxy commit error: Table ‘ddz.undo_log’ doesn’t exist。
解决方法:在数据源中切少Seata需要的日志表;在每个数据源中新增undo_log表。

CREATE TABLE `undo_log` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `branch_id` bigint(20) NOT NULL,
  `xid` varchar(100) NOT NULL,
  `context` varchar(128) NOT NULL,
  `rollback_info` longblob NOT NULL,
  `log_status` int(11) NOT NULL,
  `log_created` datetime NOT NULL,
  `log_modified` datetime NOT NULL,
  `ext` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

no available service ‘null’ found, please make sure registry config correct

异常信息:出现这个的原因是我们没有把Seata的config.txt加载到nacos上。
解决方法:执行命令把配置加载到Nacos配置中心上。参考上面:把配置文件config.txt加载到nacos上

分布式事务未生效

原因:我们使用的dynamic多数据源,默认是没有开启Seata分布式事务的。
解决方法:在yml配置文件中的dynamic下添加seata: true配置以开启分布式事务。

dynamic-datasource can not find primary datasource

原因:出现这个是数据源配置信息错误,我这里出现这个异常的原因是我自己太不细心导致数据库连接(url)连接编写错了。
解决方法:仔细检查一下datasource 下面数据源的配置。

Communications link failure

原因:这里大部分原因是MySQL需要指明是否进行SSL连接,默认是开启SSL连接的。
解决方法:在数据库连接配置URL后追加&useSSL=false即可。

总结

随着分布式系统的不断发展,分布式事务领域也会不断进化。在未来,我们可以进一步探索更多的分布式事务模式和解决方案,以满足不同业务场景的需求。同时,Seata 作为一个活跃的开源项目,将会不断推出新的功能和改进,我们可以关注 Seata 社区的更新和贡献自己的力量。

此外,除了 Seata,还有其他一些分布式事务解决方案,例如 TCC-TransactionSAGAHSTC 等,这些方案也值得我们深入学习和探索。根据业务场景的不同,我们可以选择最合适的方案来解决分布式事务问题。

参考资料

Nacos 官方文档
Seata 官方文档
Spring Boot 官方文档

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

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

相关文章

IDEA 指定spring.profiles.active本地启动

spring.profiles.activedev spring.profiles.activepro

【Linux命令详解 | less命令】Linux系统中用于分页显示文件内容的命令

文章标题 简介一&#xff0c;参数列表二&#xff0c;使用介绍1. 分页显示文件内容2. 搜索关键词3. 显示行号4. 显示特定内容5. 只显示匹配行6. 忽略大小写搜索7. 输出到文件8. 动态查看文件增长9. 开启对二进制文件的支持10. 显示控制字符11. 忽略键盘输入12. 显示百分比进度条…

Python3 高级教程 | Python3 CGI编程(二)

目录 一、什么是CGI 二、网页浏览 三、CGI架构图 四、Web服务器支持及配置 五、第一个CGI程序 六、HTTP头部 七、CGI环境变量 八、GET和POST方法 &#xff08;一&#xff09;使用GET方法传输数据 &#xff08;二&#xff09;简单的url实例&#xff1a;GET方法 &#x…

Python之多重继承

一、多重继承 Python支持多重继承&#xff0c;一个子类可以有多个“直接父类”。这样&#xff0c;就具备了“多个父类”的特点。但是由于&#xff0c;这样会被“类的整体层次”搞的异常复杂&#xff0c;尽量避免使用。 class A:def aa(self):print("aa") ​ class B…

如何用正确的姿势监听Android屏幕旋转

作者&#xff1a;37手游移动客户端团队 背景 关于个人&#xff0c;前段时间由于业务太忙&#xff0c;所以一直没有来得及思考并且沉淀点东西&#xff1b;同时组内一个个都在业务上能有自己的思考和总结&#xff0c;在这样的氛围下&#xff0c;不由自主的驱使周末开始写点东西&…

日志框架及其使用方法

log4j和logBack,同一个人写的&#xff0c;logBack为log4j的升级版&#xff0c;SpringBoot中默认集成logBack 作用&#xff1a;记录软件发布后的一些bug,以及数据是怎样被操作的 传统开发弊端&#xff1a; 1.日志直接输出在控制台&#xff0c;关闭控制台后&#xff0c;日志消…

sd-roop换脸插件安装

安装步骤 首先看官方教程 sd-webui-roop插件&#xff0c; 如下&#xff1a; 执行 pip install insightface0.7.3在web-ui 界面&#xff0c;插件菜单&#xff0c;从网址安装 https://github.com/s0md3v/sd-webui-roopweb-ui 界面重启如果遇到 NoneType object has no attribu…

【数学建模】--聚类模型

聚类模型的定义&#xff1a; “物以类聚&#xff0c;人以群分”&#xff0c;所谓的聚类&#xff0c;就是将样本划分为由类似的对象组成的多个类的过程。聚类后&#xff0c;我们可以更加准确的在每个类中单独使用统计模型进行估计&#xff0c;分析或预测&#xff1b;也可以探究不…

fastadmin自定义键值组件Fieldlist

需求场景&#xff1a; 后台设置前端的固定话费充值金额。编辑时要求能够增删改&#xff0c;给到前端的数据&#xff0c;是要根据金额正序排列&#xff0c;用fastadmin的键值组件(Fieldlist)&#xff0c;使用Art-Template模板语法自定义模板。 最终效果如下图所示&#xff1a; …

Gson 添加数据默认值问题记录

问题&#xff1a;在用Gson add(key&#xff08;string类型&#xff09;&#xff0c;value&#xff08;必须是JsonElement子类&#xff09;&#xff09;时发现&#xff0c;value 传了 "" 空字符串&#xff08;非null&#xff09;&#xff0c;默认解析后返回null&#…

android studio安卓真机调试

把usb 手机开启到usb调试模式,然后用usb线连接手机 安装adb 如果下载速度很慢,请使用vpn 终端需要先安装brew /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"使用brew安装adb brew install android-platfor…

什么是全局代理,手机怎么设置全局代理

目录 什么是全局代理 全局代理的优缺点 优点 缺点 手机怎么设置全局代理 注意事项 总结 在计算机网络和信息安全中&#xff0c;全局代理是一种常用的技术手段&#xff0c;用于将网络流量通过代理服务器进行转发和处理。本文将介绍什么是全局代理&#xff0c;探讨全局代理…

Jmeter —— jmeter设置HTTP信息头管理器模拟请求头

HTTP信息头管理器 HTTP信息头管理器是在有需要模拟请求头部的时候进行设置的&#xff0c;添加方式 是 右击线程组 -- 配置元件 -- HTTP信息头管理器 可以通过抓包工具或者F12获取http请求的header头部信息&#xff1b;如下图&#xff1a; 复制并点击jmeter中的从剪贴板添加&am…

ubuntu 20.0.4 搭建nvidia 显卡环境

一、安装docker 1、安装dokcer sudo apt install docker.io2、docker 添加到用户组 创建docker用户组 sudo groupadd docker添加当前用户加入docker用户组 sudo usermod -aG docker ${USER}重启docker服务 sudo systemctl restart docker切换或者退出当前账户再从新登入 …

高德地图 SDK 接口测试接入(AndroidTest 上手)

学习资料 官方文档 在 Android 平台上测试应用 | Android 开发者 | Android Developers 测试了解 【玩转Test】开篇-Android test 介绍 Android单元测试全解_android 单元测试_一代小强的博客-CSDN博客 Android单元测试-对Activity的测试_activitytestrule_许佳佳233的博客…

设计模式-简单工厂模式(静态工厂模式)java实现

介绍 简单工厂模式根据所提供的参数数据返回几个可能类中的一个类的实例。通常返回的类都有一个公共的父类和公共的方法。 意图 提供一个类&#xff0c;负责根据一定的条件创建某一具体类的实例。同时使用工厂模式也是为了隐藏创建对象的过程 角色及其职责 (1)工厂(Creator…

GIT-HUB上传大文件.docx

下载git Github上传大文件&#xff08;&#xff1e;25MB&#xff09;教程_UestcXiye的博客-CSDN博客 上传流程 https://blog.csdn.net/weixin_35770067/article/details/116564429?spm1001.2101.3001.6661.1&utm_mediumdistribute.pc_relevant_t0.none-task-blog-2%7Ed…

链表——LinkedList类的概述和实现

LinkedList类 1.1LinkedList类概述 LinkedList类底层是基于双向链表结构实现的&#xff0c;不同于ArrayList类和Vector类是基于数组实现的&#xff1b;LinkedList类是非线程安全的&#xff1b;LinkedList类元素允许为null&#xff0c;允许重复元素&#xff1b;LinkedList类插…

融云:从「对话框」跳进魔法世界,AIGC 带给社交的新范式

8 月 17 日&#xff08;周四&#xff09;&#xff0c;融云将带来直播课-《北极星如何协助开发者排查问题与预警风险&#xff1f;》欢迎点击上方报名~ AIGC 与社交结合的应用主要分两种&#xff0c;一是发乎于 AIGC&#xff0c;以大模型为基础提供虚拟伴侣等服务的 App&#xff…

Python web实战之Django 的 RESTful API 设计详解

关键词: Python, Web 开发, Django, RESTful API 1 API的一些事儿 1.1 什么是API&#xff1f; API是应用程序编程接口&#xff08;Application Programming Interface&#xff09;的缩写。它是一种定义了不同软件组件之间交互方式的规范。API允许不同的应用程序之间进行通信和…