微服务基础拆分实践(第一篇)

news2024/11/7 20:39:25

目录

前言

一、认识微服务

1.1 单体架构 VS 微服务架构 

1.2 微服务的集大成者:SpringCloud

1.3 微服务拆分原则

1.4 微服务拆分方式

二、微服务拆分入门步骤 :以拆分商品模块为例

三、服务注册订阅与远程调用:以拆分购物车为例

3.1 拆分模块、发现问题

3.2 问题分析、解决方法

3.3 实现远程调用:RestTemplate工具,实现端到端请求发送

四、微服务基础拆分总结

五、微服务基础追问巩固


前言

1. 微服务的基础入门篇,读完本文让你对微服务有一个基本的了解,与此同时通过两个微服务的模块拆分实验,发现微服务拆分面临的难题。并尝试去解决它。

2. 介绍微服务与单体架构的区别、微服务的拆分原则;解决跨微服务请求问题

一、认识微服务

        我觉得既然能看到这篇笔记,想必大家对微服务都是有一定的概念的。本篇文章是笔者在学习微服务、拆分微服务、解决拆分微服务中遇到的问题总结而来。是面向实践的。


参考下面这张项目架构演变图。微服务就是随着项目规模不断扩大,为了减轻服务器的压力、维持提高项目团队的高效协作、加快项目部署打包等功能提出的技术。

它将业务代码按照业务模块的不同,划分成多个小项目或是小模块,确保了每一个模块的职责明确,且分别部署到不同的一台或多台服务器上,减少服务器压力。

1.1 单体架构 VS 微服务架构 

单体架构:将业务的所有功能集中在一个项目中开发,打成一个包部署。

优点:(小规模下的优势)

  • 架构简单
  • 部署难度低 
  • 维护成本低

