当前位置: 首页 > news >正文

微服务架构实战:从服务拆分到RestTemplate远程调用

微服务架构实战:从服务拆分到RestTemplate远程调用

  • 一 . 服务拆分
    • 1.1 服务拆分注意事项
    • 1.2 导入服务拆分 Demo
    • 1.3 小结
  • 二 . 服务间调用
    • 2.1 注册 RestTemplate
    • 2.2 实现远程调用
    • 2.3 小结
  • 三 . 提供方和消费方

在分布式系统设计中,微服务架构因其灵活性、可扩展性成为主流方案。然而,如何合理拆分服务、实现高效服务间通信,是开发者面临的核心挑战。本文通过一个电商场景的订单-用户服务案例,演示如何基于单一职责原则拆分微服务,并通过RestTemplate实现服务间HTTP调用。读者将学习到:

  1. 服务拆分的三大核心原则(单一职责、数据独立、面向服务);
  2. 独立数据库设计与多服务协同开发;
  3. 使用Spring Boot的RestTemplate组件完成跨服务数据聚合。
    在这里插入图片描述

    本专栏的内容均来自于 B 站 UP 主黑马程序员的教学视频,感谢你们提供了优质的学习资料,让编程不再难懂。

    专栏地址 : https://blog.csdn.net/m0_53117341/category_12835102.html

一 . 服务拆分

1.1 服务拆分注意事项

  1. 单一职责 : 不同微服务之间不要重复的开发相同业务
  2. 数据独立 : 不能访问其他微服务的数据库
  3. 面向服务 : 将自己的业务暴露出接口 , 供其他微服务调用

1.2 导入服务拆分 Demo

第一步 : 导入提供给大家的项目模板

cloud-demo.zip

那在父工程的 <dependencyManagement> 下 , 只负责版本的锁定 , 不负责版本的导入

然后我们来修改一下两个微服务的 application.yml 信息

第二步 : 了解项目架构

  1. order-service : 根据 ID 查询订单
  2. user-service : 根据 ID 查询用户

那这两个就是不同的微服务 , 也需要有自己独立的数据库

第三步 : 将两个微服务的 SQL 进行导入

