微服务架构介绍

1)单体架构

1.1 什么是单体架构

单体架构

一个单jar包或者一个单war包包含了所有的功能模块,这种就称为 单体架构。

1.2 单体架构优缺点

优点:

开发、测试、部署都简单,如果出现了BUG和错误,找到错误的地方会很简单

缺点:

  • 所有的功能模块都是集成在一个系统,随着业务的增加代码变得越来越复杂,东西都耦合在一起了且开发人员水平参差不齐,很可能改一个BUG就出现更多BUG。
  • 单体架构代码非常复杂的话,部署起来速度会比较慢
  • 扩展设备的代价很高,如果订单业务模块比较吃CPU,那么我们为订单微服务更换性能更强的CPU,而仓库模块比较吃IO,我们可以更换性能更高的硬盘,但是如果是单体架构,只能 CPU和硬盘都一起更换

2)微服务架构

1.1 微服务定义

微服务就是将一个单机应用拆分成多个小服务,每个小服务之间相互解耦,都有自己的业务边界,可以提供特定的功能,每个服务都可以单独部署。

如:我们把单机架构拆分成微服务架构,把订单业务 、支付业务、仓库业务、营销 业务都拆成自己一个一个独立的小服务。

微服务

SOA架构和微服务架构有些相似,单兵不一样,SOA架构强调的是异构系统之间的通信和解耦,而微服务架构强调的是按照业务边界进行拆分。

微服务和微服务架构的区别

微服务是指按业务边界划分后的每个业务模块服务,而微服务架构指的是 多个微服务模块组合起来对外提供完整的服务。

1.2 微服务架构优缺点

优点

  • 每个服务之间相互解耦,如果某个服务挂了,一般不会影响到其他服务

  • 开发效率提高,每个团队可以专注一个小服务的开发,只需要了解该服务的相关逻辑即可

  • 每个小服务都可以水平伸缩部署,根据需要去伸缩部署,可扩展性非常大

缺点

  • 增加了运维人员的工作量,单机部署只需要一个jar包,而微服务需要大量的jar包

  • 服务之间的互相调用,增加了通信成本和延时

  • 会出现数据一致性问题,需要通过分布式事务来解决

  • 微服务监控,链路追踪都会变得麻烦

3)Spring Cloud 微服务技术栈

Spring Cloud是分布式微服务架构的解决方案,是多种微服务架构的集合体,里面包含了很多种微服务架构解决方案。

官网: https://spring.io/projects/spring-cloud

中文文档: https://www.springcloud.cc/

Spring Cloud中国社区:http://springcloud.cn/

image-20230331161849302

image-20230331161928053

4)Spring Cloud Alibaba技术栈

Alibaba也提供了一套微服务解决方案,包含了分布式微服务的必需组件。

相较于Spring Cloud Netflix,Spring Cloud Alibaba提供了更多的一个功能组件:

image-20230331162147271

1.1 Alibaba 开源组件

Nacos:一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。

Sentinel:把流量作为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。

RocketMQ:开源的分布式消息系统,基于高可用分布式集群技术,提供低延时的、高可靠的消息发布与订阅服务。

Dubbo:在国内应用非常广泛的一款高性能 Java RPC 框架。

Seata:阿里巴巴开源产品,一个易于使用的高性能微服务分布式事务解决方案。

Arthas:开源的Java动态追踪工具,基于字节码增强技术,功能非常强大。

1.2 Alibaba 商用组件

Alibaba Cloud ACM:一款在分布式架构环境中对应用配置进行集中管理和推送的应用配置中心产品。

Alibaba Cloud OSS:阿里云对象存储服务(Object Storage Service,简称 OSS),是阿里云提供的云存储服务。

Alibaba Cloud SchedulerX:阿里中间件团队开发的一款分布式任务调度产品,提供秒级、精准的定时(基于 Cron 表达式)任务调度服务。

1.3 Spring Cloud Alibaba架构图

image-20230331162414349

所有的微服务都要注册到Nacos中,当请求进入nginx后 进行Spring Sercuity Oauth2.0鉴权,随后经过gateway网关,gateway网关经过负载均衡或限流后,转发给对应的微服务。

而Seata作为分布式事务,起到了 事务管理的作用,确保数据的唯一性,skywallking 作为链路追踪,用于监控链上的微服务模块状态。

微服务之间通过 open feign模块相互调用。

1.4 Spring Cloud Alibaba版本选择

网址:https://github.com/alibaba/spring-cloud-alibaba/wiki/%E7%89%88%E6%9C%AC%E8%AF%B4%E6%98%8E

image-20230331162845149

