微服务架构实战:从服务拆分到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 就是服务消费方

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


小结 :

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/82626.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MySQL 索引与事务详解

目录 一、索引&#xff08;Index&#xff09; 二、事务&#xff08;Transaction&#xff09; 三、总结 一、索引&#xff08;Index&#xff09; 索引的本质&#xff1a;一种数据结构&#xff08;如 BTree、Hash&#xff09;&#xff0c;用于快速定位数据&#xff0c;避免全…

macOS Python 环境配置指南

1. 检查现有 Python 环境 python3 --version # 检查 Python 3 版本 pip3 --version # 检查 pip 版本 2. 安装 pyenv&#xff08;Python 版本管理工具&#xff09; # 使用 Homebrew 安装 pyenvbrew install pyenv# 配置 pyenv 环境变量&#xff08;添加到 ~/.zshrc&#…

游戏引擎学习第272天:显式移动转换

回顾并为今天的内容铺垫背景 我们刚开始为游戏主角编写一些程序逻辑&#xff0c;因为我们之前已经完成了大部分引擎方面的开发&#xff0c;现在可以专注在角色身上。这个角色的移动方式会有些特别&#xff0c;与大多数游戏角色的运动机制不太一样。我们当前正在实现的控制方式…

软件测试都有什么???

文章目录 一、白盒测试&#xff08;结构测试&#xff09;二、黑盒测试&#xff08;功能测试&#xff09;三、灰盒测试四、其他测试类型五、覆盖准则对比六、应用场景 软件测试主要根据测试目标、技术手段和覆盖准则进行分类。分为白盒测试、黑盒测试、灰盒测试及其他补充类型 一…

very_easy_sql(SSRF+SQL注入)

题目有一行提示&#xff1a; you are not an inner user, so we can not let you have identify~&#xff08;你不是内部用户&#xff0c;所以我们不能让你进行身份验证&#xff09;联想到可能存在SSRF漏洞&#xff0c;一般情况下&#xff0c;SSRF攻击的目标是外网无法访问的内…

国内外主流AI编程工具全方位对比分析(截至2025年5月)

一、国际主流工具对比 1. Windsurf&#xff08;Codeium公司&#xff09; 核心功能&#xff1a;代理型AI编程&#xff08;代码导航/修改/命令执行&#xff09;、浏览器DOM访问、网页研究功能语言支持&#xff1a;70语言&#xff0c;包括Python/Java/JavaScript/Rust等[[22-23]…

ARP协议的工作原理

文章目录 ARP协议的工作原理ARP报文&#xff08;以太网&#xff09;ARP高速缓存 ARP协议的工作原理 ARP协议的作用是实现任意网络层地址到任意物理地址转换。工作原理是&#xff1a; 主机向自己所在网络广播一个ARP请求&#xff0c;该请求包含目标机器的网络地址。处于该网络…

【小知识酷】《Matlab》考点精简

在线编译器 https://matlab.mathworks.com/?elqsidumic49viv8wu5r6fckew 第1章 matlab基础知识 第1节 输出函数 1. 使用disp函数 disp函数可用于输出变量的值或者字符串。 % 输出字符串 disp(Hello, MATLAB!); %显示Hello, MATLAB!% 输出变量 x 10; disp(x); %显示10% 输出数…

码蹄集——中庸之道(三个数比较)

MT1112 中庸之道 请编写一个简单程序&#xff0c;输入3个整数&#xff0c;比较他们的大小&#xff0c;输出中间的那个数 格式 输入格式&#xff1a; 输入整型&#xff0c;空格分隔 输出格式&#xff1a;输出整型 样例 1 输入&#xff1a;1 5 3 输出&#xff1a;3 比较…

快速搭建一个vue前端工程

一、环境准备 1、安装node.js 下载地址&#xff1a;Node.js 推荐版本如下&#xff1a; 2、检查node.js版本 node -v npm -v 二、安装Vue脚手架 Vue脚手架是Vue官方提供的标准化开发工具。vue官网&#xff1a;https://cn.vuejs.org/ 全局安装vue/cli &#xff08;仅第一次…

