一、什么是SpringCloud
基本概念
Spring Cloud 是一个开源的分布式系统开发框架,它基于 Spring Boot 构建,并提供了一系列工具和组件,用于构建和管理分布式应用程序和微服务架构。
SpringCloud的特点
SpringCloud能够解决微服务架构带来的一系列挑战,提供一个工具包来开发分布式系统
功能包含:
- 分布式配置中心 Config、Nacos
- 服务注册和发现 Eureka、Nacos、Zookeeper、Consul
- 路由 Gateway、Zuul
- 服务之间的调用 Feign、Dubbo
- 负载均衡 Ribbon、LoadBalancer
- 熔断器 Hystrix、Sentinel
- 全局锁
- 集群状态管理
- 分布式消息 Bus
主要优点
- 易于构建分布式系统:Spring Cloud是基于Spring Boot的,使用Spring Boot开发微服务架构变得非常简单。
- 完整的微服务工具集:Spring Cloud为开发者提供了一个完整的微服务工具集,包括配置管理、服务发现、断路器、负载均衡、智能路由、微代理、控制总线、一次性令牌、全局锁、决策竞速、分布式会话等等。
- 快速构建分布式系统:通过使用Spring Cloud,开发者可以轻松地构建分布式系统,而无需关心复杂的分布式系统的底层实现。
- 实现云原生架构:Spring Cloud支持云原生架构,可以帮助开发者实现微服务、容器化、云原生等。
- 易于接入新技术:Spring Cloud是基于Spring技术栈的,开发者可以轻松地接入新的技术,以满足业务需求。
二、 微服务架构和单体应用架构
微服务架构
微服务架构是一种将应用程序拆分为一组小型、独立的服务的架构模式。每个服务都具有自己的代码库、数据库和资源,并通过网络进行通信。每个服务都负责特定的功能或业务领域。
单体架构
单体应用架构是一种传统的软件架构模式,应用程序作为一个整体被构建、打包和部署。在单体应用中,所有的功能模块和业务逻辑都在同一个代码库中,并共享相同的数据库和资源。
两者的区别
一、架构组织方式:
- 微服务架构:应用程序以一组小型、独立的服务组织。每个服务都有自己的代码库、数据库和资源,并通过轻量级通信机制进行交互。
- 单体应用架构:应用程序作为一个整体被组织,所有的模块和功能共享同一个代码库、数据库和资源。
二、可伸缩性:
- 微服务架构:每个服务可以独立地进行水平扩展,只需对需要处理更多负载的服务进行扩展。
- 单体应用架构:整个应用必须进行垂直扩展,即增加整个应用的资源来处理更多负载。
三、开发和部署:
- 微服务架构:每个微服务可以由不同的团队开发和部署,独立进行测试和发布。
- 单体应用架构:整个应用由一个团队开发和部署,需要进行整体的集成测试和部署。
四、系统复杂性:
- 微服务架构:由于涉及多个独立的服务,系统的复杂性较高,需要更多的管理和协调。
- 单体应用架构:应用较为简单,系统复杂性较低。
五、技术灵活性:
- 微服务架构:每个微服务可以选择适合自身需求的技术和工具。
- 单体应用架构:由于整个应用耦合在一起,技术选型受限。
六、维护和修改:
- 微服务架构:对某个服务的修改和维护不会影响其他服务,每个服务可以独立开发和更新。
- 单体应用架构:修改和维护可能会影响整个应用,需要更多的协调和依赖管理。
三、微服务入门案例
订单微服务能够查询订单信息,订单信息中包含商品数据,订单微服务要调用商品微服务完成查询
订单服务数据库为sys_order
-- 订单表
create table sys_order
(
id int primary key auto_increment,
product_id int not null,
count int not null,
user_id int not null,
time datetime
);
insert into sys_order(product_id,count,user_id,time)
values(1,1,1,'2022-11-21 13:11:12'),
(2,2,1,'2022-12-21 13:11:12'),
(3,1,1,'2022-10-21 13:11:12');
select * from sys_order;
商品服务的商品数据库sys_product
-- 商品表
create table sys_product
(
id int PRIMARY key auto_increment,
name varchar(50) not null,
price double not null,
type varchar(10) not null
);
insert into sys_product(name,price,type)
values('华为笔记本',5000,'电器'),
('百事可乐',5,'饮料'),
('Nike篮球鞋',800,'鞋子');
select * from sys_product;
-
编写商品服务,完成按商品id查询商品的功能
-
编写订单服务,完成按查询订单的功能
-
订单微服务调用商品微服务
@Configuration
public class RestTemplateConfig {
/**
* 创建RestTemplate交给容器
* @return
*/
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
订单包含商品信息
@Data
@TableName("sys_order")
public class Order {
@TableId(type = IdType.AUTO)
private Long id;
private Long userId;
private Long productId;
private Long count;
private LocalDateTime time;
@TableField(exist = false)
private Product product;
}
订单service查询订单时远程调用商品服务
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements IOrderService {
@Autowired
private RestTemplate restTemplate;
@Autowired
private OrderMapper orderMa pper;
@Override
public Order getOrderById(Long id) {
Order order = orderMapper.selectById(id);
//调用商品微服务获得商品信息
ResponseEntity<Product> entity = restTemplate.getForEntity("http://localhost:8002/product/" + order.getProductId(), Product.class);
order.setProduct(entity.getBody());
return order;
}
}
结果如下
四、Eureka注册中心
什么是Eureka注册中心
Eureka 是 Spring Cloud 提供的一种服务注册与发现的组件,它实现了服务治理中的注册中心功能。服务注册中心是分布式系统中用于协调和管理服务实例的组件,它允许服务实例将自身的信息注册到注册中心,并能够通过注册中心获取其他服务实例的信息。
服务注册和发现机制
在 Eureka 中,有两个角色:Eureka Server 和 Eureka Client。
Eureka Server:
- Eureka Server 是注册中心,负责接收服务实例的注册信息并存储起来。
- 它提供了 REST API,供服务实例进行注册、注销和心跳等操作。
- Eureka Server 之间可以相互注册,形成集群,提高可用性和扩展性。
Eureka Client:
- Eureka Client 是服务提供方或消费方,它将自己注册到 Eureka Server,以便被其他服务调用或发现。
- 在启动时,Eureka Client 会向 Eureka Server 发送心跳请求,以保持注册信息的更新。
- Eureka Client 还可以从 Eureka Server 中获取其他服务实例的信息,实现服务的调用与发现。
通过使用 Eureka 注册中心,可以实现的功能
- 服务注册与发现:服务实例将自己注册到 Eureka Server,其他服务可以通过 Eureka Server 获取服务实例的信息,实现服务的调用与发现。
- 高可用性与容错:Eureka Server 可以搭建成集群来保证高可用性,当某个 Eureka Server 节点不可用时,其他节点可以接管其职责。
- 负载均衡:Eureka Client 在查询服务实例信息时,可以使用 Eureka 的负载均衡机制,从多个实例中选择一个进行调用。
创建Eureka服务器项目
修改父项目pom
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.blb</groupId>
<artifactId>springcloud_demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springcloud_demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>8</java.version>
<spring.cloud-version>Hoxton.SR8</spring.cloud-version>
</properties>
<!--固定SpringCloud依赖版本-->
<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>
</dependencies>
</dependencyManagement>
创建Eureka服务器
修改pom文件
1)继承父项目
<parent>
<groupId>com.blb</groupId>
<artifactId>springcloud_demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
2)引入服务器依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
3)配置文件
server.port=8000
# 服务器域名
eureka.instance.hostname=127.0.0.1
# 设置不拉取服务清单
eureka.client.fetch-registry=false
# 设置不注册当前服务
eureka.client.register-with-eureka=false
# 定义注册服务的地址
eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:${server.port}/eureka
4) 启动类加 @EnableEurekaServer
配置Eureka客户端
1) 继承父项目
2) 引入客户端依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
3) 配置文件
# 服务名称
spring.application.name=xxxx
# 设置拉取服务清单
eureka.client.fetch-registry=true
# 设置注册当前服务
eureka.client.register-with-eureka=true
# 定义注册服务的地址
eureka.client.serviceUrl.defaultZone=http://127.0.0.1:8000/eureka
4) 启动类加 @EnableEurekaClient或 @EnableDiscoveryClient
5) 在RestTemplate配置类方法上加@LoadBalanced
6)调用服务时修改
//调用商品微服务获得商品信息 将IP和端口写死 服务提供者ip和端口发生变化,调用出错
//改用Eureka后,调用时使用服务注册名称调用
ResponseEntity<Product> entity = restTemplate.getForEntity("http://product-service/product/" + order.getProductId(),
Product.class);
Eureka自我保护机制
心跳机制:客户端注册到Eureka服务器后,每隔30s发送心跳包给服务器,如果90s没有发送心跳包,服务器就会把客户端从服务清单剔除
自我保护机制:网络可能出现波动,Eureka服务器发现15分钟内所有客户端正常心跳比例低于85%,Eureka就会把服务清单保护起来不剔除,网络恢复正常后,服务调用就能正常执行。
开发阶段可以关闭自我保护机制,上线阶段一般都要开启# 关闭自我保护机制
eureka.server.enable-self-preservation=false
Eureka高可用
可以配置多台Eureka服务器形成集群,相互注册相互备份,提高注册中心的可用性
application-dev.properties
server.port=8011
spring.application.name=eureka-8011
# 服务器域名
eureka.instance.hostname=127.0.0.1
# 设置从其它eureka拉取服务清单
eureka.client.fetch-registry=true
# 设置注册当前服务到其它eureka
eureka.client.register-with-eureka=true
# 定义注册服务的地址
eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:8012/eureka
# 关闭自我保护机制
eureka.server.enable-self-preservation=false
application-test.properties
server.port=8012
spring.application.name=eureka-8012
# 服务器域名
eureka.instance.hostname=127.0.0.1
# 设置拉取服务清单
eureka.client.fetch-registry=true
# 设置注册当前服务到其它eureka
eureka.client.register-with-eureka=true
# 定义注册服务的地址
eureka.client.serviceUrl.defaultZone=http://${eureka.instance.hostname}:8011/eureka
# 关闭自我保护机制
eureka.server.enable-self-preservation=false
服务提供者和消费者注册到集群上
xxxxxxxxxx eureka.client.serviceUrl.defaultZone=http://127.0.0.1:8012/eureka,http://127.0.0.1:8011/eureka