万字长文讲解如何快速搭建一个Spring Cloud项目

文章目录

  • 概念
    • 基本概念
    • 微服务七大组件
  • 初始化Maven父工程
  • 整合注册中心组件
  • 整合远程调用与负载均衡组件组件
  • 整合网关组件
  • 整合配置中心组件
    • 以gateway模块为例
  • 整合分布式事务组件
    • 操作数据库模拟创建订单和扣减库存
    • 整合Seata
  • 整合熔断降级组件
  • 整合链路追踪组件
  • 源码地址
  • 参考来源

概念

基本概念

微服务就是将一个大型单体应用拆分成多个独立的、负责特定业务的小服务。一个单体应用改造成微服务应用会让应用的性能得到巨大提升,但也带来了微服务架构繁琐的治理工作。而微服务组件是为了更好的治理微服务架构项目,让程序员将更多的精力放在业务开发上。目前主流的微服务项目是使用Spring Cloud组件 + Spring Cloud Alibaba组件共同搭建的。

微服务七大组件

  • 注册中心
    国内常用的注册中心组件是Spring Cloud Alibaba的nacos
  • 远程调用与负载均衡
    国内常用的远程调用与负载均衡组件是Spring Cloud的openfeigh + loadbalancer
  • 网关
    国内常用的网关组件是Spring Cloud的gateway
  • 配置中心
    国内常用的配置中心组件是Spring Cloud Alibaba的nacos
  • 分布式事务
    国内常用的分布式事务组件是Spring Cloud Alibaba的seata
  • 熔断降级
    国内常用的熔断降级组件是Spring Cloud Alibaba的sentinel
  • 链路追踪
    国内常用的链路追踪组件是Spring Cloud的micrometer tracing + zipkin

初始化Maven父工程

  • 创建一个简单的maven工程
  • 规整目录
    删除src目录,只保留pom.xml文件和.gitignore文件
  • 将maven工程打包方式配置为pom
  <packaging>pom</packaging>
  • 规定编码方式以及依赖版本号
  <properties><java.version>17</java.version><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><spring-boot.version>3.0.2</spring-boot.version><spring-cloud-alibaba.version>2022.0.0.0</spring-cloud-alibaba.version><spring-cloud.version>2022.0.0</spring-cloud.version></properties>
  <dependencyManagement><dependencies><!--  Spring Boot版本管理  --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>${spring-boot.version}</version><type>pom</type><scope>import</scope></dependency><!--  Spring Cloud版本管理  --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud.version}</version><type>pom</type><scope>import</scope></dependency><!--  Spring Cloud Alibaba版本管理  --><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>
  • 添加Spring Boot依赖
<dependencies><!--  Spring Boot 启动依赖  --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency>
</dependencies>

整合注册中心组件

  • 下载解压nacos
    下载地址:nacos下载
  • 启动nacos(Windows环境)
    startup.cmd -m standalone
  • 用maven创建一个订单子模块order
  • 规定编译版本和编码方式
    <properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties>
  • 父工程引入注册中心依赖
    <!--  注册中心组件  --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency>
  • order模块引入web启动依赖
    <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency></dependencies>
  • 创建启动类
@SpringBootApplication
public class OrderApplication {public static void main(String[] args) {SpringApplication.run(OrderApplication.class, args);}
}
  • 配置nacos注册中心地址
server:port: 20100
spring:application:name: ordercloud:nacos:discovery:server-addr: 127.0.0.1:8848
  • 启动order模块
  • 访问nacos

可以看到order服务已注册到nacos中了
在这里插入图片描述

整合远程调用与负载均衡组件组件

我们模拟订单服务创建订单后远程调用库存服务扣减库存的场景

  • 用之前的方式创建一个storage模块并整合注册中心组件
  • 编写storage服务扣减库存接口
@RestController
@RequestMapping("/storage")
public class StorageController {@GetMapping("/reduceStorage/{productId}")public String reduceStorage(@PathVariable Integer productId) {return "扣减库存成功;";}}
  • order服务引入远程调用与负载均衡组件依赖
     <!--  远程调用组件  --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency><!--  负载均衡组件  --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-loadbalancer</artifactId></dependency>
  • order服务启动类开启远程调用注解
@EnableFeignClients
  • order服务编写Feign接口
@FeignClient("storage")
public interface StorageClient {@GetMapping("/storage/reduceStorage/{productId}")String reduceStorage(@PathVariable("productId") Integer productId);
}
  • order服务编写Controller接口