缺点:(大规模下的缺陷)

  • 团队协作难(就好像1个人盖楼100天、100人盖楼1天、100万人盖楼1分钟 可能吗? 人越多,在一个单体中开发、维护越来越困难)
  • 发布效率低 (单体打包几个G、几十个G甚至更大,浪费多少时间
  • 系统可用性差(对服务器压力大,别的业务请求量大的时候会影响其他正常的业务


微服务架构:是服务化思想指导下的一套最佳实践架构方案。服务化,就是把单体架构中的功能模块拆分为多个独立项目。

优点:(大规模下谈、小规模都不用)

  • 粒度小、发布效率高
  • 团队协调效率高
  • 单台服务器压力小

缺点:(大规模下谈、小规模都不用)

  • 需要解决不同业务之间的服务调用问题 (涉及到不同服务器之间的通信请求
  • 需要更多的部署成本 (服务器多了、项目的部署更加讲究

1.2 微服务的集大成者:SpringCloud

简单来说,微服务的概念很早就有了,但是家家不同。SpringCloud的出现,就像统一度量衡制定了一系列行业标准。

SpringCloud是目前国内使用最广泛的微服务框架。 SpringCloud集成了各种微服务功能组件,并基于SpringBoot实现了这些组件的自动装配,从而提供了良好的开箱即用体验。

官网学习Spring Cloud

这张图可重要啦,对应着我们在拆分微服务项目的时候会遇到的各种问题,SpringCloud都给出了相应的解决措施。


SpringCloud 与 SpringBoot的版本对照

由于目前企业使用jdk8、jdk11比较多,所有本次实验采用2021版Spring Cloud进行微服务搭建

1.3 微服务拆分原则

1. 单一职责原则

每个微服务应专注于执行单一的功能或业务领域。

2. 高内聚、低耦合

把相关的行为都聚集在一起,把不相干的行为放到其他地方。这样,当他们要修改某个行为的时候,只需要在一个地方修改即可,然后就能对该修改及早地进行发布。同时也有利于降低模块与模块之间的耦合性,提高每个模块的独立性。

如果要在很多不同的地方做修改,那么就需要同时发布多个微服务才能交付这个功能。修改进度不统一、测试工作不线性、部署工作不集中。从而大大降低开发效率。

3. 独立有边界

微服务应有明确定义的边界和功能。

1.4 微服务拆分方式

纵向拆分:按业务模块进行拆分,并遵循微服务拆分原则

横向补充:对于大家都会用到的公共服务,还可以在纵向基础上补充横向拆分,抽取公共服务,提高代码复用

目前广泛应用的两种微服务架构

1. 拆分独立若干project,分项目管理

这种拆分适合于超大规模的团队协调开发,项目完全解耦。

  • 优点:服务之间耦合度低

  • 缺点:每个项目都有自己的独立仓库,管理起来比较麻烦

2. 拆分依赖于主模块的若干子模块,统一Maven管理

这种拆分相对我们学习来说比较容易,一个项目内用不同的模块代表不同的服务

  • 优点:项目代码集中,管理和运维方便

  • 缺点:服务之间耦合,编译时间较长

二、微服务拆分入门步骤 :以拆分商品模块为例

本次实验以黑马商城的项目拆分为例,采用拆分模块的方式来进行微服务的学习:

2.1 入门拆分微服务步骤 

  • 第一步:新建微服务模块
  • 第二步:拷贝父工程的依赖坐标
  • 第三步:搭建基本框架,编写启动类
  • 第四步:拷贝配置文件,修改相关配置
  • 第五步:拷贝业务代码,遵循从 domain -- mapper -- service -- controller,注意检查导包
  • 第六步:连接数据库,确认微服务数据库
  • 第七步:测试项目 访问 接口文档 进行代码请求测试http://localhost:8081/doc.htmlicon-default.png?t=O83Ahttp://localhost:8081/doc.html

<!--来自父工程-->
    <dependencies>
        <!--common-->
        <dependency>
            <groupId>com.heima</groupId>
            <artifactId>hm-common</artifactId>
            <version>1.0.0</version>
        </dependency>
        <!--web-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--数据库-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!--mybatis-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
        </dependency>
        <!--单元测试-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
    </dependencies>
    <build>
        <finalName>${project.artifactId}</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

2.2 解决商品模块的请求 500 问题

原因】 数据库连接失败,配置文件加载失败

解决措施】修改配置文件名即可

三、服务注册订阅与远程调用:以拆分购物车为例

3.1 拆分模块、发现问题

前面的拆分步骤照常,以下是拆分购物车模块遇到的问题

购物车微服务需要依赖商品微服务模块的方法,因此产生了报错,对此我们先采取注释的方式。先确保购物车微服务模块搭建运行成功后,后续我们再来通过SpringCloud的技术来解决这个问题。

接着配置数据库、将微服务部署到8082端口,启动访问测试:http://localhost:8082/doc.html

3.2 问题分析、解决方法

我们发现,拆分微服务的项目往往会面临这样一个问题:一个微服务需要注入另外一个微服务的方法或属性。

可是拆分微服务需要遵循一个原则:独立性、单一职责。也就是说我们不应该在购物车的微服务业务中注入过多的商品微服务模块的方法。

因此,我们需要思考如何让购物车微服务获取到商品微服务的方法同时又不破坏拆分原则呢?我们知道实际上我们发送的请求是一个完整的URL,可不可以这样做:我们模仿前端向后端发送请求的格式,让购物车发送获取商品信息的请求,这样一来不就解决问题了嘛

3.3 实现远程调用:RestTemplate工具,实现端到端请求发送

服务拆分之后,不可避免的会出现跨微服务的业务,此时微服务之间就需要进行远程调用。微服务之间的远程调用被称为RPC,即远程过程调用。

RestTemplate介绍

java开发中,使用http连接访问第三方网络接口,通常使用工具HttpClient和OKHttp。(后面讲)

如果使用spring框架,可以使用Spring给我们提供了一个RestTemplate工具,可以方便的实现Http请求的发送。

restTemplate默认的连接方式是java中的HttpConnection,可以使用ClientHttpRequestFactory指定不同的HTTP连接方式。

【使用步骤】

1. 在springboot项目中,需要使用RestTemplate的模块【cartcart-service】新建config配置

2. 注入RestTemplate对象

3. 使用RestTemplate方法进行代码修改

private void handleCartItems(List<CartVO> vos) {
        // 1.获取商品id
        Set<Long> itemIds = vos.stream().map(CartVO::getItemId).collect(Collectors.toSet());
        // 2.查询商品
        // 2.1 构建请求、发送请求
        ResponseEntity<List<ItemDTO>> response = restTemplate.exchange(
            "http://localhost:8081/items?ids={ids}",
                HttpMethod.GET,
                null,
                new ParameterizedTypeReference<List<ItemDTO>>() {},
                Map.of("ids", CollUtil.join(itemIds, ","))
        );
        //2.2 解析响应对象
        if(!response.getStatusCode().is2xxSuccessful()) {
            // 查询失败
            return;
        }
        // 2.3 获取查询商品对象
        List<ItemDTO> items = response.getBody();
        if(CollUtils.isEmpty(items)) {
            return;
        }

        // 3.构建商品id与商品对象的映射
        Map<Long,ItemDTO> itemMap = items.stream().collect(Collectors.toMap(ItemDTO::getId, Function.identity()));

        //4. 写入VO对象返回前端
        for(CartVO v : vos) {
            ItemDTO item = itemMap.get(v.getItemId());
            if(item == null) {
                continue;
            }
            v.setNewPrice(item.getPrice()); // 最新价格
            v.setStock(item.getStock()); // 库存
            v.setStatus(item.getStatus()); // 状态
        }
    }

功能测试

四、微服务基础拆分总结

到此为止,事实上你已经可以搭建一个简易的微服务项目了。尽管这个微服务项目还有诸多问题和挑战。

例如你发现没有?在我们使用RestTemplate工具发送请求的时候,url是我们写死的。而且开发者需要非常清楚有这么一个方法,有这么一个方法的提供者,并且要知道提供者的具体地址。与此同时,如果服务的提供者宕机了,服务调用者也无法得知。这样的限制太大了。所以后期我们一定会寻求这方面的突破的。

在基础篇中,我们了解了微服务架构和单体架构的区别、学习了微服务拆分的模式和需要遵循的原则、尝试进行简单微服务模块的拆分并调试成功、成功发现跨微服务请求问题并初步尝试使用强大的RestTemplate去解决它......通过以上内容,相信你已经入门微服务了,接下来也能更好地去深入微服务项目的学习。

五、微服务基础追问巩固

1. 谈谈什么是微服务?什么时候要用微服务?目前主流的微服务技术有哪些?

2. 谈谈拆分微服务应该遵守哪些原则?你认为其中最有挑战性的是什么?

3. 详细讲解微服务的拆分步骤是什么?

4. 如果拆分过程中遇到要使用其他微服务提供的方法是,如何实现请求的远程调用?

5. 了解过RestTemplate没有?请谈谈你对RestTemplate的看法,具体的使用步骤是什么?

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

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

相关文章

【NOIP普及组】 过河卒

【NOIP普及组】 过河卒 &#x1f490;The Begin&#x1f490;点点关注&#xff0c;收藏不迷路&#x1f490; 如图&#xff0c;A 点有一个过河卒&#xff0c;需要走到目标 B 点。卒行走规则&#xff1a;可以向下、或者向右。同时在棋盘上的任一点有一个对方的马&#xff08;如上…

功能强大视频编辑软件 Movavi Video Editor Plus 2024 v24.2.0 中文特别版

Movavi Video Editor Plus中文修改版是一款功能强大的视频制作编辑软件&#xff0c;使用能够帮助用户快速从录制的素材中制作成一个精美的电影&#xff0c;支持进行视频剪辑&#xff0c;支持添加背影、音乐和各种音乐&#xff0c;软件使用简单&#xff0c;无需任何的经验和专业…

linux基本指令之文件操作

前言 这次博客的主要目的就是要解决如何快速查看或查找文件&#xff0c;以及讲解文件的一些属性。本次博客还是以基本指令为主来理解linux对文件的操作。 linux下输入输出流的理解 在linux中&#xff0c;我们要对文件进行输入输出时&#xff0c;一般会怎么做呢? 可以通过pr…

JavaEE初阶---网络原理值TCP篇(三)

文章目录 1.延时应答机制2.捎带应答3.面向字节流---粘包问题3.1问题引入3.2解决方法 4.异常情况的处理5.TCP的心跳机制6.TCP/UDP的对比 1.延时应答机制 例如我们的这个剩余空间大小10kb,如果我们直接返回ack,这个发送方的窗口大小只能是10kb&#xff0c;但是如果我们进行延时&…

慢sql优化和Explain解析

要想程序跑的快&#xff0c;sql优化不可懈怠&#xff01;今日来总结一下常用的慢sql的分析和优化的方法。 1、慢sql的执行分析&#xff1a; 大家都知道分析一个sql语句执行效率的方法是用explain关键词&#xff1a; 举例&#xff1a;sql:select * from test where bussiness_…

Java后端面试内容总结

先讲项目背景&#xff0c;再讲技术栈模块划分&#xff0c; 讲业务的时候可以先讲一般再特殊 为什么用这个&#xff0c;好处是什么&#xff0c;应用场景 Debug发现问题/日志发现问题. QPS TPS 项目单元测试&#xff0c;代码的变更覆盖率达到80%&#xff0c;项目的复用性高…

【10月】新款3DMAX插件排行榜

根据近期的行业动态和插件发布情况&#xff0c;整理并推荐一些在10月或近期内受到关注的3DMAX新款插件。 1. MaxToCAD插件 功能特点&#xff1a;允许用户将3D MAX中的三维模型快速转换为CAD软件可识别的二维平面图&#xff0c;适用于需要将3D设计导出为施工图或平面图的设计师…

【数据结构与算法】第7课—数据结构之队列

文章目录 1. 队列1.1 什么是队列1.2 队列的结构1.3 队列初始化1.4 队列入栈1.5 出队列1.6 查找队列有效元素个数1.7 取队头和队尾数据1.8 销毁链表 2. 用两个队列实现栈3. 用两个栈实现队列4. 循环队列 1. 队列 注&#xff1a;文中Queue是队列&#xff0c;Quene是错误写法 1.1 …

window快捷键:window + v 打开剪切板历史记录 / 非常实用

一、剪切板历史记录功能介绍 1.1、window v 打开剪切板历史记录 / 文字、图片都可记录 1.2、window v 最近使用 1.3、window v 表情符号 1.4、window v GIF 1.5、window v 颜文字 1.6、window v 符号 二、欢迎交流指正

手机功耗异常大数据看板建设

一、背景 基于《软件绿色联盟应用体验标准—功耗标准》监控软硬件资源功耗异常类别与趋势 上述为手机功耗问题的前世今生及我们应该在哪些维度建立功耗的埋点监控支持分析​ 二、目标 手机端侧建立alarm\wakelock\wakeup\gps\bt\cpu\sensor\netTriffic等功耗相关的使用次数和时…

多彩电子显示屏

在仓储管理的广阔舞台上&#xff0c;一款名为“仓库46代”的创新标签悄然登场&#xff0c;它不仅是技术的飞跃&#xff0c;更是智慧仓储的新篇章。这款标签&#xff0c;以其独特的515.6x260x29mm身材&#xff0c;优雅地融入了繁忙的仓库环境&#xff0c;其沉稳的黑色外观&#…

sklearn|机器学习:决策树(一)

文章目录 sklearn&#xff5c;机器学习&#xff1a;决策树&#xff08;一&#xff09;&#xff08;一&#xff09;概述&#xff08;二&#xff09;实战1. 环境配置2. sklearn 中的决策树&#xff08;1&#xff09;模块 sklearn.tree&#xff08;2&#xff09;sklearn 基本建模流…

服务器Linux系统网络重启失败 Restarting network (via systemctl):......

网络重启时报错&#xff1a; Linux 网络服务重启失败可能由网络配置工具冲突或配置错误引起。 冲突问题&#xff1a;在 Linux 中&#xff0c;network 和 NetworkManager 这两个工具可能会冲突&#xff0c;禁用 NetworkManager 可以尝试解决该问题。 先停止服务 systemctl s…

域控操作二十四:主域故障辅域接替

模拟环境&#xff1a;上海DC1故障无法开机&#xff0c;导致只有一个DNS的电脑无法上网&#xff08;实际可以添加DC2但是为了实验就不说了&#xff09; FSMO还在DC1上 使用powershell把角色迁移到DC2 ntdsutil roles connections connect to server DC2SHA.whbk.cn quitSeize …

边缘AI计算技术应用-实训解决方案

一、解决方案架构 1.1 来自产业的项目 实训项目全部是基于产业的商业化项目&#xff0c;经过角色拆解、任务拆解、代码拆解、部署流程拆解等过程&#xff0c;讲其标准化为教师可以带领学生完成的实训内容&#xff0c;真正帮助学生接触产业前沿技术和工作内容&#xff0c;提升就…

贪心算法习题其二【力扣】【算法学习day.18】

前言 ###我做这类文档一个重要的目的还是给正在学习的大家提供方向&#xff08;例如想要掌握基础用法&#xff0c;该刷哪些题&#xff1f;&#xff09;我的解析也不会做的非常详细&#xff0c;只会提供思路和一些关键点&#xff0c;力扣上的大佬们的题解质量是非常非常高滴&am…

【Axure原型分享】颜色选择器——填充颜色

今天和大家分享颜色选择器——填充颜色的原型模板&#xff0c;点击颜色区域可以弹出颜色选择器&#xff0c;点击可以选择对应颜色&#xff0c;颜色区域会变色我们选择的颜色&#xff0c;具体效果可以观看下方视频或者打开预览地址体验。 【原型效果】 【Axure高保真原型】颜色…

SQL实战训练之,力扣:1843. 可疑银行账户

目录 一、力扣原题链接 二、题目描述 三、建表语句 四、题目分析 五、SQL解答 六、最终答案 七、验证 八、知识点 一、力扣原题链接 1843. 可疑银行账户 二、题目描述 表: Accounts ---------------------- | Column Name | Type | ---------------------- | acco…

软件系统交付阶段必备文档,验收体系配套资料,软件系统各阶段各步骤相关配套资料,各类软件建设方案(word,ppt)

软件文档交付清单是指在软件开发项目完成后&#xff0c;开发团队需要准备的一份详细清单&#xff0c;用于确保交付的软件产品符合客户需求并达到预期的质量标准。以下是软件文档交付清单中可能包含的一些关键要素 软件资料清单列表部分文档清单&#xff1a;工作安排任务书&…

Day07爬楼梯

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢&#xff1f; class Solution {public int climbStairs(int n) {if (n 1) return 1;if (n 2) return 2;return climbStairs(n - 1) climbStairs(n - 2);} }用…