0


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

文章目录

概念

基本概念

微服务就是将一个大型单体应用拆分成多个独立的、负责特定业务的小服务。一个单体应用改造成微服务应用会让应用的性能得到巨大提升,但也带来了微服务架构繁琐的治理工作。而微服务组件是为了更好的治理微服务架构项目,让程序员将更多的精力放在业务开发上。目前主流的微服务项目是使用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>
  • 创建启动类
@SpringBootApplicationpublicclassOrderApplication{publicstaticvoidmain(String[] args){SpringApplication.run(OrderApplication.class, args);}}
  • 配置nacos注册中心地址
server:port:20100spring:application:name: order
  cloud:nacos:discovery:server-addr: 127.0.0.1:8848
  • 启动order模块
  • 访问nacos

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

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

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

  • 用之前的方式创建一个storage模块并整合注册中心组件
  • 编写storage服务扣减库存接口
@RestController@RequestMapping("/storage")publicclassStorageController{@GetMapping("/reduceStorage/{productId}")publicStringreduceStorage(@PathVariableInteger 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")publicinterfaceStorageClient{@GetMapping("/storage/reduceStorage/{productId}")StringreduceStorage(@PathVariable("productId")Integer productId);}
  • order服务编写Controller接口
@RestController@RequestMapping("/order")publicclassOrderController{@AutowiredprivateOrderService orderService;@GetMapping("/createOrder")publicStringcreateOrder(){return orderService.createOrder();}}
  • order服务编写Service接口
publicinterfaceOrderService{StringcreateOrder();}
@ServicepublicclassOrderServiceImplimplementsOrderService{@AutowiredprivateStorageClient storageClient;@OverridepublicStringcreateOrder(){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: gateway
  cloud: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
  • 创建订单表
CREATETABLE`t_order`(`id`int(11)NOTNULLAUTO_INCREMENTCOMMENT'主键',`product_id`int(11)NOTNULLCOMMENT'商品id',`user_id`int(11)NOTNULLCOMMENT'用户id',`order_number`varchar(100)NOTNULLCOMMENT'订单编号',`order_amount`decimal(10,2)NOTNULLCOMMENT'订单金额',`flag`tinyint(4)NOTNULLDEFAULT'1'COMMENT'删除标志:0-删除,1-不删除',`create_time`timestampNOTNULLDEFAULTCURRENT_TIMESTAMPCOMMENT'创建时间',`update_time`timestampNOTNULLDEFAULTCURRENT_TIMESTAMPONUPDATECURRENT_TIMESTAMPCOMMENT'更新时间',PRIMARYKEY(`id`))ENGINE=InnoDBAUTO_INCREMENT=5DEFAULTCHARSET=utf8mb4 COMMENT='订单表';
  • 创建库存数据库spring_cloud_storage
  • 创建库存表
CREATETABLE`t_storage`(`id`int(11)NOTNULLAUTO_INCREMENTCOMMENT'主键',`product_id`int(11)NOTNULLCOMMENT'商品id',`quantity`int(11)NOTNULLCOMMENT'商品数量',`flag`tinyint(4)NOTNULLDEFAULT'1'COMMENT'删除标志:0-删除,1-不删除',`create_time`timestampNOTNULLDEFAULTCURRENT_TIMESTAMPCOMMENT'创建时间',`update_time`timestampNOTNULLDEFAULTCURRENT_TIMESTAMPONUPDATECURRENT_TIMESTAMPCOMMENT'更新时间',PRIMARYKEY(`id`))ENGINE=InnoDBAUTO_INCREMENT=2DEFAULTCHARSET=utf8mb4 COMMENT='库存表';
  • 新增产品id为1的库存数据
INSERTINTO`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>- 配置ymlspring:datasource:driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/spring_cloud_order?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC&useSSL=falseusername: root password: rootmybatis-plus:global-config:db-config:logic-delete-field: flag logic-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")publicclassOrderimplementsSerializable{privatestaticfinallong serialVersionUID =1L;@TableId(value ="id", type =IdType.AUTO)privateInteger id;privateInteger productId;privateInteger userId;privateString orderNumber;privateBigDecimal orderAmount;privateInteger flag;privateLocalDateTime createTime;privateLocalDateTime updateTime;}``````publicinterfaceOrderMapperextendsBaseMapper<Order>{}
  • storage服务整合Mybatis-Plus 同理,请自行整合
  • 优化创建订单接口
@GetMapping("/createOrder")publicStringcreateOrder(Order order){return orderService.createOrder(order);}
StringcreateOrder(Order order);
@OverridepublicStringcreateOrder(Order order){// 创建订单
        order.setOrderNumber(UUID.randomUUID().toString());
        orderMapper.insert(order);// 扣减库存String reduceRes = storageClient.reduceStorage(order.getProductId());return"创建订单成功 == "+ reduceRes;}
  • 优化扣减库存接口
@AutowiredprivateStorageMapper storageMapper;@GetMapping("/reduceStorage/{productId}")publicStringreduceStorage(@PathVariableInteger productId){Storage storage = storageMapper.selectOne(newLambdaUpdateWrapper<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: nacos
    nacos:application: seata-server
      server-addr: 127.0.0.1:8848group: SEATA_GROUP
      namespace:cluster: default
      username:password:
  • 启动seata server 双击 bin/seata-server.bat 可以看到seata server已注册到注册中心在这里插入图片描述
  • 在订单数据库和库存数据库新建表undo_log
CREATETABLEIFNOTEXISTS`undo_log`(`branch_id`BIGINTNOTNULLCOMMENT'branch transaction id',`xid`VARCHAR(128)NOTNULLCOMMENT'global transaction id',`context`VARCHAR(128)NOTNULLCOMMENT'undo_log context,such as serialization',`rollback_info`LONGBLOBNOTNULLCOMMENT'rollback info',`log_status`INT(11)NOTNULLCOMMENT'0:normal status,1:defense status',`log_created`DATETIME(6)NOTNULLCOMMENT'create datetime',`log_modified`DATETIME(6)NOTNULLCOMMENT'modify datetime',UNIQUEKEY`ux_undo_log`(`xid`,`branch_id`))ENGINE=InnoDBAUTO_INCREMENT=1DEFAULTCHARSET= utf8mb4 COMMENT='AT transaction mode undo table';ALTERTABLE`undo_log`ADDINDEX`ix_log_created`(`log_created`);
  • order服务和storage服务配置seata server
seata:registry:type: nacos
    nacos: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_group
  service: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")publicStringgetOrders(){return orderService.getOrderList();}
StringgetOrderList();
@SentinelResource(value ="getOrderList")// 指定资源名并标识资源是否被限流、降级@OverridepublicStringgetOrderList(){return"返回订单列表";}
  • 重启order服务
  • 访问getOrders接口
  • 访问sentinel控制台 - 访问地址:http://localhost:8080/#/login- 用户名:sentinel- 密码:sentinel

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

  • 对getOrders接口添加流控规则在这里插入图片描述> 这样我们就新增了一个流控规则> 在这里插入图片描述- 测试> 每秒请求数超过2就会出现限流报错> 在这里插入图片描述- 优化报错提示 service接口中编写熔断降级提示方法/** * 编写熔断降级提示 * @param be * @return */publicStringgetOrderListBlockHandler(BlockException be){ be.printStackTrace();return"触发熔断降级处理规则";}@SentinelResource注解指定getOrderListBlockHandler@SentinelResource(value ="getOrderList",blockHandler ="getOrderListBlockHandler")- 重启order服务> 限流报错提示友好了> 在这里插入图片描述- 优化异常提示 如果接口运行时抛出异常了,这时候不会触发流控规则,而是会提示500错误,如下图我们模拟接口异常在这里插入图片描述- service接口中编写异常提示方法publicStringgetOrderListFallback(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/spans
  tracing: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 教程
标签: spring cloud spring

本文转载自: https://blog.csdn.net/weixin_45972546/article/details/139386614
版权归原作者 小林是程序员 所有, 如有侵权,请联系我们删除。

“万字长文讲解如何快速搭建一个Spring Cloud项目”的评论:

还没有评论