SpringCloud ---day1

认识微服务

单体架构

微服务架构

方便进行打包上线,版本的更新上线,降低项目之间的耦合度,减少代码量巨大导致的编译/打包时间长的问题

SpringCloud简介

项目熟悉

业务流程

 项目模块划分

服务拆分原则

  什么时候拆:

对于一个初创的项目,首先要做的是验证项目的可行性。因此这一阶段的首要任务是敏捷开发,快速产出生产可用的产品,投入市场做验证。为了达成这一目的,该阶段项目架构往往会比较简单,很多情况下会直接采用单体架构,这样开发成本比较低,可以快速产出结果,一旦发现项目不符合市场,损失较小。

  如果这一阶段采用复杂的微服务架构,投入大量的人力和时间成本用于架构设计,最终发现产品不符合市场需求,等于全部做了无用功。

所以,对于大多数小型项目来说,一般是先采用单体架构,随着用户规模扩大、业务复杂后再逐渐拆分为微服务架构。这样初期成本会比较低,可以快速试错。但是,这么做的问题就在于后期做服务拆分时,可能会遇到很多代码耦合带来的问题,拆分比较困难(前易后难)。

  而对于一些大型项目,在立项之初目的就很明确,为了长远考虑,在架构设计时就直接选择微服务架构。虽然前期投入较多,但后期就少了拆分服务的烦恼(前难后易)。

 怎么拆:

之前我们说过,微服务拆分时粒度要小,这其实是拆分的目标。具体可以从两个角度来分析:

  • 高内聚:每个微服务的职责要尽量单一,包含的业务相互关联度高、完整度高。

  • 耦合:每个微服务的功能要相对独立,尽量减少对其它微服务的依赖,或者依赖接口的稳定性要强。

高内聚首先是单一职责,但不能说一个微服务就一个接口,而是要保证微服务内部业务的完整性为前提。目标是当我们要修改某个业务时,最好就只修改当前微服务,这样变更的成本更低。

一旦微服务做到了高内聚,那么服务之间的耦合度自然就降低了。

当然,微服务之间不可避免的会有或多或少的业务交互,比如下单时需要查询商品数据。这个时候我们不能在订单服务直接查询商品数据库,否则就导致了数据耦合。而应该由商品服务对应暴露接口,并且一定要保证微服务对外接口的稳定性(即:尽量保证接口外观不变)。虽然出现了服务间调用,但此时无论你如何在商品服务做内部修改,都不会影响到订单微服务,服务间的耦合度就降低了。

明确了拆分目标,接下来就是拆分方式了。我们在做服务拆分时一般有两种方式:

  • 纵向拆分

  • 横向拆分

所谓纵向拆分,就是按照项目的功能模块来拆分。例如黑马商城中,就有用户管理功能、订单管理功能、购物车功能、商品管理功能、支付功能等。那么按照功能模块将他们拆分为一个个服务,就属于纵向拆分。这种拆分模式可以尽可能提高服务的内聚性。

横向拆分,是看各个功能模块之间有没有公共的业务部分,如果有将其抽取出来作为通用服务。例如用户登录是需要发送消息通知,记录风控数据,下单时也要发送短信,记录风控数据。因此消息发送、风控数据记录就是通用的业务功能,因此可以将他们分别抽取为公共服务:消息中心服务、风控管理服务。这样可以提高业务的复用性,避免重复开发。同时通用业务一般接口稳定性较强,也不会使服务之间过分耦合。

服务注册和发现

服务拆分之后,不可避免的会出现跨微服务的业务,此时微服务之间就需要进行远程调用。微服务之间的远程调用被称为RPC,即远程过程调用。RPC的实现方式有很多,比如:​

基于Http协议​

基于Dubbo协议​
我们课堂中使用的是Http方式,这种方式不关心服务提供者的具体技术实现,只要对外暴露Http接口即可,更符合微服务的需要。​

不过这种手动发送Http请求的方式存在一些问题。​
试想一下,假如商品微服务被调用较多,为了应对更高的并发,我们进行了多实例部署
此时,每个item-service的实例其IP或端口不同,问题来了:​

item-service这么多实例,cart-service如何知道每一个实例的地址?​

http请求要写url地址,cart-service服务到底该调用哪个实例呢?​

如果在运行过程中,某一个item-service实例宕机,cart-service依然在调用该怎么办?​

