1.Spring-Cloud初识

1.微服务

1.1单体架构

很多创业公司早期或者传统企业会把业务的所有功能实现都打包在⼀个项⽬, 这就是单体架构. 业务的所有功能实现都打包在⼀个war包或者Jar包中, 这种⽅式就称为单体架构

1.2集群和分布式架构

当⽹站的⽤⼾量越来越⼤, 需求也会越来越多, 流量也会越来越⼤,我们从两个⽅⾯进⾏优化:

  • 横向: 添加服务器, 把单台机器变成多台机器的集群.
  • 纵向: 把⼀个应⽤, 按照业务进⾏拆分, 拆分为多个项⽬. 此架构也称为垂直架构
    集群:将⼀个系统完整的部署到多个服务器上, 每个服务器都能提供系统的所有服务, 多个服务器通过负载均衡调度完成任务. 每个服务器称为集群的节点

分布式:将⼀个系统拆分为多个⼦系统,多个⼦系统部署在多个服务器上,多个服务器上的⼦系统

协同合作完成⼀个特定任务

1.3集群 vs 分布式

  • 从概念上. 集群是多个计算机做同样的事, 分布式是多个计算机做不同的事
  • 从功能上. 集群的每⼀个节点功能是相同的, 并且可以替代的. 分布式也是多个节点组成的系统, 但是每个节点完成的业务是不同的, ⼀个节点出现问题, 这个业务就不可访问了
  • 从关系上. 分布式和集群在实践中, 很多时候是互相配合使⽤的. ⽐如分布式的某⼀个节点, 可能由⼀个集群来代替. 分布式架构⼤多是建⽴在集群上的. 所以实际的分布式架构设计中并不会把分布式和集群单独区分, ⽽是统称: 分布式架构.

1.4微服务架构

微服务:在分布式架构下, 当部署的服务越来越多, 重复的代码就会越来越多, 服务的调⽤关系也会越来越复杂. 我们可以把⼀些通⽤的, 会被多个上层服务调⽤的共享业务, 提取成独⽴的基础服务, 组成⼀个个微小的服务. 简单来说, 微服务就是很⼩的服务. ⼩到⼀个服务只对应⼀个单⼀的功能, 只做⼀件事. 这个服务可以单独部署运⾏,

2.解决方案-Spring Cloud

2.1基本定义

Spring Cloud 提供了⼀些可以让开发⼈员快速构建分布式服务的⼯具, ⽐如配置管理, 服务发现, 熔断,

智能路由等. 他们可以在任何分布式环境中很好的⼯作.简单来说, Spring Cloud 就是分布式微服务架构的⼀站式解决⽅案, 是微服务架构落地的多种技术的集合.

2.2实现方案

(1)Spring Cloud Netflix

Spring Cloud Netflix是 Netflix OSS(Netflix Open Source Software)在Spring Cloud规范下的实现.

包含的组件及其主要功能⼤致如下:

  • Eureka: 服务注册和发现
  • Zuul: 服务⽹关
  • Ribbon: 负载均衡
  • Feign: 服务调⽤组件
  • Hystrix: 断路器, 提供服务熔断和限流
  • Hystrix Dashboard: 监控⾯板

(2)Spring Cloud Alibaba

Spring Cloud Alibaba 是阿⾥巴巴集团下的开源组件和云产品在Spring Cloud规范下的实现. 如果说Spring Cloud Netflix 是 Spring Cloud 的第⼀代实现, 那么Spring Cloud Alibaba 也可以看做是 Spring Cloud 的第⼆代实现, 主要由 Nacos、Sentinel、Seata 等组件组成

3.环境工程搭建

3.1开发环境安装