当我们选定了Spring Cloud Alibaba版本后,对应的Sentinel 和nacos以及组件 建议都按照官网的要求使用指定的版本,避免出现一些不可预料的意外,因为这些版本都是官网测试过后觉得稳定的版本。

Nacos 微服务注册中心

1)注册中心

1.1 注册中心的作用

主要作用 服务注册与服务发现。

服务注册

  • 将某个模块的IP和端口信息注册到 公共的组件中(注册中心)。

服务发现

  • 不论是新增模块还是删减模块都能自动被其他调用者发现。

1.2 注册中心实现思路

image-20230331200527463

注册接口

  • 服务通过注册接口 把服务的信息(IP和PORT等)注册到注册中心。

注销接口

  • 服务通过 注销接口 在注册中心中 注销掉该服务。

心跳接口

  • 服务开启定时任务,定时往注册中心发送心跳检测,注册中心如果没有收到心跳检测的话,就会判定服务下线,从而注销该服务。

服务获取接口

  • 服务端定时拉取注册中心的节点 缓存到本地,在远程调用时通过 负载均衡器进行调用。

2)Nacos

Nacos是Alibaba提供的一个应用动态服务发现、配置管理、服务管理平台,可以快速的帮我们发现、配置、管理微服务。

2.1 Nacos优点

易用:简单的数据模型,标准的 restfulAPI,易用的控制台,丰富的使用文档。

稳定:99.9% 高可用,脱胎于历经阿里巴巴 10 年生产验证的内部产品,支持具有数百万服务的大规模场景,具备企业级 SLA 的开源产品。

实时:数据变更毫秒级推送生效;1w 级,SLA 承诺 1w 实例上下线 1s,99.9% 推送完成;10w 级,SLA 承诺 1w 实例上下线 3s,99.9% 推送完成;100w 级别,SLA 承诺 1w 实例上下线 9s 99.9% 推送完成。

规模:十万级服务/配置,百万级连接,具备强大扩展性。

2.2 Nacos注册中心核心概念

image-20230331210533930

服务 (Service)

服务是指一个对外提供服务的应用。

服务注册中心 (Service Registry)

服务注册中心,它是服务及其实例和元数据的数据库。服务实例在启动时注册到服务注册表,并在关闭时注销。服务和路由器的客户端查询服务注册表以查找服务的可用实例。服务注册中心可能会调用服务实例的健康检查 API(心跳检测)来验证它是否能够处理请求。

服务元数据 (Service Metadata)

服务元数据是指包括服务端点(endpoints)、服务标签、服务版本号、服务实例权重、路由规则、安全策略等描述服务的数据。

服务提供方 (Service Provider)

是指提供可复用和可调用服务的应用方。

服务消费方 (Service Consumer)

是指会发起对某个服务调用的应用方。

2.3 Nacos注册中心核心功能

服务注册:Nacos Client会通过发送REST请求的方式向Nacos Server注册自己的服务,提供自身的元数据,比如ip地址、端口等信息。Nacos Server接收到注册请求后,就会把这些元数据信息存储在一个双层的内存Map中。

服务心跳:在服务注册后,Nacos Client会维护一个定时心跳来持续通知Nacos Server,说明服务一直处于可用状态,防止被剔除。默认5s发送一次心跳。

服务同步:Nacos Server集群之间会互相同步服务实例,用来保证服务信息的一致性。

服务发现:服务消费者(Nacos Client)在调用服务提供者的服务时,会发送一个REST请求给Nacos Server,获取上面注册的服务清单,并且缓存在Nacos Client本地,同时会在Nacos Client本地开启一个定时任务定时拉取服务端最新的注册表信息更新到本地缓存。

服务健康检查:Nacos Server会开启一个定时任务用来检查注册服务实例的健康情况

  • 对于超过15s没有收到客户端心跳的实例会将它的healthy属性置为false(客户端发现时会看不到该实例)
  • 如果某个实例超过30秒没有收到心跳,直接剔除该实例(被剔除的实例如果恢复发送心跳则会重新注册到Nacos Server中)

Nacos 微服务注册中心搭建

官网网站:https://nacos.io/zh-cn/index.html

Nacos2.1.0安装包:https://files.javaxing.com/nacos/nacos-server-2.1.0.tar.gz

1)单机模式

解压并进入nacos/bin目录,以单机模式启动nacos

1
2
3
4
[root@S1 bin]# tar -xvf nacos-server-2.1.0.tar.gz
[root@S1 ~]# cd nacos
# 以单机模式启动nacos
[root@S1 bin]# ./startup.sh ‐m standalone