如果并发太高,item-service临时多部署了N台实例,cart-service如何知道新实例的地址?

注册中心原理

在微服务远程调用的过程中,包括两个角色:

  • 服务提供者:提供接口供其它微服务访问,比如item-service

  • 服务消费者:调用其它微服务提供的接口,比如cart-service

  • 服务启动时就会注册自己的服务信息(服务名、IP、端口)到注册中心

  • 调用者可以从注册中心订阅想要的服务,获取服务对应的实例列表(1个服务可能多实例部署)

  • 调用者自己对实例列表负载均衡,挑选一个实例

  • 调用者向该实例发起远程调用

当服务提供者的实例宕机或者启动新实例时,调用者如何得知呢?​
• 服务提供者会定期向注册中心发送请求,报告自己的健康状态(心跳请求)​
• 当注册中心长时间收不到提供者的心跳时,会认为该实例宕机,将其从服务的实例列表中剔除​
• 当服务有新实例启动时,会发送注册服务请求,其信息会被记录在注册中心的服务实例列表​
• 当注册中心服务列表变更时,会主动通知微服务,更新本地服务列表

Nacos注册中心

我们基于Docker来部署Nacos的注册中心,首先我们要准备MySQL数据库表,用来存储Nacos的数据。由于是Docker部署,所以大家需要将资料中的SQL文件导入到你Docker中的MySQL容器

然后,将课前资料中的nacos目录上传至虚拟机的/root目录。

进入root目录,然后执行下面的docker命令:

 

docker run -d \ --name nacos \ --env-file ./nacos/custom.env \ -p 8848:8848 \ -p 9848:9848 \ -p 9849:9849 \ --restart=always \ nacos/nacos-server:v2.1.0-slim

以上是在将naco部署在docker中,接下来进入docker中的naco

服务注册

<!--nacos 服务注册发现-->
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

 

服务发现

服务的消费者要去nacos订阅服务,这个过程就是服务发现,步骤如下:

  • 引入依赖

  • 配置Nacos地址

  • 发现并调用服务

服务发现除了要引入nacos依赖以外,由于还需要负载均衡,因此要引入SpringCloud提供的LoadBalancer依赖。

我们在cart-service中的pom.xml中添加下面的依赖:


<!--nacos 服务注册发现-->
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

可以发现,这里Nacos的依赖于服务注册时一致,这个依赖中同时包含了服务注册和发现的功能。因为任何一个微服务都可以调用别人,也可以被别人调用,即可以是调用者,也可以是提供者。

因此,等一会儿cart-service启动,同样会注册到Nacos

接下来,服务调用者cart-service就可以去订阅item-service服务了。不过item-service有多个实例,而真正发起调用时只需要知道一个实例的地址。

因此,服务调用者必须利用负载均衡的算法,从多个实例中挑选一个去访问。常见的负载均衡算法有:

  • 随机

  • 轮询

  • IP的hash

  • 最近最少访问

  • ...

这里我们可以选择最简单的随机负载均衡;

另外,服务发现需要用到一个工具,DiscoveryClient,SpringCloud已经帮我们自动装配,我们可以直接注入使用

 OpenFeign

我们利用Nacos实现了服务的治理,利用RestTemplate实现了服务的远程调用。但是远程调用的代码太复杂了

而且这种调用方式,与原本的本地方法调用差异太大,编程时的体验也不统一,一会儿远程调用,一会儿本地调用。

因此,我们必须想办法改变远程调用的开发模式,让远程调用像本地方法调用一样简单。而这就要用到OpenFeign组件了。

其实远程调用的关键点就在于四个:

  • 请求方式

  • 请求路径

  • 请求参数

  • 返回值类型

所以,OpenFeign就利用SpringMVC的相关注解来声明上述4个参数,然后基于动态代理帮我们生成远程调用的代码,而无需我们手动再编写,非常方便

  <!--openFeign--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency><!--负载均衡器--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-loadbalancer</artifactId></dependency>

 在cart-service中,定义一个新的接口,编写Feign客户端:

这里只需要声明接口,无需实现方法。接口中的几个关键信息:

package com.hmall.cart.client;import com.hmall.cart.domain.dto.ItemDTO;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;import java.util.List;@FeignClient("item-service")
public interface ItemClient {@GetMapping("/items")List<ItemDTO> queryItemByIds(@RequestParam("ids") Collection<Long> ids);
}

