2. 服务拆分和远程调用
在构建微服务架构时,服务的拆分与协作是至关重要的。本节将深入探讨服务拆分的原则,以及如何通过远程调用实现微服务之间的协作。
2.1. 服务拆分原则
在进行微服务拆分时,遵循一些原则可以帮助我们更好地设计服务体系:
-
避免重复开发相同业务: 不同的微服务应该专注于不同的业务领域,避免在不同的微服务中重复开发相同的业务逻辑,从而提高代码的可维护性和复用性。
-
微服务数据独立: 微服务应该拥有自己的独立数据库,避免直接访问其他微服务的数据库。这有助于隔离数据,减少耦合,以及更好地维护和扩展每个微服务。
-
业务暴露为接口: 微服务应该将自己的业务封装成接口,供其他微服务调用。通过定义清晰的接口,可以实现松耦合,方便协作,以及更容易进行微服务的替换和升级。
2.2. 服务拆分示例
让我们通过一个实际的示例来理解服务拆分。考虑一个微服务架构中的示例项目cloud-demo
,其结构如下:
项目结构包括:
cloud-demo
:父工程,负责依赖管理order-service
:订单微服务,处理订单相关业务user-service
:用户微服务,处理用户相关业务
在这个示例中,我们有以下要求:
- 订单微服务和用户微服务必须使用各自独立的数据库
- 订单服务和用户服务需要对外暴露 RESTful 接口
- 订单服务在需要查询用户信息时,只能调用用户服务的 RESTful 接口,不得直接访问用户数据库
2.2.1. 数据库导入
首先,我们需要将提供的数据库脚本 cloud-order.sql
和 cloud-user.sql
导入到 MySQL 数据库中:
初始数据如下:
2.2.2. 导入示例工程
使用 IntelliJ IDEA 导入示例项目 cloud-demo
:
导入后的项目结构如下:
在这一步,确保项目配置使用正确的 JDK 版本。
2.3. 实现远程调用案例
在微服务架构中,各个服务之间需要进行远程调用,以实现不同服务的协同工作。在示例项目中,我们将介绍如何通过 RESTful 接口实现订单服务调用用户服务的功能。
2.3.1. 远程调用需求
假设我们要求修改订单服务,使得在查询订单的同时,也查询订单中包含的用户信息,并一并返回。这就要求订单服务通过调用用户服务的接口来获取用户信息。
实现这个需求的大致步骤如下:
- 在订单服务中注册一个
RestTemplate
实例,以便进行 HTTP 请求。 - 修改订单服务中的业务逻辑,调用用户服务的接口来查询用户信息,并将其填充到订单信息中。
2.3.2. 注册 RestTemplate
在订单服务的启动类 OrderApplication
中注册 RestTemplate
实例:
package cn.itcast.order;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@MapperScan("cn.itcast.order.mapper")
@SpringBootApplication
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
}
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
2.3.3. 实现远程调用
修改订单服务中的 OrderService
类的 queryOrderById
方法,实现订单信息查询的同时,远程调用用户服务获取用户信息并填充到订单中。
package cn.itcast.order.service;
import cn.itcast.order.domain.Order;
import cn.itcast.order.domain.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
@Service
public class OrderService {
@Autowired
private RestTemplate restTemplate;
public Order queryOrderById(Long orderId) {
// 查询订单信息(这部分代码略)
// 通过远程调用获取用户信息
User user = restTemplate.getForObject("http://user-service/users/{userId}", User.class, userId);
// 将用户信息填充到订单中
order.setUser(user);
return order;
}
}
2.4. 提供者与消费者
在微服务体系中,服务可以扮演提供者和消费者两种不同的角色。下面是对这两种角色的简要描述:
-
服务提供者: 在一次业务过程中,被其他微服务调用的服务。提供者负责暴露接口,供其他服务调用。
-
服务消费者: 在一次业务过程中,调用其他微服务的服务。消费者通过调用其他服务的接口来获取所需功能。
这两种角色相对而言,并非绝对。当一个服务同时调用其他服务,同时又被其他服务调用时,它可以同时担当提供者和消费者的角色。
请留下您对这些内容的反馈:
-
你觉得这篇文章是否清晰易懂?
- 是
- 否
-
你是否理解了微服务的服务拆分原则和远程调用实现?
- 是
- 部分理解
- 不太清楚
-
你在实际项目中是否遇到过类似的微服务拆分和远程调用情况?
- 是
- 否
-
你对于投票与读者互动的方式感兴趣吗?
- 是
- 一般
- 不感兴趣
请在下方进行投票并分享你的反馈。如果你有任何进一步的问题或想法,也欢迎在评论中与大家讨论。