SpringCloud概述和环境搭建
SpringCloud概述和环境搭建
- 一.微服务的引入
- 1.单体架构
- 2.集群和分布式架构
- 3.集群和分布式
- 4.微服务架构
- 4.微服务的优缺点
- 二.微服务解决方案-SpringCloud
- 1.Spring Cloud简介
- 2.Spring Cloud版本
- 3.Spring Cloud实现方案
- 4.Spring Cloud Alibaba
- 三.环境搭建
- 1.安装JDK17
- 2.Ubantu上下载JDK17
- 3.Ubantu环境下安装MySQL
- 四.服务拆分
- 1. 单⼀职责原则
- 2.服务自治
- 3. 单向依赖
- 五.工程搭建
- 1.父工程的搭建
- 2.子工程的搭建
- 六.远程调用
- 1.需求
- 2.实现
- 3.RestTemplate
- REST
- RESTful
- RESTful实践
- 上述项目存在的问题
一.微服务的引入
下图表示了服务架构从单体应用逐渐转变为微服务应用的过程:
1.单体架构
很多创业公司早期或者传统企业会把业务的所有功能实现都打包在一个项目,这就是单体架构。业务的所有功能实现都打包在一个war包或者Jar包中,这种方式就称为单体架构。比如Spring课程中的博客系统,前端+后端+数据库实现,都在⼀个项目中,这种架构就称为单体架构。
以大家都很熟悉的电商系统为例,电商系统包括:用户管理,商品管理,订单管理,支付管理,库存管理,物流管理等等,项目早期我们会把这些模块都写在⼀个web项目中,然后统⼀部署到⼀个Web服务器中。
这种架构开发简单,部署简单一个项目就包含了所有的功能,省去了多个项目之间的交互和调用消耗
直接部署在一个服务器即可。
2.集群和分布式架构
当网站的用户量越来越大,需求也会越来越多,流量也会越来越大,服务可能就会面临以下问题:
- 后端服务器的压力就会越来越大,负载越来越高,甚至出现无法访问的情况
- 业务场景逐渐复杂。为了满足用户的需求,单体应用也会越来越大。各个业务代码之间的耦合度也会
越来越高,任何一个问题,都需要整个项目重新构建,发布。 - ⼀个微小的问题,可能会导致整个应用挂掉。
我们从两个方面进行优化:
- 横向:添加服务器,把单台机器变成多台机器的集群。
- 纵向:把⼀个应用,按照业务进行拆分,拆分为多个项⽬。此架构也称为垂直架构。
以单体结构规模的项目为单位进行垂直划分。也就是将一个大项目拆分成⼀个⼀个单体结构项目,项目和项目之间相对比较独立,接口多为数据同步功能。
3.集群和分布式
- 集群(cluster)是将一个系统完整的部署到多个服务器上,每个服务器都能提供系统的所有服务,多个服务器通过负载均衡调度完成任务。每个服务器称为集群的节点。
- 分布式是将一个系统拆分为多个子系统,多个子系统部署在多个服务器上,多个服务器上的子系统
协同合作完成一个特定任。
比如:
⼀个饭店只有⼀个厨师,这个厨师负责备菜,洗菜,切菜,炒菜。随着这个饭店的生意越来越好,这个厨师忙不过来了,饭店⼜请了⼀个厨师,新厨师和老厨师做⼀样的事情,也是洗菜,切菜,炒菜,这两个厨师的关系就是集群。
为了让厨师专⼼炒菜,饭店⼜请了⼀个配菜师,负责备菜,洗菜,切菜。厨师和配菜师的关系就是分布式。后来⼀个配菜师也忙不过来了,⼜请了⼀个配菜师,这两个配菜师的关系就是集群
集群和分布式区别和联系
- 从概念上:集群是多个计算机做同样的事,分布式是多个计算机做不同的事。
- 从功能上:集群的每一个节点功能是相同的,并且可以替代的,分布式也是多个节点组成的系统,但是每个节点完成的业务是不同的,一个节点出现问题,这个业务就不可访问了。
- 从关系上:分布式和集群在实践中,很多时候是互相配合使⽤的。比如分布式的某一个节点,可能由一个集群来代替。分布式架构大多是建立在集群上的。所以实际的分布式架构设计中并不会把分布式和
集群单独区分,而是统称:分布式架构。
4.微服务架构
从上图中可以看出,按照业务进行拆分后,会有一些重复的功能开发,比如订单系统,电商平台和支付系统都会涉及。
在分布式架构下,当部署的服务越来越多,重复的代码就会越来越多,服务的调⽤关系也会越来越复杂
我们可以把⼀些通用的,会被多个上层服务调⽤的共享业务,提取成独立的基础服务,组成⼀个个微小的服务,这就是微服务.
简单来说,微服务就是很小的服务。小到一个服务只对应一个单一的功能,只做一件事。这个服务可以单独部署运行,微服务之间可以采用REST和RPC协议进行通信。
从这个角度来看,微服务架构是分布式架构的⼀种拓展,这种架构模式下它拆分粒度更小,服务更独立。可以理解为:微服务是⼀种经过良好架构设计的分布式架构方案。
分布式架构&微服务架构
-
分布式:服务拆分,拆了就行。
微服务:指非常微小的服务,更细粒度的垂直拆分,通常指不能再拆的服务。 -
分布式架构侧重于压力的分散,强调的是服务的分散化。微服务侧重于能力的分散,更强调服务的专业化和精细分工。从实践的角度来看,微服务架构通常是分布式服务架构,反之则未必成立。所以,选择微服务通常意味着需要解决分布式架构的各种难题。
4.微服务的优缺点
优点:
- 易开发和维护:每个微服务负责的业务比较清晰,体量小,开发和维护成本降低。
- 容错性高:⼀个服务发生故障,可以使故障隔离在单个服务中,不影响整体服务故障。
- 扩展性好:每个服务都是独立运行的,我们可以结合项⽬实际情况进行扩展,按需伸缩。
- 技术选型灵活:每个微服务都是单独的团队来运维,可以根据业务特点和团队特点,选择适合的技术
栈。
缺点:
- 运维成本:一个业务流程会涉及多个微服务共同完成,有更多的服务需要编译,部署,运行,甚至可能是不同的编程语言,不同的运行环境,当然也需要集群来处理故障转移等。这对于运维⼈员而言,挑战是巨大的。
- 开发和测试:一个业务流程可能涉及多个微服务共同完成,服务调⽤引入网络延迟,不可靠的⽹络,如何进行容错处理等问题。这对开发和测试而言,难度也会提升。
- 服务监控:在⼀个单体结构中,很容易实现服务的监控。因为所有功能都在⼀个服务中,微服务架构
下,不仅需要对整个链路进行监控,还需要对每⼀个服务实现监控。 - 负载均衡:微服务架构中的服务实例数量可能非常庞大,因此需要有效的服务发现和负载均衡机制
来管理请求流量和保证高可用性。
栗子:
比如企业员⼯管理员工少的时候,⼀个员工可能各方面的工作都要会,但是员工之间的协同工作会少⼀点,员工管理也会相对简单。
随着企业的发展,事情越来越多,⼀个员工的能力有限,就需要招聘更多的⼈,这时候就涉及到员工的
管理了。员工越多,员工的管理就越复杂服务也是类似.
二.微服务解决方案-SpringCloud
1.Spring Cloud简介
可以通过点击此处查看Spring Cloud官方的介绍Spring Cloud简介
简单地说:Spring Cloud 是一个基于 Spring Boot 的 分布式系统开发工具集,专注于简化微服务架构的构建、部署和运维。它提供了一系列开箱即用的组件,覆盖了服务治理、配置管理、容错处理、安全等关键领域,是 Java 生态中实现微服务的核心框架之一。
Spring Cloud并不是Spring团队研发的框架,它只是把⼀些比较优秀的解决微服务架构中常见问题的开源框架基于SpringCloud规范进行了整合,并基于SpringBoot的风格,对这些组件进行封装,屏蔽掉了复杂的配置和实现原理。为开发者提供了开箱即用的微服务开发体验。这些开源技术的框架是由各个公司来维护的。Spring Cloud就是这些微服务的大管家.
2.Spring Cloud版本
3.Spring Cloud实现方案
在Spring Cloud的规范下,有很多实现,其中最为出名的是
- Spring Cloud Netflix
- Spring Cloud Alibaba
Spring Cloud Netflix
Spring Cloud Netflix是 Netflix OSS(Netflix Open Source Software)在Spring Cloud规范下的实现.
包含的组件及其主要功能⼤致如下:
- Eureka: 服务注册和发现
- Zuul: 服务网关
- Ribbon: 负载均衡
- Feign: 服务调用组件
- Hystrix: 断路器,提供服务熔断和限流
- Hystrix Dashboard:监控面板
在很长的一段时间里,Spring Cloud ⼀度被泛指 Spring Cloud Netflix。Spring Cloud一直以来把Netflix OSS 套件作为其官放默认的⼀站式解决方案。然而,Netflix公司在2018年前后宣布其核心组件Hystrix、Ribbon、Zuul等均进⼊维护状态,Spring Cloud 也被迫宣布删除这些维护模块。
spring-cloud-netflix 并没有从Spring Cloud的依赖中完全删除,只是从2020.0版本起,他只管理Eureka.
Spring Cloud Netflix 在很多公司都有大规模使用,一旦停止更新,短期看影响不大,但长期显然是不合
适的,Spring Cloud官方也提供了⼀些替换建议。
4.Spring Cloud Alibaba
标题是超链接,可以跳转到Spring Cloud Alibaba的官方文档
Spring Cloud Alibaba 是阿里巴巴集团下的开源组件和云产品在Spring Cloud规范下的实现。虽然Spring Cloud Alibaba⽬前并不是Spring Cloud官方推荐的默认方案,但是Spring Cloud Alibaba 是阿里中间件团队主导的⼀个新生项目,正处于高速迭代中。甚至在Alibaba的开源组件还没有织入Spring Cloud生态之前,就已经在各大公司广泛使用了.
如果说Spring Cloud Netflix 是 Spring Cloud 的第一代实现,那么Spring Cloud Alibaba 也可以看做是
Spring Cloud 的第⼆代实现,主要由 Nacos、Sentinel、Seata 等组件组成。
Spring Cloud Alibaba 吸收了 Spring Cloud Netflix 微服务框架的核心架构思想,并进行了高⾼性能改
进。自Spring Cloud Netflix 进⼊停更维护后,Spring Cloud Alibaba 逐渐代替它成为主流的微服务框
架。
三.环境搭建
1.安装JDK17
JDK安装地址
Spring Cloud 是基于 SpringBoot 进行开发的,SpringBoot 3.X以下的版本,Spring官方已不再进行维
护(还可以继续使用),SpringBoot 3.X的版本,使用的JDK版本基线为JDK17。
2.Ubantu上下载JDK17
更新软件包
sudo apt update
安装JDK
sudo apt install openjdk-17-jdk
检查JDK版本:
java -version
如果需要卸载按照下面的步骤:
检查安装的是哪个OpenJDK
dpkg --list | grep -i jdk
移除 openjdk包:
apt-get purge openjdk*
卸载 OpenJDK 相关包:
apt-get purge icedtea-* openjdk-*
检查所有 OpenJDK包是否都已卸载完毕:
dpkg --list | grep -i jdk
3.Ubantu环境下安装MySQL
查找安装包
apt list |grep “mysql-server”
安装mysql
sudo apt install mysql-server
查看一下MySQL状态:sudo systemctl status mysql
安装设置:sudo mysql_secure_installation
设置密码
进入到MySQL中:sudo mysql
使用alter user来修改密码:ALTER USER ‘root’@‘localhost’ IDENTIFIED WITH mysql_native_password BY 你的密码;
四.服务拆分
服务拆分原则:
微服务到底多小才算"微",这个在业界并没有明确的标准。微服务并不是越小越好,服务越小,微服务架构的优点和缺点都会越来越明显。
服务越小,微服务的独立性就会越来越高,但同时,微服务的数量也会越多,管理这些微服务的难度也会提高。所以服务拆分也要考虑场景。
还是以企业管理为例,企业中一个员工的工作内容与企业规模,项目规模等都有关系。在小公司,一个员工可能需要负责很多部门的事情,大公司的话,一个部门的工作可能需要多个员工来处理。
拆分微服务—般遵循如下原则:
1. 单⼀职责原则
单一职责原则原本是面向对象设计中的一个基本原则,它指的是一个类应该专注于单一功能。不要存在
多于一个导致类变更的原因。在微服务架构中,一个微服务也应该只负责一个功能或业务领域,每个服务应该有清晰的定义和边界,只关注自己的特定业务领域。
2.服务自治
服务自治是指每个微服务都应该具备高度自治的能力,即每个服务要能做到独立开发,独立测试,独立构建,独立部署,独立运行。
以上面的电商系统为例,每一个微服务应该有自己的存储,配置,在进行开发,构建,部署,运行和测试时,并不需要过多关注其他微服务的状态和数据。
3. 单向依赖
微服务之间需要做到单向依赖,严禁循环依赖,双向依赖
循环依赖:A -> B -> C ->A
双向依赖:A -> B,B -> A
五.工程搭建
1.父工程的搭建
-
先创建一个空项目:
-
删除src:
-
对pom文件进行配置:
DependencyManagement 和 Dependencies :
1.dependencies :将所依赖的jar直接加到项目中。子项目也会继承该依赖。
2.dependencyManagement :只是声明依赖,并不实现Jar包引入。如果子项目需要用到相关依赖,
需要显式声明。如果子项目没有指定具体版本,会从父项目中读取version。如果子项目中指定了版本
号,就会使用子项目中指定的jar版本。此外父工程的打包方式应该是pom,不是jar,这里需要手动
使用 packaging 来声明.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>org.example</groupId><artifactId>spring-cloud-demo</artifactId><version>1.0-SNAPSHOT</version><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>3.1.6</version><relativePath/> <!-- lookup parent from repository --></parent><properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target><java.version>17</java.version><mybatis.version>3.0.3</mybatis.version><mysql.version>8.0.33</mysql.version><spring-cloud.version>2022.0.3</spring-cloud.version></properties><dependencies><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency></dependencies><dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud.version}</version><type>pom</type><scope>import</scope></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>${mybatis.version}</version></dependency><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId><version>${mysql.version}</version></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter-test</artifactId><version>${mybatis.version}</version><scope>test</scope></dependency></dependencies></dependencyManagement></project>
2.子工程的搭建
- 在父工程中创建一个Module
- 创建子工程的空项目
- 子工程的POM文件配置:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.example</groupId><artifactId>spring-cloud-demo</artifactId><version>1.0-SNAPSHOT</version></parent><artifactId>order-service</artifactId><properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>com.mysql</groupId><artifactId>mysql-connector-j</artifactId></dependency><!--mybatis--><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>
- 手写启动类和配置文件:
六.远程调用
1.需求
当前写了两个简单的子工程,一个子工程是OrderService,一个子工程师ProductService,此时根据订单查询订单信息时,根据订单里产品ID,获取产品的详细信息:
2.实现
实现思路:order-service服务向product-service服务发送⼀个http请求,把得到的返回结果,和订单结
果融合在⼀起,返回给调用方。实现方式:采用Spring 提供的RestTemplate (实现http请求的方式,有很多,可点击此处)
-
定义RestTemplate
-
在OrderInfo中引入了ProductInfo,并且在OrderService的子工程的model包中引入了ProductInfo:
-
修改order-service中的OrderService
-
结果
3.RestTemplate
RestTemplate 是从 Spring3.0 开始支持的⼀个 HTTP 请求工具,它是⼀个同步的 REST API 客户端,提供了常见的REST请求方案的模版。
REST
REST(Representational State Transfer),表现层资源状态转移。REST是由HTTP的主要设计者Roy Fielding博士在2000年他的博士论文中提出来的⼀种软件架构风格。
主要有三个概念:
- 资源:网络上的所有事物都可以抽象为资源,每个资源都有一个唯一的资源标识符(URI)
- 表现层:资源的表现形式,比如文本作为资源,可以用txt格式表现,也可以通HTML,XML,JSON等格式来表现,甚至以二进制的格式表现。
- 状态转移:访问URI,也就是客户端和服务器的交互过程。客户端用到的手段,只能是HTTP议。这
个过程中,可能会涉及到数据状态的变化。比如对数据的增删改查,都是状态的转移。
REST是⼀种设计风格,指资源在网络中以某种表现形式进行状态转移。简单来说:REST描述的是在⽹络中Client和Server的⼀种交互形式,REST本身不实用,实用的是如何设计 RESTful API(REST风格的网络接口)
RESTful
REST 是一种设计风格,并没有⼀个明确的标准。满足这种设计风格的程序或接⼝我们称之RESTful(从
单词字⾯来看就是⼀个形容词)。所以RESTful API 就是满足REST架构风格的接⼝。
主要特征:
- 资源:资源可以是⼀个图片,音频,视频或者JSON格式等网络上的一个实体,除了一些二进制的资源外普通的文本资源更多以JSON为载体、面向用户的一组数据(通常从数据库中查询而得到)
- 统一接口:对资源的操作。比如获取,创建,修改和删除。这些操作正好对应HTTP协议提供的GET、POST、PUT和DELETE方法。换言而知,如果使⽤RESTful⻛格的接⼝,从接⼝上你可能只能定位其资源,但是无法知晓它具体进行了什么操作,需要具体了解其发生了什么操作动作要从其HTTP请求方法类型上进行判断
比如同⼀个的URL:
GET/blog/{blogId}:查询博客
DELETE/blog/{blogId}:删除博客
这些内容都是通过HTTP协议来呈现的。所以RESTful是基于HTTP协议的。
RestTemplate 是Spring提供,封装HTTP调用,并强制使用RESTful风格,它会处理HTTP连接和关闭,只需要使用者提供资源的地址和参数即可。
RESTful实践
RESTful风格的API 固然很好很规范,但大多数互联网公司并没有按照其规则来设计,因为REST是⼀种风格,而不是⼀种约束或规则,过于理想的RESTful API 会付出太多的成本。
RESTful API 缺点:
- 操作方式繁琐,RESTful API通常根据GET,POST,PUT,DELETE 来区分对资源的操作动作。但是HTTP Method 并不可直接见到,需要通过抓包等工具才能观察。如果把动作放在URL上反而更加直
观,更利于团队的理解和交流。 - 一些浏览器对GET,POST之外的请求支持不太友好,需要额外处理。
- 过分强调资源。而实际业务需求可能比较复杂,并不能单纯使用增删改查就能满足需求,强行使用
RESTful API会增加开发难度和成本。
所以,在实际开发中,如果业务需求和RESTfu API不太匹配或者很麻烦时,也可以不用RESTful API。如果使用场景和REST风格比较匹配,就可以采⽤RESTful API。
上述项目存在的问题
- 远程调用时,URL的IP和端口号是写死的(http://127.0.0.1:9090/product/),如果更换IP,需要修改代码 。调用方如何可以不依赖服务提供方的IP?
- 多机部署,如何分摊压力?
- 远程调用时,URL非常容易写错,而且复用性不高,如何优雅的实现远程调⽤
- 所有的服务都可以调用该接口,是否有风险?