JDK:⽬前⻓期维护的版本有: JDK8, JDK11, JDK17, JDK21,在 JDK版本的选择上,尽量选择⻓期维护的版本. Spring Cloud 是基于 SpringBoot 进⾏开发的, SpringBoot 3.X以下的版本, Spring官⽅已不再进⾏维护, SpringBoot 3.X的版本, 使⽤的JDK版本基线为JDK17. 鉴于JDK21 是2023.09⽉发 布的, 很多功能还没有在⽣产环境验证, 所以选择使⽤JDK17来学习

3.2案例引入

实现⼀个电商平台:⼀个电商平台包含的内容⾮常多, 仅从⾸⻚上就可以看到巨多的功能,我们该如何实现呢? 如果把这些功能全部写在⼀个服务⾥, 这个服务将是巨⼤的. 微服务架构是最好的选择. 微服务应⽤开发的第⼀步, 就是服务拆分. 拆分后才能进⾏"各⾃开发"

3.3服务拆分

服务越⼩, 微服务的独⽴性就会越来越⾼, 但同时, 微服务的数量也会越多, 管理这些微服务的难度也会

提⾼. 所以服务拆分也要考虑场景,遵守一定的原则

(1)单⼀职责原则

单⼀职责原则原本是⾯向对象设计中的⼀个基本原则, 它指的是⼀个类应该专注于单⼀功能. 不要存在多于⼀个导致类变更的原因

(2)服务⾃治

服务⾃治是指每个微服务都应该具备⾼度⾃治的能⼒, 即每个服务要能做到独⽴开发, 独⽴测试, 独⽴构建, 独⽴部署, 独⽴运⾏

(3)单向依赖

微服务之间需要做到单向依赖, 严禁循环依赖, 双向依赖

  • 循环依赖: A -> B -> C ->A
  • 双向依赖: A -> B, B -> A

3.4工程搭建

3.4.1创建父工程

(1)创建⼀个空的Maven项⽬, 删除所有代码, 只保留pom.xml

(2)完善pom文件

使⽤properties来进⾏版本号的统⼀管理, 使⽤dependencyManagement来管理依赖, 声明⽗⼯程的打包⽅式为pom

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>spring-cloud-demo</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>
    
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.1.6</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <java.version>17</java.version>
        <mybatis.version>3.0.3</mybatis.version>
        <mysql.version>8.0.33</mysql.version>
        <spring-cloud.version>2022.0.3</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>
    <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>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>${mybatis.version}</version>
            </dependency>

            <dependency>
                <groupId>com.mysql</groupId>
                <artifactId>mysql-connector-j</artifactId>
                <version>${mysql.version}</version>
            </dependency>

            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter-test</artifactId>
                <version>${mybatis.version}</version>
                <scope>test</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>

DependencyManagement 和 Dependencies

  • dependencies :将所依赖的jar直接加到项⽬中. ⼦项⽬也会继承该依赖.
  • dependencyManagement :只是声明依赖, 并不实现Jar包引⼊. 如果⼦项⽬需要⽤到相关依赖, 需要显式声明. 如果⼦项⽬没有指定具体版本, 会从⽗项⽬中读取version. 如果⼦项⽬中指定了版本号,就会使⽤⼦项⽬中指定的jar版本. 此外⽗⼯程的打包⽅式应该是pom,不是jar, 这⾥需要⼿动使⽤ packaging 来声明
3.4.2创建子项目

(1)订单服务

声明项⽬依赖和项⽬构建插件

xml 复制代码
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
        </dependency>

        <!-- mybatis -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

(2)商品服务

声明和订单服务相同

(3)完善订单服务

完善启动类

java 复制代码
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class OrderServiceApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderServiceApplication.class,args);
    }
}

配置文件

java 复制代码
server:
  port: 8080
spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/cloud_order?characterEncoding=utf8&useSSL=false
    username: root
    password: xxxxx
    driver-class-name: com.mysql.cj.jdbc.Driver
#设置MyBatis的xml路径
mybatis:
  configuration:
    # 配置打印 MyBatis⽇志
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    # 配置驼峰⾃动转换
    map-underscore-to-camel-case: true