​​​​​​​

  • @FeignClient("item-service") :声明服务名称

  • @GetMapping :声明请求方式

  • @GetMapping("/items") :声明请求路径

  • @RequestParam("ids") Collection<Long> ids :声明请求参数

  • List<ItemDTO> :返回值类型

然后我们直接调用itemClient方法

feign替我们完成了服务拉取、负载均衡、发送http请求的所有工作, 看起来优雅多了。

而且,这里我们不再需要RestTemplate了,还省去了RestTemplate的注册。

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

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

相关文章

el-table :span-method合并单元格

<el-table :data"tableData" :span-method"objectSpanMethod" border style"width: 100%" :height"300"><el-table-column type"index" label"序号" width"50"></el-table-column>&l…

ajax同步与异步,json-serve的安装与使用,node.js的下载

20.ajax json 轻量级的数据格式做配置文件网络传输 xml 重量级的数据格式 可扩展标记语言做配置文件网络传输 现在目前主流就是大量采用json做网络传输数据格式 1.ajax的概念: 与服务器进行’通信’的一种技术,能够实现异步的刷新页面 **同步:**按照顺序一步步的执行,容易造…

算法通过村第十四关-堆|黄金笔记|中位数

文章目录 前言数据流中的中位数的问题总结 前言 提示&#xff1a;我独自度过了太多的时光&#xff0c;沉默已成一种习惯。 帕瑞尔马卡姆《夜航西飞》 这个是一个比较难的题目&#xff0c;要不尝试一下看看。 数据流中的中位数的问题 参考题目地址&#xff1a;295. 数据流的中位…

MyBatisPlus-02

一 查询条件的三种 1.按条件查询 //方式一&#xff1a;按条件查询QueryWrapper qw new QueryWrapper();qw.lt("age",18);List<User> userList userDao.selectList(qw);System.out.println(userList); 2.lambda格式按条件查询 //方式二&#xff1a;lambda格…

基于EtherCAT的机器人多轴同步运动控制

随着工业自动化的发展&#xff0c;机器人在生产线上的应用越来越广泛。为了实现高效、精确的运动控制&#xff0c;机器人的多轴运动必须能够实现同步操作&#xff0c;它能够提高机器人的运动精度和稳定性&#xff0c;实现更高效的生产线操作。同时&#xff0c;它也为机器人的协…

WebGPU入门一

1 WebGPU学习开发环境配置 WebGPU的环境配置比较简单&#xff0c;不需要vite或webpack配置一个复杂的开发环境&#xff0c;直接使用.html文件即可。 1.1 支持WebGPU的浏览器 Chrome 113 beta测试版开始默认支持WebGPU。 1.2 index.html文件 创建index.html文件&#xff0c…

C++进阶篇1---继承

一、继承的概念和定义 1.1概念 继承机制是面向对象程序设计使代码可以复用的最重要的手段&#xff0c;它允许程序员在保持原有类特性的基础上进行扩展&#xff0c;增加功能&#xff0c;这样产生新的类&#xff0c;称为派生类。继承呈现了面向对象程序设计的层次结构&#xff…

ExoPlayer架构详解与源码分析(5)——MediaSource

系列文章目录 ExoPlayer架构详解与源码分析&#xff08;1&#xff09;——前言 ExoPlayer架构详解与源码分析&#xff08;2&#xff09;——Player ExoPlayer架构详解与源码分析&#xff08;3&#xff09;——Timeline ExoPlayer架构详解与源码分析&#xff08;4&#xff09;—…

掌握Python爬虫实现网站关键词扩展提升曝光率

目录 一、关键词优化的重要性 二、关键词优化的基本方法 1、选择与网站内容相关的关键词 2、控制关键词的密度和分布 3、关键词的层次布局 三、Python爬虫实现网站关键词扩展 1、确定目标网站 2、分析目标网站的HTML结构 3、编写Python爬虫代码 4、分析爬取到的关键词…

【算法练习Day22】 组合总和 III电话号码的字母组合

