文章目录
- 前言
- 一、认识微服务
- 1.1 服务架构的演变:从单体到微服务
- 单体架构
- 分布式架构
- 微服务架构
- 1.2 微服务技术的对比:Dubbo、Spring Cloud、Spring Cloud Alibaba
- 技术对比
- 公司需求的选择
- 1.3 Spring Cloud:微服务框架的精华
- 什么是 Spring Cloud
- Spring Cloud 的功能
- Spring Cloud 与 Spring Boot 的版本兼容关系
- 二、微服务拆分案例与远程调用
- 2.1 准备 Spring Cloud Demo 代码
- 2.2 案例:在微服务中根据订单ID查询完整的订单信息
- 2.3 RestTemplate 工具说明
前言
随着信息技术的迅速发展和业务需求的不断变化,传统的单体架构在应对复杂性和灵活性方面逐渐显露出局限性。为了更好地适应现代企业的需求,微服务架构应运而生。微服务架构是一种通过将应用程序拆分成小的、相互独立的服务来构建系统的方法。
使用微服务架构的主要动机包括:
-
灵活性和可扩展性: 微服务允许将整个系统划分为多个小型服务,每个服务专注于特定的业务功能。这种模块化的设计使得系统更加灵活,能够根据需求进行快速扩展或缩减。
-
独立部署和维护: 微服务可以独立部署,每个服务都有自己的数据库和运行环境。这意味着一个服务的修改或更新不会对其他服务产生影响,简化了部署和维护的复杂性。
-
技术多样性: 微服务允许使用不同的技术栈和编程语言来实现不同的服务。这种灵活性使得团队能够选择最适合特定任务的工具,而不是受限于单一技术栈。
-
故障隔离和容错性: 单个微服务的故障不会影响整个系统的运行。系统中的其他服务仍然可以正常工作,从而提高了系统的容错性和可用性。
-
团队自治: 每个微服务都可以由一个小团队独立开发和维护,提高了团队的自治性。这种分布式的团队结构有助于加速开发周期和响应业务变化。
总体而言,微服务架构旨在提供更敏捷、可维护和可伸缩的软件开发和部署方式,使企业能够更好地适应快速变化的市场和业务环境。同时,这也是我们要学习微服务架构的原因。
一、认识微服务
1.1 服务架构的演变:从单体到微服务
随着互联网技术的不断发展,软件架构也在不断演变,从最早的单体架构逐步演进为分布式架构,再到如今更为灵活和可伸缩的微服务架构。在这个演变的过程中,架构设计逐步从简单向复杂迈进,服务之间的耦合度逐步降低,从而更好地适应了不断变化的业务需求。
单体架构
最早期的软件开发采用单体架构,所有的功能都被集成在一个项目中,最终打包成一个整体进行部署。这种架构的优势在于简单,部署成本相对较低。然而,由于所有功能都耦合在一起,当系统变得庞大复杂时,维护和扩展变得异常困难,单体架构的弊端逐渐显露。
优点:
- 架构简单
- 部署成本低
缺点:
- 耦合度高
- 维护困难
- 扩展性差
分布式架构
为了解决单体架构的问题,逐步演变出了分布式架构。在分布式架构中,系统根据业务功能进行拆分,每个业务模块作为独立的项目开发和部署。这样做的优势在于降低了服务之间的耦合度,使得系统更容易维护和扩展。然而,分布式架构也带来了新的问题,例如服务拆分粒度、服务集群地址维护、服务之间的远程调用等。
优点:
- 降低服务耦合
- 有利于服务升级和拓展
问题:
- 服务拆分粒度
- 服务集群地址维护
- 服务之间远程调用
- 服务健康状态感知
微服务架构
微服务架构是分布式架构的一种更为灵活和先进的形式。在微服务架构中,系统被拆分成多个微小的服务,每个服务都对应着唯一的业务能力,实现了单一职责。这些服务通过明确定义的接口进行通信,各自独立部署和维护。微服务架构的特点包括面向服务、自治性、隔离性强等。
微服务架构的特点:
- 单一职责:每个服务负责唯一的业务能力
- 面向服务:服务通过接口对外暴露业务
- 自治性:团队、技术、数据、部署都独立
- 隔离性强:服务调用做好隔离、容错、降级
微服务架构的优势在于更好地适应业务变化,提高了系统的可维护性和可扩展性。然而,微服务架构也带来了一些新的挑战,例如服务治理、分布式事务、服务调用的复杂性等,需要在设计和实施中注意解决这些问题。
总体而言,服务架构的演变是为了更好地适应复杂多变的业务需求,选择合适的架构取决于具体的业务场景和需求。
1.2 微服务技术的对比:Dubbo、Spring Cloud、Spring Cloud Alibaba
微服务架构的实施离不开相应的技术框架的支持,而在国内,Dubbo、Spring Cloud以及Spring Cloud Alibaba是三个备受关注的微服务技术栈。让我们深入比较它们的一些关键方面:
技术对比
Dubbo | Spring Cloud | Spring Cloud Alibaba | |
---|---|---|---|
注册中心 | Zookeeper、Redis | Eureka、Consul | Nacos、Eureka |
服务远程调用 | Dubbo协议 | Feign(HTTP协议) | Dubbo、Feign |
配置中心 | 无 | Spring Cloud Config | Nacos、Spring Cloud Config |
服务网关 | 无 | Spring Cloud Gateway、Zuul | Spring Cloud Gateway、Nacos网关 |
服务监控和保护 | Dubbo-admin(功能较弱) | Hystrix | Sentinel |
1. Dubbo:
Dubbo 是一款由阿里巴巴提供的高性能、轻量级的开源 RPC(远程过程调用)框架。它主要用于解决分布式服务之间的通信问题,使得不同服务之间能够方便地进行远程调用。Dubbo 提供了服务注册与发现、负载均衡、服务调用等一系列分布式系统的核心功能。
主要特点:
-
服务注册与发现: Dubbo 提供了多种服务注册中心的支持,包括 Zookeeper、Redis 等,用于管理和发现服务实例。
-
负载均衡: Dubbo 内置了多种负载均衡算法,能够根据实际场景选择合适的负载均衡方式,提高系统的可用性和性能。
-
服务调用: Dubbo 支持多种调用方式,包括同步调用、异步调用、单播调用、广播调用等,满足不同业务场景的需求。
-
服务容错: Dubbo 提供了多种容错机制,包括超时重试、失败自动切换、快速失败等,增强了系统的稳定性。
-
面向接口代理: Dubbo 使用接口代理的方式进行服务调用,支持多种协议,包括 Dubbo 协议、HTTP 协议等。
2. Spring Cloud
Spring Cloud 是一套基于 Spring Boot 的分布式系统开发工具集,用于构建微服务架构。它提供了一系列的解决方案和组件,帮助开发者轻松构建、连接和管理微服务。Spring Cloud 提供了服务注册与发现、配置管理、负载均衡、断路器、网关等一系列工具,使得构建和管理分布式系统更加简便。
主要特点:
-
服务注册与发现: Spring Cloud 支持多种服务注册中心,包括 Eureka、Consul、Zookeeper 等,用于服务的动态发现和注册。
-
配置管理: Spring Cloud Config 提供了集中式的配置管理,支持配置的动态刷新,使得配置更加灵活。
-
服务调用: Spring Cloud 使用 Feign 进行声明式的服务调用,简化了服务之间的远程调用。
-
负载均衡: Spring Cloud 集成了 Ribbon 负载均衡器,能够实现在多个服务之间的负载均衡。
-
断路器: Spring Cloud 使用 Hystrix 提供了断路器的支持,防止分布式系统中的故障扩散。
3. Spring Cloud Alibaba:
Spring Cloud Alibaba 是基于 Spring Cloud 和阿里巴巴的技术体系之上的微服务框架。它在 Spring Cloud 的基础上集成了阿里巴巴的一些开源组件,提供了更多与阿里云生态系统集成的功能。
主要特点:
-
服务注册与发现: Spring Cloud Alibaba 支持 Nacos 作为服务注册中心,同时兼容 Eureka。
-
配置管理: 使用 Nacos 作为配置中心,实现集中式的配置管理。
-
服务调用: Spring Cloud Alibaba 既支持 Dubbo 协议,也支持使用 Feign 进行服务调用。
-
负载均衡: 集成了 Alibaba 的负载均衡解决方案,如 Ribbon 和 Nacos。
-
服务容错: 使用 Sentinel 实现流量控制、熔断和降级,提高系统的稳定性。
总体而言,Dubbo、Spring Cloud 和 Spring Cloud Alibaba 都是为了解决分布式系统中的通信、配置、服务发现等问题而设计的框架,它们在实现上有一些差异,可以根据实际需求选择合适的框架。
公司需求的选择
-
Spring Cloud + Feign: 适用于使用Spring Cloud技术栈,服务接口采用Restful风格,服务调用采用Feign方式的场景。
-
Spring Cloud Alibaba + Feign: 适用于使用Spring Cloud Alibaba技术栈,服务接口采用Restful风格,服务调用采用Feign方式的场景。
-
Spring Cloud Alibaba + Dubbo: 适用于使用Spring Cloud Alibaba技术栈,服务接口采用Dubbo协议标准,服务调用采用Dubbo方式的场景。
-
Dubbo原始模式: 适用于基于Dubbo老旧技术体系,服务接口采用Dubbo协议标准,服务调用采用Dubbo方式的场景。
在选择技术栈时,需要根据具体业务需求、团队经验以及技术栈的特点进行权衡和选择。不同的技术栈有不同的优势和适用场景,因此在实际应用中需要综合考虑各方面因素。
1.3 Spring Cloud:微服务框架的精华
什么是 Spring Cloud
Spring Cloud 是一套在分布式系统中快速构建微服务架构的开发工具集。它提供了一系列的工具和组件,使得开发者能够轻松地在分布式系统中构建各种微服务,并解决微服务架构中的一些常见问题,如服务发现、配置管理、负载均衡、熔断器等。
Spring Cloud 的功能
Spring Cloud 组合了多个微服务相关的组件,形成一个完整的微服务框架。以下是 Spring Cloud 提供的一些核心功能:
在上图中展示了 Spring Cloud 提供的一些核心功能,每个功能的作用如下:
-
服务注册发现: 通过服务注册中心(如Eureka、Consul、Nacos等),微服务实例能够注册和发现其他服务,从而实现服务之间的动态发现和通信。
-
统一配置管理: Spring Cloud Config 允许将应用程序的配置集中存储在配置服务器中,使得配置的修改和管理更为方便,同时支持配置的动态刷新。
-
服务远程调用: Spring Cloud 提供了 Feign 作为声明式的服务调用工具,简化了服务之间的远程调用,开发者只需定义接口并使用注解进行配置。
-
统一网关路由: Spring Cloud Gateway 和 Zuul 是两个常用的服务网关组件,它们负责请求的路由、过滤和转发,提供了统一的入口和出口。
-
服务链路监控: Spring Cloud Sleuth 与 Zipkin 结合使用,实现了对微服务系统的分布式追踪和监控,有助于发现和解决系统中的性能问题。
-
流控、降级、保护: 通过使用 Sentinel 或 Hystrix,可以实现对微服务的流量控制、降级和熔断保护,提高了系统的稳定性和容错能力。
这些功能共同构建了一个完整的微服务生态系统,使得开发者能够更轻松地构建、管理和监控复杂的分布式系统。 Spring Cloud 的这些功能组件使得微服务架构更加强大、灵活,并能够更好地适应不同的业务需求。
Spring Cloud 与 Spring Boot 的版本兼容关系
Spring Cloud 是构建在 Spring Boot 之上的微服务框架,因此它与 Spring Boot 的版本兼容性是一个关键问题。Spring Cloud 通常会与特定版本的 Spring Boot 一起发布,以确保二者之间的兼容性。
在选择 Spring Cloud 版本时,需要查看 Spring Cloud 官方文档,了解该版本与对应 Spring Boot 版本的兼容性。这有助于确保微服务系统的稳定运行,同时能够利用 Spring Boot 的最新功能。
例如,可以在:https://spring.io/projects/spring-cloud#learn 中点击具体的 SpringCloud 版本的参考文档,就能够在里面发现对应的 Spring Boot 版本。
例如:
点击查看 Spring Cloud 2021.0.8 的参考文档,就能够发现其对应的 Spring Boot 版本是 2.6.15:
二、微服务拆分案例与远程调用
2.1 准备 Spring Cloud Demo 代码
为了演示微服务的拆分与远程调用,我们准备了一个简单的 Spring Cloud Demo 代码,其中包含两个模块:order-service
(订单模块)和 user-service
(用户模块)。
项目结构如下:
在这个 Demo 中,订单模块负责查询订单信息,用户模块则负责查询用户信息。
查询订单信息的代码:
@Autowired
private OrderService orderService;
@GetMapping("{orderId}")
public Order queryOrderByUserId(@PathVariable("orderId") Long orderId) {
// 根据id查询订单并返回
return orderService.queryOrderById(orderId);
}
查询用户信息的代码:
/**
* 路径: /user/110
*
* @param id 用户id
* @return 用户
*/
@GetMapping("/{id}")
public User queryById(@PathVariable("id") Long id) {
return userService.queryById(id);
}
示例:查询订单信息
示例:查询用户信息
通过上述示例,我们发现一个问题:订单模块在查询订单信息时,用户信息为 null
。为了解决这个问题,我们需要订单模块调用用户模块的接口 /user/{userId}
来获取用户信息,并将用户信息填充到订单中。
这种情况下,我们就涉及到了微服务的拆分与远程调用:
- 微服务的拆分要根据业务模块,做到单一职责,避免重复开发相同业务。
- 微服务可以将业务暴露为接口,供其他微服务使用。
- 不同微服务应该有独立的数据库。
在接下来的步骤中,我们可以继续完善这个示例,演示如何使用 Spring Cloud 进行微服务的拆分与远程调用。
2.2 案例:在微服务中根据订单ID查询完整的订单信息
对这个案例要求是:根据订单 ID 查询订单的同时,把订单所属的用户信息一起返回,如下图所示:
远程调用方式的分析:
当我们请求订单信息的时候,在订单模块不光要请求订单信息,还需要根据该订单的用户 ID 去想用户模块请求对应的用户信息,最后将所有请求的结果进行合并,再返回给前端。
微服务远程调用的步骤如下:
- 注册 RestTemplate
在order-service
的 启动类OrderApplication
中注册RestTemplate
:
@SpringBootApplication
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
}
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
- 服务远程调用
RestTemplate
修改 order-service
中的 OrderService
的 queryOrderById
方法:
@Autowired
private OrderMapper orderMapper;
@Autowired
private RestTemplate restTemplate;
public Order queryOrderById(Long orderId) {
// 1. 查询订单
Order order = orderMapper.findById(orderId);
// 2. 查询用户
// 2.1 构建查询用户的 url
String url = "http://localhost:8081/user/" + order.getUserId();
// 2.2 使用 RestTemplate 远程调用查询用户
User user = restTemplate.getForObject(url, User.class);
// 3. 封装 user 信息
order.setUser(user);
// 4.返回
return order;
}
当所有的代码修改完后,重启order-service
服务,再次查询订单:
此时就实现了微服务的远程调用了。
2.3 RestTemplate 工具说明
1. 什么是 RestTemplate?
RestTemplate 是 Spring 提供的用于访问 REST 服务的客户端工具。它简化了与 RESTful 服务的通信,并提供了多种便捷的方法,包括 GET、POST、PUT、DELETE 等请求方式。
RestTemplate 的主要特点包括:
-
简化 HTTP 请求: RestTemplate 封装了 HTTP 请求,通过简单的方法调用,可以实现 HTTP 请求的发送和接收。
-
支持多种请求方式: RestTemplate 支持 GET、POST、PUT、DELETE 等多种 HTTP 请求方式,以满足不同的业务需求。
-
方便的参数传递: RestTemplate 提供了多种方式来传递请求参数,包括 URL 变量、请求体、请求头等。
-
简化错误处理: RestTemplate 对 HTTP 响应进行了封装,方便处理不同的响应状态码和错误信息。
2. RestTemplate 示例代码
以下是一个简单的使用 RestTemplate 发送 GET 请求的示例代码:
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
public class RestClient {
public static void main(String[] args) {
// 创建 RestTemplate 实例
RestTemplate restTemplate = new RestTemplate();
// 定义请求地址
String url = "https://jsonplaceholder.typicode.com/posts/1";
// 发送 GET 请求,并获取响应结果
ResponseEntity<String> responseEntity = restTemplate.getForEntity(url, String.class);
// 获取响应状态码
int statusCode = responseEntity.getStatusCodeValue();
// 获取响应体
String responseBody = responseEntity.getBody();
// 输出结果
System.out.println("Status Code: " + statusCode);
System.out.println("Response Body: " + responseBody);
}
}
在上述代码中,我们使用 RestTemplate 的 getForEntity
方法发送一个 GET 请求,并获取到响应的状态码和响应体。这只是一个简单的示例,RestTemplate 还提供了许多其他方法,以支持更丰富的 HTTP 请求和响应操作。