-- 创建数据库
create database `cloud_user` character set utf8mb4;-- 使用数据库
use `cloud_user`;SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;-- ----------------------------
-- Table structure for tb_user
-- ----------------------------
DROP TABLE IF EXISTS `tb_user`;
CREATE TABLE `tb_user`  (`id` bigint(20) NOT NULL AUTO_INCREMENT,`username` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '收件人',`address` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '地址',PRIMARY KEY (`id`) USING BTREE,UNIQUE INDEX `username`(`username`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 109 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;-- ----------------------------
-- Records of tb_user
-- ----------------------------
INSERT INTO `tb_user` VALUES (1, '柳岩', '湖南省衡阳市');
INSERT INTO `tb_user` VALUES (2, '文二狗', '陕西省西安市');
INSERT INTO `tb_user` VALUES (3, '华沉鱼', '湖北省十堰市');
INSERT INTO `tb_user` VALUES (4, '张必沉', '天津市');
INSERT INTO `tb_user` VALUES (5, '郑爽爽', '辽宁省沈阳市大东区');
INSERT INTO `tb_user` VALUES (6, '范兵兵', '山东省青岛市');SET FOREIGN_KEY_CHECKS = 1;
-- 创建数据库
create database `cloud_order` character set utf8mb4;-- 使用数据库
use `cloud_order`;SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;-- ----------------------------
-- Table structure for tb_order
-- ----------------------------
DROP TABLE IF EXISTS `tb_order`;
CREATE TABLE `tb_order`  (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '订单id',`user_id` bigint(20) NOT NULL COMMENT '用户id',`name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '商品名称',`price` bigint(20) NOT NULL COMMENT '商品价格',`num` int(10) NULL DEFAULT 0 COMMENT '商品数量',PRIMARY KEY (`id`) USING BTREE,UNIQUE INDEX `username`(`name`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 109 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;-- ----------------------------
-- Records of tb_order
-- ----------------------------
INSERT INTO `tb_order` VALUES (101, 1, 'Apple 苹果 iPhone 12 ', 699900, 1);
INSERT INTO `tb_order` VALUES (102, 2, '雅迪 yadea 新国标电动车', 209900, 1);
INSERT INTO `tb_order` VALUES (103, 3, '骆驼(CAMEL)休闲运动鞋女', 43900, 1);
INSERT INTO `tb_order` VALUES (104, 4, '小米10 双模5G 骁龙865', 359900, 1);
INSERT INTO `tb_order` VALUES (105, 5, 'OPPO Reno3 Pro 双模5G 视频双防抖', 299900, 1);
INSERT INTO `tb_order` VALUES (106, 6, '美的(Midea) 新能效 冷静星II ', 544900, 1);
INSERT INTO `tb_order` VALUES (107, 2, '西昊/SIHOO 人体工学电脑椅子', 79900, 1);
INSERT INTO `tb_order` VALUES (108, 3, '梵班(FAMDBANN)休闲男鞋', 31900, 1);SET FOREIGN_KEY_CHECKS = 1;

那将来微服务的模块有可能会很多 , 启动起来会很麻烦 , 就给大家介绍一种新的启动方式

之后我们想要启动谁 , 选中谁即可

1.3 小结

  1. 微服务需要根据业务模块拆分 , 做到单一职责 , 不要重复开发相同业务
  2. 微服务可以将业务暴漏为接口 , 供其他微服务使用
  3. 不同微服务都应该有自己独立的数据库

二 . 服务间调用

我们先访问这两个服务

访问 http://127.0.0.1:8081/user/1 就可以获取到 ID 为 1 的用户信息

访问 http://127.0.0.1:8080/order/101 就可以获取到 ID 为 101 的订单信息

那接下来 , 我们想实现一个案例 : 根据订单 ID 查询订单的同时 , 把订单所属的用户信息一起返回

那这样的话 , 我们就需要将上面两个 URL 所获取的内容合并 , 然后进行返回

那我们用户是通过 URL 来获取到数据的 , 所以我们也可以通过代码的方式来去模拟 URL 来去获取数据

那接下来 , 我们就在 order-service 中向 user-service 发起一个 HTTP 请求 , 调用 http://127.0.0.1:8081/user/{userId} 这个接口

2.1 注册 RestTemplate

我们在 order-service 的启动类中创建一个模板对象

package com.example.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("com.example.order.mapper")
@SpringBootApplication
public class OrderApplication {public static void main(String[] args) {SpringApplication.run(OrderApplication.class, args);}@Beanpublic RestTemplate restTemplate() {return new RestTemplate();}
}

2.2 实现远程调用

那接下来 , 我们就需要组装出要发送的 URL 地址了

首先 , 我们需要获取到 userId , 而正好 order 表中也存储了 userId , 所以我们可以直接获取

那接下来就需要拼接 URL 了

接下来 , 我们就可以调用 RestTemplate 来去发起请求获取用户信息

首先需要注入 RestTemplate 对象

然后我们调用它的 getForObject 方法 , 他有两个参数

  1. 要发起请求的 URL 地址
  2. 获取到的消息应该转化成哪种对象

最后我们把获取到的内容添加到 order 的 user 字段中

package com.example.order.service;import com.example.order.mapper.OrderMapper;
import com.example.order.pojo.Order;
import com.example.order.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;@Service
public class OrderService {@Autowiredprivate OrderMapper orderMapper;@Autowiredprivate RestTemplate restTemplate;public Order queryOrderById(Long orderId) {// 1. 查询订单Order order = orderMapper.findById(orderId);// 2. 查询用户 IDLong userId = order.getUserId();// 3. 拼接 URLString url = "http://127.0.0.1:8081/user/" + userId;// 4. 调用 RestTemplate 发起请求获取用户信息// 第一个参数: 要请求的 URL 地址// 第二个参数: 获取到的数据要转换成哪种对象User user = restTemplate.getForObject(url, User.class);// 5. 将获取到的用户信息添加到 order 实体类的 user 字段中order.setUser(user);// 6. 返回return order;}
}

接下来 , 我们重启 order-service 服务 , 来观察一下前后变化

2.3 小结

微服务调用方式

  • 基于 RestTemplate 发起的 HTTP 请求实现远程调用
  • HTTP 请求做远程调用是与语言无关的调用 , 只需要知道对方的 IP、端口、接口路径、请求参数即可 .

三 . 提供方和消费方

服务提供方 : 被其他微服务调用的服务 (提供接口给其他微服务)

服务消费方 : 调用其他微服务的服务 (调用其他微服务提供的接口)

那我们之前的案例中 , user-service 就是服务提供方 , order-service 就是服务消费方

那提供方与消费方的角色其实是相对来说的 , 一个服务既可以是服务提供者 , 又可以是服务消费者


小结 :

相关文章:

  • 模型过拟合是什么?
  • springboot3整合SpringSecurity实现登录校验与权限认证
  • 理解反向Shell:隐藏在合法流量中的威胁
  • React 从零到一执行原理 (2025 最新版)
  • 数据仓库Hive
  • 力扣2680题解
  • 趣味编程:四叶草
  • 一种混沌驱动的后门攻击检测指标
  • 关于chatshare.xyz激活码使用说明和渠道指南!
  • vue数据可视化开发echarts等组件、插件的使用及建议-浅看一下就行
  • MNIST 手写数字分类
  • HVV面试题汇总合集
  • 雷达工程师面试题目
  • Redis 基础详解:从入门到精通
  • 【Redis】Redis的主从复制
  • 5G-A来了!5G信号多个A带来哪些改变?
  • C++ stl中的priority_queue的相关函数用法
  • 大模型都有哪些超参数
  • 如何实现Flask应用程序的安全性
  • 接口在函数参数和对象类型中的应用
  • 国产水陆两栖大飞机AG600批产首架机完成总装下线
  • 全国汽车以旧换新补贴申请量突破1000万份
  • 浙江省机电集团党委书记、董事长廉俊接受审查调查
  • 上海工匠学院首届学历班56人毕业,新一届拟招生200人
  • 国常会:研究深化国家级经济技术开发区改革创新有关举措等
  • 纪念|古文字学泰斗裘锡圭:“还有很多事情要做”