(4)业务代码

实体类

java 复制代码
@Data
public class OrderInfo {
    private Integer id;
    private Integer userId;
    private Integer productId;
    private Integer num;
    private Integer price;
    private Integer deleteFlag;
    private Date createTime;
    private Date updateTime;
    private ProductInfo productInfo;
}

Mapper层

java 复制代码
@Mapper
public interface OrderMapper {
    @Select("select * from order_detail where id=#{orderId}")
    OrderInfo selectOrderById(Integer orderId);
}

Service层

java 复制代码
@Service
public class OrderService {
    @Autowired
    private OrderMapper orderMapper;
    public OrderInfo selectOrderById(Integer orderId){
        OrderInfo orderInfo = orderMapper.selectOrderById(orderId);
        return orderInfo;
    }
}

Controller层

java 复制代码
@RequestMapping("/order")
@RestController
public class OrderController {
    @Autowired
    private OrderService orderService;

    @RequestMapping("/{orderId}")
    //从URL的路径中提取一个名为 "orderId" 的部分,并将其值绑定到方法参数 orderId 上
    public OrderInfo getOrderById(@PathVariable("orderId") Integer orderId){
        return orderService.selectOrderById(orderId);
    }
}

商品服务代码修改参考上述

3.4.3需求分析

(1)需求

根据订单查询订单信息时, 根据订单⾥产品ID, 获取产品的详细信息.

(2)实现方案

  • 实现思路: order-service服务向product-service服务发送⼀个http请求, 把得到的返回结果, 和订单结果融合在⼀起, 返回给调⽤⽅.
  • 实现⽅式: 采⽤Spring 提供的RestTemplate

(3)定义RestTemplate

java 复制代码
@Configuration
public class BeanConfig {
    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}

(4)修改Order-Service中的Service

java 复制代码
@Service
public class OrderService {

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private RestTemplate restTemplate;
    public OrderInfo selectOrderById(Integer orderId){
        OrderInfo orderInfo = orderMapper.selectOrderById(orderId);
        String url="http://127.0.0.1:9090/product/"+orderInfo.getProductId();
        ProductInfo productInfo = restTemplate.getForObject(url, ProductInfo.class);
        orderInfo.setProductInfo(productInfo);
        return orderInfo;
    }
}
3.4.4RestTemplate

RestTemplate 是从 Spring3.0 开始⽀持的⼀个 HTTP 请求⼯具, 它是⼀个同步的 REST API 客⼾端, 提供了常⻅的REST请求⽅案的模版;RestTemplate 是Spring提供, 封装HTTP调⽤, 并强制使⽤RESTful⻛格. 它会处理HTTP连接和关闭, 只需要使⽤者提供资源的地址和参数即可.

相关推荐
小坏讲微服务2 小时前
Spring Boot 4.0 + MyBatis-Plus 实战响应式编程的能力实战
java·spring boot·后端·mybatis
by__csdn2 小时前
javascript 性能优化实战:垃圾回收优化
java·开发语言·javascript·jvm·vue.js·性能优化·typescript
BAStriver2 小时前
关于Flowable的使用小结
java·spring boot·spring·flowable
扶苏-su2 小时前
Java---泛型
java·开发语言·泛型
Dolphin_Home2 小时前
Java Stream 实战:订单商品ID过滤技巧(由浅入深)
java·开发语言·spring boot
毕设源码-钟学长2 小时前
【开题答辩全过程】以 高校健康申报系统为例,包含答辩的问题和答案
java·tomcat·echarts
cike_y2 小时前
JavaWeb之HttpServletResponse
java·开发语言·安全·java安全
小黄编程快乐屋2 小时前
线程、并发与互斥:解锁多任务编程的核心逻辑
java·开发语言·jvm
宠友信息2 小时前
打造可持续增长的垂直社区:仿小红书平台功能体系与架构深度解析
java·微服务·微信小程序·springboot·uniapp