除了可以通过命令的形式指定为单机模式启动,也可以修改startup.sh的MODE参数为:standalone

image-20230401102631210

启动成功后监听日志文件

1
[root@S1 bin]# tail -f  /root/nacos/logs/start.out

启动成功后,访问nacos的管理端:http://10.211.55.12:8848/nacos,默认用户名和密码都是nacos

image-20230401102804898

2)集群模式

2.1 环境准备

环境要求

  • 安装JDK1.8或以上版本
  • 生产环境建议2核4G及以上配置

nacos集群示意图

注意:如果要搭建伪集群的话(一台服务器上跑多个nacos节点),端口一定不可以连续,如 8848,8849,8850,会导致端口冲突,因为Nacos2.x版本新增了gRPC通信方式,会新增2个端口,而新增的端口会在主端口 如 8848上进行一定的偏移。

gRPC端口号:

9848:客户端gRPC请求服务端端口,用于客户端向服务端发起连接和请求

9849:服务端gRPC请求服务端端口,用于服务间同步等

2.2 配置外部数据源

nacos启动时默认会启用内置数据源,但是如果我们部署nacos集群的话,就必须使用外部数据源,才能确保 集群中的节点元数据一致。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[root@S1 nacos]# vim conf/application.properties


spring.datasource.platform=mysql

### Count of DB:
db.num=1

### Connect URL of DB:
db.url.0=jdbc:mysql://10.211.55.12:3306/nacos?characterEncoding=utf8&connectTimm
eout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serr
verTimezone=UTC
db.user.0=root
db.password.0=123123
image-20230401110232063

2.3 配置集群参数

1
[root@S1 conf]# mv cluster.conf.example cluster.conf

将cluster.conf.example改为cluster.conf,并在文件里面配置 集群节点

1
2
3
4
5
6
7
# 编辑集群配置文件
[root@S1 conf]# vim cluster.conf

# 配置集群中的节点IP:PORT
10.211.55.12:8848
10.211.55.17:8848
10.211.55.18:8848

注意:不要使用localhost和127.0.0.1,否则会出错

2.4 创建nacos数据库

在2.2 我们配置了外部数据源,所以我们还需要创建一个nacos数据库来存放元数据。

SQL脚本:https://files.javaxing.com/nacos/nacos.sql

image-20230401111014713

2.5 在所有集群节点上启动nacos

1
[root@S1 bin]# ./startup.sh

启动成功

image-20230401111231817

3)Spring Cloud Alibaba集成Nacos

选定了Spring Cloud Alibaba版本后,对应的Sentinel 和nacos以及组件 建议都按照官网的要求使用指定的版本,避免出现一些不可预料的意外。

这里我们所使用的对应的版本信息如下:

Spring Cloud Alibaba Version Spring Cloud Version Spring Boot Version
2.2.8.RELEASE Spring Cloud Hoxton.SR12 2.3.12.RELEASE

3.1 项目结构

image-20230401124454292

父pom配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
<?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.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.12.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>

<groupId>com.javaxing</groupId>
<artifactId>NacosServer</artifactId>
<version>1.0-SNAPSHOT</version>

<packaging>pom</packaging>


<properties>
<spring-cloud.version>Hoxton.SR12</spring-cloud.version>
<spring-cloud-alibaba.version>2.2.8.RELEASE</spring-cloud-alibaba.version>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- 引入nacos依赖-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</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>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>

</dependencies>
</dependencyManagement>


<modules>
<module>SpringBootNacos</module>
</modules>

</project>

子模块xml配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<!-- 指定父类工程-->
<groupId>com.javaxing</groupId>
<artifactId>NacosServer</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>

<groupId>com.javaxing</groupId>
<artifactId>SpringBootNacos</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>SpringBootNacos</name>
<description>SpringBootNacos</description>


<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

</project>

3.2 配置nacos注册中心

1
2
3
4
5
6
7
8
9
server:
port: 8080
spring:
application:
name: xingmall-user
cloud:
nacos:
discovery:
server-addr: 10.211.55.12:8848

Nacos Starter更多的配置参数