​&#x1f4dd;个人主页&#xff1a;Sherry的成长之路 &#x1f3e0;学习社区&#xff1a;Sherry的成长之路&#xff08;个人社区&#xff09; &#x1f4d6;专栏链接&#xff1a;练题 &#x1f3af;长路漫漫浩浩&#xff0c;万事皆有期待 文章目录 组合总和 III剪枝 电话号码…

深入理解React中的useEffect钩子函数

引言&#xff1a; React是一种流行的JavaScript库&#xff0c;它通过组件化和声明式编程的方式简化了前端开发。在React中&#xff0c;一个核心概念是组件的生命周期&#xff0c;其中包含了许多钩子函数&#xff0c;用于管理组件的不同阶段。其中之一就是useEffect钩子函数&…

LuaJit交叉编译移植到ARM Linux

简述 Lua与LuaJit的主要区别在于LuaJIT是基于JIT&#xff08;Just-In-Time&#xff09;技术开发的&#xff0c;可以实现动态编译和执行代码&#xff0c;从而提高了程序的运行效率。而Lua是基于解释器技术开发的&#xff0c;不能像LuaJIT那样进行代码的即时编译和执行。因此&…

系统架构与Tomcat的安装和配置

2023.10.16 今天是学习javaweb的第一天&#xff0c;主要学习了系统架构的相关知识和原理&#xff0c;下载了web服务器软件&#xff1a;Tomcat&#xff0c;并对其进行了配置。 系统架构 包括&#xff1a;C/S架构 和 B/S架构。 C/S架构&#xff1a; Client / Server&#xff0…

离散数学 学习 之 递推方程和生成函数

递推方程 注意这里的特征根一定不是相等 特解的话一般要去设出基本的形式 这是0 次多项式 生成函数

【JAVA】集合与背后的逻辑框架,包装类,List,Map,Set,静态内部类

❤️ Author&#xff1a; 老九 ☕️ 个人博客&#xff1a;老九的CSDN博客 &#x1f64f; 个人名言&#xff1a;不可控之事 乐观面对 &#x1f60d; 系列专栏&#xff1a; 文章目录 collectionCollection创建collection使用泛型collection方法 Map 接口Map的存储结构HashMap和Tr…

lenovo联想笔记本ThinkPad系列T15p或P15v Gen3(21DA,21DB,21D8,21D9)原厂Win11系统镜像

下载链接&#xff1a;https://pan.baidu.com/s/1V4UXFhYZUNy2ZQ8u4x1AFg?pwdqz0s 系统自带指纹驱动、人脸识别驱动、显卡、声卡等所有驱动、出厂主题壁纸、Office办公软件、Lenovo联想电脑管家等预装程序 所需要工具&#xff1a;32G或以上的U盘 文件格式&#xff1a;ISO …

一篇文章带你搞定所有二叉树题型的递归思维(思路超详细)

文章目录 &#x1f380;前言&#xff1a;&#x1f3c5;先在开头总结一下&#xff0c;二叉树解题的思维模式分两类&#xff1a;&#x1f387;先解释一下“前序位置”&#xff0c;“后序位置”的意思&#x1f3e8;举一个简单的例子&#xff1a; &#x1fa80;下面通过两道例题&am…

从自动化到测开,测试人员逆袭之路从此起步

在当今竞争激烈的软件测试行业中&#xff0c;近期的招聘市场确实面临一些挑战。大量的求职者争相涌入岗位&#xff0c;许多热衷于功能测试的人士甚至难以找到理想的工作机会。更不幸的是&#xff0c;连自动化测试和性能测试这些专业领域也受到了测试开发人员的竞争压力。然而&a…

C# 图解教程 第5版 —— 第4章 类型、存储和变量

文章目录 4.1 C# 程序是一组类型声明4.2 类型是一种模板&#xff08;*&#xff09;4.3 实例化类型4.4 数据成员和函数成员4.5 预定义类型4.6 用户定义类型4.7 堆和栈&#xff08;*&#xff09;4.8 值类型和引用类型4.9 变量4.9.1 变量声明4.9.2 多变量声明&#xff08;*&#x…

模式植物背景基因集制作

一边学习&#xff0c;一边总结&#xff0c;一边分享&#xff01; 写在前面 关于GO背景基因集文件的制作&#xff0c;我们在很早以前也发过。近两天&#xff0c;自己在分析时候&#xff0c;也是被搞了头疼。想重新制作一份GO背景基因集&#xff0c;进行富集分析。但是结果&…