@RestController
@RequestMapping("/order")
public class OrderController {@Autowiredprivate OrderService orderService;@GetMapping("/createOrder")public String createOrder() {return orderService.createOrder();}
}
  • order服务编写Service接口
public interface OrderService {String createOrder();
}
@Service
public class OrderServiceImpl implements OrderService {@Autowiredprivate StorageClient storageClient;@Overridepublic String createOrder() {return "创建订单成功;" + storageClient.reduceStorage(1);}
}
  • 重启order服务和storage服务并访问测试
    在这里插入图片描述

整合网关组件

  • 用之前的方式创建一个gateway模块并整合注册中心组件
  • 引入网关和负载均衡组件依赖
  <dependencies><!--   无需引入web启动依赖     --><!--    网关启动依赖    --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency><!--  负载均衡组件  --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-loadbalancer</artifactId></dependency></dependencies>
  • 配置网关路由
spring:cloud:gateway:routes:- id: order_route # 订单服务路由iduri: lb://order # 转发到订单服务并实现负载均衡predicates:- Path=/api-order/** # 匹配 /api-order 开头的请求filters:- RewritePath=/api-order/?(?<segment>.*), /$\{segment} # 路径重写,如 /api-order/order 重写为 /order- id: storage_route # 库存服务路由iduri: lb://storage # 转发到库存服务并实现负载均衡predicates:- Path=/api-storage/**filters:- RewritePath=/api-storage/?(?<segment>.*), /$\{segment}
  • 启动网关

网关已注册到注册中心了
在这里插入图片描述

  • 使用网关ip和接口前缀访问order服务和storage服务
    在这里插入图片描述
    在这里插入图片描述

整合配置中心组件

以gateway模块为例

  • 下载并启动nacos
    这一步前面已经做了,可以跳过
  • 引入配置中心相关依赖
    <!--  配置中心组件  --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId></dependency><!--  bootstrap启动依赖  --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-bootstrap</artifactId></dependency>
  • 创建并配置bootstrap.yml
    在Spring Boot中,bootstrap.yml会比application.yml优先加载,所以可以将application.yml的部分配置迁移到bootstrap.yml,帮助程序加载配置中心的配置
spring:application:name: gatewaycloud:nacos:discovery:server-addr: 127.0.0.1:8848config:server-addr: 127.0.0.1:8848prefix: ${spring.application.name}  #通过 ${prefix}-${spring.profiles.active}.${file-extension} 可以找到配置中心对应的配置文件file-extension: yml  # nacos配置文件扩展名,目前只支持 properties 和 yaml 类型namespace: public # 默认就是 publicgroup: DEFAULT_GROUP # 默认就是 DEFAULT_GROUP

Spring Boot默认会将prefix-spring.profiles.active.file-extension作为DataID找到配置中心对应的配置文件,如果profiles.active.file不配置,则会将prefix.file-extension作为DataID找到配置中心对应的配置文件
默认情况下,配置文件的命名空间为public,分组名为DEFAULT_GROUP,我们可以为每个微服务创建不同的命名空间来区分不同服务,创建不同分组来区分不同环境,这里就不做演示了

  • 在配置中心创建配置文件
    在这里插入图片描述

  • 将网关的配置迁移到配置中心
    在这里插入图片描述

  • 重启gateway服务并测试

整合分布式事务组件

操作数据库模拟创建订单和扣减库存

前面我们调用创建订单接口只是返回字符串信息,接下来我们创建订单数据库、订单表、库存数据库和库存表,实现真实的数据库操作

  • 创建订单数据库spring_cloud_order
  • 创建订单表