配置项 Key 默认值 说明
服务端地址 spring.cloud.nacos.discovery.server-addr Nacos Server 启动监听的ip地址和端口
服务名 spring.cloud.nacos.discovery.service ${spring.application.name} 给当前的服务命名
服务分组 spring.cloud.nacos.discovery.group DEFAULT_GROUP 设置服务所处的分组
权重 spring.cloud.nacos.discovery.weight 1 取值范围 1 到 100,数值越大,权重越大
网卡名 spring.cloud.nacos.discovery.network-interface 当IP未配置时,注册的IP为此网卡所对应的IP地址,如果此项也未配置,则默认取第一块网卡的地址
注册的IP地址 spring.cloud.nacos.discovery.ip 优先级最高
注册的端口 spring.cloud.nacos.discovery.port -1 默认情况下不用配置,会自动探测
命名空间 spring.cloud.nacos.discovery.namespace 常用场景之一是不同环境的注册的区分隔离,例如开发测试环境和生产环境的资源(如配置、服务)隔离等。
AccessKey spring.cloud.nacos.discovery.access-key 当要上阿里云时,阿里云上面的一个云账号名
SecretKey spring.cloud.nacos.discovery.secret-key 当要上阿里云时,阿里云上面的一个云账号密码
Metadata spring.cloud.nacos.discovery.metadata 使用Map格式配置,用户可以根据自己的需要自定义一些和服务相关的元数据信息
日志文件名 spring.cloud.nacos.discovery.log-name
集群 spring.cloud.nacos.discovery.cluster-name DEFAULT 配置成Nacos集群名称
接入点 spring.cloud.nacos.discovery.enpoint UTF-8 地域的某个服务的入口域名,通过此域名可以动态地拿到服务端地址
是否集成Ribbon ribbon.nacos.enabled true 一般都设置成true即可
是否开启Nacos Watch spring.cloud.nacos.discovery.watch.enabled true 可以设置成false来关闭 watch
注册的IP地址类型 spring.cloud.nacos.discovery.ip-type IPv4 可以配置IPv4和IPv6两种类型

3.3 启动服务注册到nacos

image-20230401125209477

启动成功后,我们可以在Web管理界面中 看到2个服务均以注册成功。

4)Nacos分层存储模型

image-20230401125748140

Nacos 分为服务-集群-实例的三层模型,这种模型可以满足服务在所有场景下的数据存储和管理。

服务

  • 健康检查开关
  • 元数据
  • 路由机制
  • 保护阈值

集群

  • 健康检查模式
  • 元数据
  • 同步机制

实例

  • IP
  • 端口
  • 权重
  • 健康状态
  • 下线状态
  • 元数据
  • 响应时间

5)隔离模型

5.1 服务隔离

image-20230401130203840

服务逻辑隔离分为三层:

Namespace:公共命名空间 public

不同命名空间的节点是完全隔离开的,相互之间无法访问。一般用于不同环境的隔离,如 开发测试环境(dev)和生产环境(prod)的隔离。

image-20230401130324617

Group:默认分组 DEFAULT_GROUP

不同的服务可以归类到同一个分组中,分组也能起到隔离的作用,不同的分组之间无法相互访问。

image-20230401130401038

Service

5.2 隔离测试

我们把xingmall-order服务注册到 dev的命名空间中。

新建命名空间

image-20230401131026705

image-20230401131039839

修改配置文件

1
2
3
4
5
6
7
8
9
10
11
server:
port: 8081
spring:
application:
name: xingmall-order
cloud:
nacos:
discovery:
server-addr: 10.211.55.12:8848
# 指定命名空间
namespace: 37731914-6c28-4265-a090-7a9391ed843d

6)临时实例和持久化实例

临时实例

临时实例只是临时存在于注册中心中,会在服务下线或不可用时被注册中心剔除。临时实例会与注册中心保持心跳,注册中心会在⼀段时间没有收到来自客户端的心跳后会将实例设置为不健康,然后在⼀段时间后进行剔除。

持久化实例

持久化实例在被删除之前会永久的存在于注册中心,且有可能并不知道注册中心存在,不会主动向注册中心上报心跳,那么这个时候就需要注册中心主动进行探活。

什么时候用临时实例什么时候用持久化实例?

在大型公司中,两种模式一般都会混合使用,在一些基础组件中 如 数据库、缓存,这种不会上报心跳的,我们就采用 持久化实例注册。

对于一些会主动上报心跳的服务,如 微服务等,我们就使用 临时实例动态注册。

默认情况下注册到Nacos中都是临时实例,如果我们想修改成持久化实例可以通过以下配置:

1
spring.cloud.nacos.discovery.ephemeral: false

loadBalanced必须在Bean完全初始化后才可以生效,所以如果需要使用到带有loadBalanced的restTemplate,就必须要等Bean都初始化后再使用。

微服务刚启动起来后,第一次调用都会比较慢,如ribbom组件,所以在微服务启动时进行 小数据的预热,让他初始化好线程和组件。

延迟注册,避免服务端还没有完全启动成功,然后有数据就请求进来导致报错的情况。

临时实例:微服务

持久实例:数据库等