React Native基础环境配置

React Native基础环境配置 1.引言2.React-Native简介3.项目基础环境搭建1.引言 感觉自己掌握的知识面还是有点太窄了,于是决定看看移动端的框架,搞个react搭一个后端管理项目,然后拿react-native写个小的软件,试着找个三方上架一下应用市场玩玩。毕竟不可能一直在简历上挂一…

PHP和Composer 安装

Composer 是 PHP 的 依赖管理工具&#xff0c;就像&#xff1a; Node.js 用 npm Python 用 pip Java 用 maven 用来安装和管理 PHP 项目中需要用到的第三方库 安装PHP可以理解成 Java解释器 安装PHP PHP For Windows: Binaries and sources Releaseshttps://windows.php.n…

API请求参数有哪些?

通用参数 app_key&#xff1a;应用的唯一标识&#xff0c;用于验证应用身份&#xff0c;调用API时必须提供。 timestamp&#xff1a;请求时间戳&#xff0c;通常为当前时间的毫秒级时间戳&#xff0c;用于防止请求被重放攻击。 format&#xff1a;返回数据的格式&#xff0c;…

并发笔记-条件变量(三)

文章目录 背景与动机30.1 条件变量的定义与基本操作 (Definition and Routines)30.2 生产者/消费者问题 (Bounded Buffer Problem)30.3 覆盖条件 (Covering Conditions) 与 pthread_cond_broadcast30.4 总结 背景与动机 到目前为止&#xff0c;我们已经学习了锁 (Locks) 作为并…

stm32实战项目:无刷驱动

目录 系统时钟配置 PWM模块初始化 ADC模块配置 霍尔接口配置 速度环定时器 换相逻辑实现 主控制循环 系统时钟配置 启用72MHz主频&#xff1a;RCC_Configuration()设置PLL外设时钟使能&#xff1a;TIM1/ADC/GPIO时钟 #include "stm32f10x.h"void RCC_Configu…

LC-3 中常见指令

当然可以&#xff01;以下是 LC-3 中常见指令&#xff08;汇编格式&#xff09;与对应的二进制编码格式 的总结表&#xff0c;通俗易懂地介绍每条指令的用途、操作码&#xff08;opcode&#xff09;以及格式结构。 ✅ 常见 LC-3 指令与对应的二进制格式 指令名称操作码&#x…

深入解析Docker:核心架构与最佳实践

文章目录 前言一、Docker 解决了什么问题&#xff1f;二、Docker 底层核心架构2.1 Docker 引擎的分层架构2.2 镜像的奥秘&#xff1a;联合文件系统&#xff08;UnionFS&#xff09;2.3 容器隔离的核心技术2.3.1 命名空间2.3.2 控制组&#xff08;Cgroups&#xff09;2.3.3 内核…

从零打造企业级Android木马:数据窃取与远程控制实战

简介 木马病毒已从简单的恶意软件演变为复杂的攻击工具,尤其在2025年企业级攻击中,木马病毒正成为黑客组织的主要武器之一。 本文将深入探讨如何制作具备数据窃取和远程控制功能的Android木马,从基础原理到企业级防御绕过技术,同时提供详细的代码实现,帮助开发者理解木马…

ES常识5:主分词器、子字段分词器

文章目录 一、主分词器&#xff1a;最基础的文本处理单元主分词器的作用典型主分词器示例 二、其他类型的分词器&#xff1a;解决主分词器的局限性1. 子字段分词器&#xff08;Multi-fields&#xff09;2. 搜索分词器&#xff08;Search Analyzer&#xff09;3. 自定义分词器&a…

【第三十五周】Janus-pro 技术报告阅读笔记

Janus-Pro 摘要Abstract文章信息引言方法Janus 架构Janus 训练Janus-Pro 的改进 实验结果总结 摘要 本篇博客介绍了Janus-Pro&#xff0c;这是一个突破性的多模态理解与生成统一模型&#xff0c;其核心思想是通过解耦双路径视觉编码架构解决传统方法中语义理解与像素生成的任务…