CREATE TABLE `t_order` (`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',`product_id` int(11) NOT NULL COMMENT '商品id',`user_id` int(11) NOT NULL COMMENT '用户id',`order_number` varchar(100) NOT NULL COMMENT '订单编号',`order_amount` decimal(10,2) NOT NULL COMMENT '订单金额',`flag` tinyint(4) NOT NULL DEFAULT '1' COMMENT '删除标志:0-删除,1-不删除',`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COMMENT='订单表';
  • 创建库存数据库spring_cloud_storage
  • 创建库存表
CREATE TABLE `t_storage` (`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',`product_id` int(11) NOT NULL COMMENT '商品id',`quantity` int(11) NOT NULL COMMENT '商品数量',`flag` tinyint(4) NOT NULL DEFAULT '1' COMMENT '删除标志:0-删除,1-不删除',`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COMMENT='库存表';
  • 新增产品id为1的库存数据
INSERT INTO `spring_cloud_storage`.`t_storage` (`id`, `product_id`, `quantity`, `flag`, `create_time`, `update_time`) VALUES (1, 1, 100, 1, '2024-06-01 09:22:56', '2024-06-08 16:32:13');
  • order服务整合Mybatis-Plus

    • 引入maven依赖
        <!--    MySQL驱动    --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><!--    mybatis-plus启动依赖。注意依赖版本要匹配    --><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.5</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency>
    
    • 配置yml
    spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/spring_cloud_order?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC&useSSL=falseusername: rootpassword: root
    mybatis-plus:global-config:db-config:logic-delete-field: flaglogic-not-delete-value: 1logic-delete-value: 0configuration:log-impl: org.apache.ibatis.logging.stdout.StdOutImpl  # mybatis-plus Sql日志打印mapper-locations: /mapper/**/*.xml # mapper对应xml扫描路径
    
    • 启动类配置Mapper接口扫描
    @MapperScan("com.xiaolin.order.mapper")
    
    • 编写代码
    @Data
    @TableName("t_order")
    public class Order implements Serializable {private static final long serialVersionUID = 1L;@TableId(value = "id", type = IdType.AUTO)private Integer id;private Integer productId;private Integer userId;private String orderNumber;private BigDecimal orderAmount;private Integer flag;private LocalDateTime createTime;private LocalDateTime updateTime;
    }
    public interface OrderMapper extends BaseMapper<Order> {
    }
  • storage服务整合Mybatis-Plus
    同理,请自行整合

  • 优化创建订单接口

    @GetMapping("/createOrder")public String createOrder(Order order) {return orderService.createOrder(order);}
   String createOrder(Order order);
   @Overridepublic String createOrder(Order order) {// 创建订单order.setOrderNumber(UUID.randomUUID().toString());orderMapper.insert(order);// 扣减库存String reduceRes = storageClient.reduceStorage(order.getProductId());return "创建订单成功 == " + reduceRes;}
  • 优化扣减库存接口
  @Autowiredprivate StorageMapper storageMapper;@GetMapping("/reduceStorage/{productId}")public String reduceStorage(@PathVariable Integer productId) {Storage storage = storageMapper.selectOne(new LambdaUpdateWrapper<Storage>().eq(Storage::getProductId, productId));storage.setQuantity(storage.getQuantity() - 1);storageMapper.updateById(storage);return "库存扣减成功";}
  • 重启order和storage服务

  • 测试正常情况
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

  • 测试异常情况

    • 库存接口新增一行异常代码,模拟扣减库存失败
      int a=10/0;
    
    • 重启库存服务并测试
      在这里插入图片描述
      在这里插入图片描述

    我们发现订单创建成功但库存却扣减失败了,这明显不符合数据一致性原理,所以接下来我们引入分布式事务组件Seata,解决分布式环境数据库事务问题

整合Seata

  • 下载并解压Seata
    下载地址 Seata
  • 在seata配置文件conf/application.yml配置注册中心地址
seata:registry:# support: nacos, eureka, redis, zk, consul, etcd3, sofatype: nacosnacos:application: seata-serverserver-addr: 127.0.0.1:8848group: SEATA_GROUPnamespace:cluster: defaultusername:password:
  • 启动seata server
    双击 bin/seata-server.bat
    可以看到seata server已注册到注册中心
    在这里插入图片描述

  • 在订单数据库和库存数据库新建表undo_log

CREATE TABLE IF NOT EXISTS `undo_log`
(`branch_id`     BIGINT       NOT NULL COMMENT 'branch transaction id',`xid`           VARCHAR(128) NOT NULL COMMENT 'global transaction id',`context`       VARCHAR(128) NOT NULL COMMENT 'undo_log context,such as serialization',`rollback_info` LONGBLOB     NOT NULL COMMENT 'rollback info',`log_status`    INT(11)      NOT NULL COMMENT '0:normal status,1:defense status',`log_created`   DATETIME(6)  NOT NULL COMMENT 'create datetime',`log_modified`  DATETIME(6)  NOT NULL COMMENT 'modify datetime',UNIQUE KEY `ux_undo_log` (`xid`, `branch_id`)) ENGINE = InnoDB AUTO_INCREMENT = 1 DEFAULT CHARSET = utf8mb4 COMMENT ='AT transaction mode undo table';
ALTER TABLE `undo_log` ADD INDEX `ix_log_created` (`log_created`);
  • order服务和storage服务配置seata server
seata:registry:type: nacosnacos:application: seata-server # seate 服务端服务名server-addr: 127.0.0.1:8848group : SEATA_GROUP # seata 服务端分组名,请确保seata服务端与客户端的namespace和group一致namespace: # seata 服务端命名空间username:password:context-path:tx-service-group: default_tx_groupservice:vgroup-mapping:default_tx_group: default
  • order服务service接口添加全局事务注解
    在这里插入图片描述

  • 重启order和storage服务测试

测试后我们可以发现,即使库存服务扣减库存失败了,订单服务也会回滚订单数据,这样就保证了数据一致性了

整合熔断降级组件

以order服务为例

  • 下载sentinel控制台
    下载地址:sentinel控制台
  • 启动sentinel控制台
java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.6.jar
  • 引入maven依赖
    <!--  熔断降级组件sentinel  --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId></dependency>
  • 配置sentinel
spring:cloud:sentinel:transport:port: 8719dashboard: localhost:8080 # sentinel 控制台地址
  • 编写获取订单列表接口
    @GetMapping("/getOrders")public String getOrders() {return orderService.getOrderList();}
    String getOrderList();
 	@SentinelResource(value = "getOrderList")  // 指定资源名并标识资源是否被限流、降级@Overridepublic String getOrderList() {return "返回订单列表";}
  • 重启order服务
  • 访问getOrders接口
  • 访问sentinel控制台
    • 访问地址:http://localhost:8080/#/login
    • 用户名:sentinel
    • 密码:sentinel

可以看到order服务
在这里插入图片描述

  • 对getOrders接口添加流控规则
    在这里插入图片描述

    这样我们就新增了一个流控规则
    在这里插入图片描述

    • 测试

    每秒请求数超过2就会出现限流报错
    在这里插入图片描述

    • 优化报错提示
      service接口中编写熔断降级提示方法
        /*** 编写熔断降级提示* @param be* @return*/public String getOrderListBlockHandler(BlockException be) {be.printStackTrace();return "触发熔断降级处理规则";}

    @SentinelResource注解指定getOrderListBlockHandler

    @SentinelResource(value = "getOrderList",blockHandler ="getOrderListBlockHandler")
    
    • 重启order服务

    限流报错提示友好了
    在这里插入图片描述

    • 优化异常提示
      如果接口运行时抛出异常了,这时候不会触发流控规则,而是会提示500错误,如下图我们模拟接口异常
      在这里插入图片描述

    • service接口中编写异常提示方法

        public String getOrderListFallback(Throwable t) {t.printStackTrace();return "触发异常处理规则";}
    
    • @SentinelResource注解指定getOrderListFallback
    @SentinelResource(value = "getOrderList",blockHandler = "getOrderListBlockHandler",fallback = "getOrderListFallback")
    
    • 重启order服务

    异常提示友好了
    在这里插入图片描述

  • 对getOrders接口添加熔断规则
    添加熔断规则跟添加限流规则类似,我这里就不展示啦

整合链路追踪组件

  • 下载zipkin
    下载地址:zipkin
  • 启动zipkin
java -jar zipkin.jar
  • order和storage服务引入maven依赖
<!--  健康监控配置  --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><!--  链路追踪依赖  --><dependency><groupId>io.micrometer</groupId><artifactId>micrometer-tracing</artifactId></dependency><!--   micrometer-tracing-bridge-brave适配zipkin的桥接包  --><dependency><groupId>io.micrometer</groupId><artifactId>micrometer-tracing-bridge-brave</artifactId></dependency><!--  OpenZipkin Zipkin with Brave  --><dependency><groupId>io.zipkin.reporter2</groupId><artifactId>zipkin-reporter-brave</artifactId></dependency><!--  micrometer-observation  --><dependency><groupId>io.micrometer</groupId><artifactId>micrometer-observation</artifactId></dependency><!--  feign-micrometer  --><dependency><groupId>io.github.openfeign</groupId><artifactId>feign-micrometer</artifactId></dependency>
  • order和storage服务配置micrometer-tracing和zipkin
management:zipkin:tracing:endpoint: http://localhost:9411/api/v2/spanstracing:sampling:probability: 1.0 #采样率默认为0.1(0.1就是10次只能有一次被记录下来),值越大收集越及时。
  • 重启order和storage服务
  • 访问创建订单接口
  • 访问zipkin
    • 访问地址:http://127.0.0.1:9411

点击找到一个痕迹页签,可以看到,创建订单经过了order服务和storage这两个服务,点击show还可以查看调用详情
在这里插入图片描述

点击依赖页面,可以看到order服务依赖于storage服务
在这里插入图片描述

首先,恭喜各位朋友坚持看完了教程。相信你们看完这个教程并动手实践一遍,以后就能轻松搭建一个Spring Cloud服务了。也希望朋友们可以多多关注、多多点赞收藏哦。谢谢大家啦

源码地址

spring cloud demo

参考来源

  • nacos官网
  • spring cloud openfeign
  • spring cloud gateway
  • seata官网
  • sentinel官网
  • micrometer官网
  • zipkin官网
  • 尚硅谷 Spring Cloud 教程

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

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

相关文章

springcloud gateway转发websocket请求的404问题定位

一、问题 前端小程序通过springcloud gateway接入并访问后端的诸多微服务&#xff0c;几十个微服务相关功能均正常&#xff0c;只有小程序到后端推送服务的websocket连接建立不起来&#xff0c;使用whireshark抓包&#xff0c;发现在小程序通过 GET ws://192.168.6.100:8888/w…

Robot Operating System (ROS)中,发布与订阅

在Robot Operating System (ROS)中&#xff0c;发布与订阅是一种基于主题的异步消息传递机制&#xff0c;用于节点间的通信。ROS的设计是围绕着这一概念&#xff0c;它允许不同节点之间解耦&#xff0c;每个节点专注于自己的任务&#xff0c;通过发布和订阅消息来与其他节点交互…

计算机体系结构重点学习

从外部I/O与上层应用交互的整体软硬件过程 上层应用发出I/O请求&#xff1a;上层应用程序&#xff0c;如一个文本编辑器、网络浏览器或者任何软件应用&#xff0c;需要读取或写入数据时&#xff0c;会通过调用操作系统提供的API&#xff08;如文件操作API、网络操作API等&…

SpringBoot之请求映射原理

前言 我们发出的请求&#xff0c;SpringMVC是如何精准定位到那个Controller以及具体方法&#xff1f;其实这都是 HandlerMapping 发挥的作用&#xff0c;这篇博文我们以 RequestMappingHandlerMapping 为例并结合源码一步步进行分析。 定义HandlerMapping 默认 HandlerMappi…

Docker部署常见应用之桌面版系统ubuntu-desktop

文章目录 ubuntu-desktop 简介ubuntu-desktop 部署参考文章 ubuntu-desktop 简介 colinchang/ubuntu-desktop 是一个Docker镜像&#xff0c;基于KasmWeb⁠的 Ubuntu 22.04 桌面版&#xff08;Web&#xff09; Docker Image。镜像替换了阿里云Ubuntu Jammy镜像源&#xff0c;安…

重生之 SpringBoot3 入门保姆级学习(21、场景整合 Redis 定制对象序列化存储)

重生之 SpringBoot3 入门保姆级学习&#xff08;21、场景整合 Redis 定制对象序列化存储&#xff09; 6.4 定制化 6.4 定制化 需求&#xff1a;保存一个 Person 对象到 redis 创建 Person 类 package com.zhong.redis.entity;import lombok.AllArgsConstructor; import lombok…

浅谈C++基本框架内涵及其学习路线

目录 一.C的内涵本质 1. 面向对象编程&#xff08;OOP&#xff09; 2. 低级控制 3. 模板编程 4. 标准库&#xff08;STL&#xff09; 5. 多范式支持 二.学习路线 1. 基础阶段 C基础语法 函数 数组和指针 2. 面向对象编程 类和对象 继承和多态 运算符重载 3. 高级…

【服务的主从切换实现原理】

文章目录 主从架构介绍zookeeper利用ZK实现主从架构 主从架构介绍 主从服务架构是一种常见的分布式系统设计模式&#xff0c;常用于提高系统的性能、可用性和扩展性。在这种架构中&#xff0c;系统中的节点被分为两类&#xff1a;主节点&#xff08;Master&#xff09;和从节点…

Java基础面试重点-1

0. 符号&#xff1a; *&#xff1a;记忆模糊&#xff0c;验证后特别标注的知识点。 &&#xff1a;容易忘记知识点。 *&#xff1a;重要的知识点。 1. 简述一下Java面向对象的基本特征&#xff08;四个&#xff09;&#xff0c;以及你自己的应用&#xff1f; 抽象&#…

R可视化:ggpubr包学习

欢迎大家关注全网生信学习者系列&#xff1a; WX公zhong号&#xff1a;生信学习者 Xiao hong书&#xff1a;生信学习者 知hu&#xff1a;生信学习者 CDSN&#xff1a;生信学习者2 介绍 ggpubr是我经常会用到的R包&#xff0c;它傻瓜式的画图方式对很多初次接触R绘图的人来…

提升你的编程体验:自定义 PyCharm 背景图片

首先&#xff0c;打开 PyCharm 的设置菜单&#xff0c;点击菜单栏中的 File > Settings 来访问设置&#xff0c;也可以通过快捷键 CtrlAItS 打开设置。 然后点击Appearance & Behavior > Appearance。 找到Background image...左键双击进入。 Image:传入自己需要设置…

常见的 EVM 版本以及它们的区别

EVM&#xff08;以太坊虚拟机&#xff09;版本的演进是为了引入新的特性和改进以太坊平台的安全性、效率和功能性。每个版本通常伴随着以太坊网络的硬分叉&#xff0c;这是以太坊协议的重大升级。以下是一些常见的EVM版本及其主要区别&#xff1a; Homestead (2016年3月)&…

中国首台!紧随美国,重磅发布100比特中性原子量子计算机

2024年6月11日上午&#xff0c;“武汉量子论坛—2024”隆重开幕&#xff0c;国家自然科学基金委员会主任窦贤康院士&#xff0c;武汉大学校长张平文院士&#xff0c;以及叶朝辉、徐红星、祝世宁等院士出席大会。在会议上&#xff0c;中科酷原重磅发布国内首台原子量子计算机——…

利用 HTML5 Canvas 实现在线签字功能

目录 前言 一、HTML5 Canvas 简介 二、签字功能的实现 效果演示 完整代码 前言 在现代互联网应用中&#xff0c;有时我们需要让用户在网页上进行签字操作&#xff0c;比如确认文件、填写电子表格或者签署合同。利用 HTML5 的 canvas 画布&#xff0c;我们可以轻松地实现这一…

图片转Base64

在Python中, 可以使用内置的base64模块以及图像处理库(如PIL, 也称为Pillow)来将图片转换为Base64编码的字符串. 以下是一个简单的示例, 说明如何实现这一过程:首先, 需要安装Pillow库(如果尚未安装), 可以使用pip来安装: pip install pillow然后, 可以使用以下Python代码将图片…

RabbitMQ实践——交换器(Exchange)和绑定(Banding)

大纲 direct型交换器默认交换器命名交换器 fanout型交换器topic型交换器headers型交换器 RabbitMQ在概念上由三部分组成&#xff1a; 交换器&#xff08;Exchange&#xff09;&#xff1a;负责接收消息发布者发布消息的结构&#xff0c;同时它会根据“绑定关系”&#xff08;Ba…

基于SpringBoot+VueBBS论坛系统设计和实现(源码+LW+调试文档+讲解等)

&#x1f497;博主介绍&#xff1a;✌全网粉丝1W,CSDN作者、博客专家、全栈领域优质创作者&#xff0c;博客之星、平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌&#x1f497; &#x1f31f;文末获取源码数据库&#x1f31f; 感兴趣的可以先收藏起来&#xff0c;还…

sku与spu的区别!!!

一个 SPU 可以有多个 SKU。

攻防演练之-成功的钓鱼邮件溯源

书接上文&#xff0c;《网络安全攻防演练风云》专栏之攻防演练之-网络安全产品大巡礼二&#xff0c;这里。 演练第一天并没有太大的波澜&#xff0c;白天的时间过得很快。夜色降临&#xff0c;攻防演练中心内的灯光依旧明亮。对于网络安全团队来说&#xff0c;夜晚和白天并没有…

教育培训知识付费在线课程小程序开发

教育培训知识付费在线课程小程序功能概述 核心功能 课程报名与缴费&#xff1a;支持线上报名、缴费&#xff0c;自定义课程时间、人数等。 砍价功能&#xff1a;用户通过分享邀请好友参与砍价&#xff0c;享受低价购买课程的优惠。 视频课程&#xff1a;支持倍速播放&#x…