一、SpringCloud简介

1、SpringCloud是什么

Spring Cloud是一系列框架的有序集合,这些框架为我们提供了分布式系统构建工具。

2、SpringCloud包含那些项目

项目项目名称服务注册于发现Alibaba Nacos、Netflix Eureka、Apache Zookper分布式配置中心Alibaba Nacos、Spring Cloud Config网关Spring Cloud Gateway、Netflix Zull限流熔断器Alibaba Sentinel、Netflix Hystrix、 Resilience4j服务调用RestTemplate、Open Feign、Dubbo Spring Cloud负载均衡Spring Cloud LoadBalancer、Netflix Ribbon消息总线Spring Cloud Bus……

3、SpringCloud版本选择

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

Spring Cloud Alibaba VersionSpring Cloud VersionSpring Boot Version2.1.4.RELEASESpring Cloud Greenwich.SR62.1.13.RELEASE

Spring Cloud Alibaba VersionSentinel VersionNacos VersionSeata Version2.1.4.RELEASE1.8.01.4.11.3.0

二、Nacos安装以及编译

1、下载源码

解压进入目录中进行maven编译

mvn clean install -DskipTests -Drat.skip=true -f pom.xml

注意:编译的时候可能需要你自己指定jdk版本,可以修改maven配置文件conf/settings.xml

jdk-1.8

true

1.8

1.8

1.8

1.8

2、源码单机启动

将jdk版本都设置为jdk8设置参数

-Dnacos.standalone=true

3、单机启动服务

下载nacos服务 https://github.com/alibaba/nacos/releases 解压进入bin目录 执行命令 startup.cmd -m standalone

5、修改startup.cmd

将MODE模式改为standalone,这样下次直接双击startup.cmd就可以了

三、Nacos服务领域模型

service->cluster-> instanc【之所以他会这样设置就是为了大的互联网公司,多集群垮机房提供了解决方案。但我们小公司一般都不需要这样。】

Namespace:实现环境隔离,默认值public

Group:不同的service可以组成一个Group,默认值Default-Group

Service:服务名称 Cluster:对指定的微服务虚拟划分,默认值Default

Instance:某个服务的具体实例

Nacos服务注册中心于发现的领域模型的最佳实践。

NameSpace: 是我们生产,开发和测试环境的隔离。测试访问测试,生产访问生产。

Group:比如说有一类服务。他们都是为了交易而服务的。比方说我们的订单,比方说我们的支付。这个在服务注册中心的场景中并不常用。

Service:下一个层级就是service,同一个group有多个service,再服务下面就是集群的概念:

Cluster:比方我们可以有北京的集群也可以有上海的集群。那这个集群的概念意义是什么? 我们可以设想这样的一个场景,比方阿里只在杭州部署一个淘宝的集群,那我们北方的人民去访问,是不是就会相对较慢,一般都会再南方和北方都设置两个集群。当北方人民访问的时候一般我们都访问北京这个集群的服务,其他的服务都会在北京的集群里面互相调用,而不会垮cluster进行访问,这样在同一个数据中心访问都是比较快的。这就是他的意义。

Instance: 这个就是实例,并且是多实例的,这样防止单点问题,从而实现高可用,当北京集群坏了,他会可以访问上海的集群。当一个实例挂掉,另一个实例会替代,当一个集群挂掉,另一个集群会替代上。这样就保证了高可用。很多公司宣传5个9或者4个9的可用,那么全年停机的时长不会超过固定的时长。

四、Nacos的使用

1、 正常使用http客户端调用

我们下订单的时候的调用:

1、讲解单独调用的图 2、然后运行一下这个demo 3、提出问题 4、进行改造

2、引入nacos

改造msb-stock

1、父pom引入依赖

com.alibaba.cloud

spring-cloud-starter-alibaba-nacos-discovery

2、启动注解

@EnableDiscoveryClient

@SpringBootApplication

public class StockApplication {

public static void main(String[] args) {

SpringApplication.run(StockApplication.class);

}

}

3、增加配置

spring:

cloud:

nacos:

discovery:

service: msb-stock

server-addr: localhost:8848

改造msb-order

2、启动注解:

@EnableDiscoveryClient

@SpringBootApplication

public class OrderApplication {

@Bean

public RestTemplate restTemplate(){

return new RestTemplate();

}

public static void main(String[] args) {

SpringApplication.run(OrderApplication.class);

}

}

3、增加配置

spring:

cloud:

nacos:

discovery:

service: msb-order

server-addr: localhost:8848

4、改造代码:

@GetMapping("/order/create")

public String createOrder(Integer productId,Integer userId){

String result = restTemplate.getForObject("http://msb-stock/stock/reduce//" + productId, String.class);

return "下单成功";

}

5、现在我们访问msb-stock ,但是restTemplate并不知道怎样调用

@GetMapping("/order/create")

public String createOrder(Integer productId,Integer userId){

// 此时restTemplate并不能识别msb-stock所以他不能进行调用

// RestTempLate调用需要一个负载均衡器 1、 获取msb-stock对应服务列表 2、选择一个去调用

// RestTemplate扩展点clientHttpRequestInterceptor

// 我们有个组件ribbon 实现了这个扩展点 LoadBalancerInterceptor

// 他做的事情就是将msb-stock:替换为:localhost:11001

String result = restTemplate.getForObject("http://msb-stock/stock/reduce//" + productId, String.class);

return "下单成功";

}

分析一下LoadBalancerInterceptor的拦截器Interceptor

我们可以进行如下改造:

@Autowired

LoadBalancerClient loadBalancerClient;

@Bean

public RestTemplate restTemplate(){

RestTemplate restTemplate = new RestTemplate();

restTemplate.setInterceptors(Collections.singletonList(new LoadBalancerInterceptor(loadBalancerClient)));

return restTemplate;

}

当然我们也可以进行如下改造:直接加入注解@LoadBalance后面我们会讲

@LoadBalanced

@Bean

public RestTemplate restTemplate(){

return new RestTemplate();

}

五、Nacos注册中心的原理

首先服务在启动的时候会将数据注册到注册中心,这样就服务只要启动就可以对外提供服务了, 那么同时他也要维持一个心跳,心跳的意义就是某个服务挂掉,我肯定让注册中心知道,如果服务挂了还没有告诉注册中心,那么注册中心会引导客户端调用挂掉的服务体验就不好了,所以注册中心重要的概念就是和我们的服务维持一个心跳,来实时的监听我们服务的状态,当服务挂掉就会将其从服务列表中踢掉,接下来肯定还有服务的调用者,他在调用服务之前一定会到注册中心拉取服务列表,获取可用的服务,并且还有一个定时任务来定时拉取服务列表,以保持服务列表的最新状态,其次还有更新的功能,这个功能就是当服务挂掉的时候通过心跳他会发现这服务不健康了,他会更新本地的服务注册表,同时将所有订阅这个注册表的服务进行更新。

六、 Nacos服务注册源码解析

6.1 源码方式打包

客户端源码中增加打包方式,将源码打入包中

org.apache.maven.plugins

maven-source-plugin

3.2.1

true

compile

jar

然后打包:

mvn install -DskipTests

6.2 入口

https://github.com/alibaba/nacos/tree/1.4.1

首先我们会把源码下载下来,我们会通过源码的方式进行启动, 你可以通过debug的方式进行运行来判断他的运行过程。

我们从源码的角度来分析一下:服务启动后他会上报到注册中心:

NacosNamingService 就是服务注册和发现相关的类,他就是在这里将当前启动的服务调用注册实例的方法,我们看一下这个方法干什么了?

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-V7vidLw9-1680575213440)(E:\BaiduNetdiskWorkspace\springcloud alibaba\img\image-20211221124947544.png)]

他就是拼接了一些参数发送http请求,到达服务注册中心进行发现,请求的就是这个路径:

好这就是对应的路径,我们回到官方文档的指南当中

https://nacos.io/zh-cn/docs/open-api.html

好,按照我们讲到这里就不用再往里面看了,我们可以点进去看一下,

他真正的调用给你是在这里。

在这里进行调用

好哪有同学问你怎么知道断点就达到这里,那我们看一下怎样查看源码的启动的路径,我们看一下我们订单微服务的路径,我们要集成nacos的服务发现功能,我们要引入我们的discovery的包,他是一个starter,前面我们学过springboot我们知道任何starter里面一定有个spring.factories,作为一个入口

这里面动态加载的类很多,NacosServiceRegistryAutoConfiguration 从这名字我们能发现他是一个nacos服务注册的自动配置类,

这里面实现了三个类,我们看一下这个类NacosAUtoServiceRegistration

自动注册类,我们可以看一下他的集成关系,是一个ApplicationListener spring启动完成后都会发送一个消息,applicaitonListener就是通过监听这个消息然后进行执行的。所以我们知道下一步我们应该怎么看:

所以查看他的抽象类。

查看onApplicationEvent方法:这样在服务发送完就会发送这样一个消息,收到这个消息就会调用这个bind方法

这里有个if return 我们就直接跳过,这一定是分支代码,像这样的分支代码我们就不要看,第一 次要看主线,所以我们直接看这里的start方法,如果后面这里没有对应的代码逻辑我们可以进入这个分支来看。 好,像这样start, begin,init,register方法都是很重要的方法,我们一定要进去看

第一个if就不用看,第二个if需要看,因为后面就没有逻辑了你看这个register(),应该就是这个方法,因为你就是查看注册的流程。

这里需要你知道SpringBoot自动装配的基本知识,其次要知道Spring启动发现的 基本知识。

6.3 服务注册

Nacos高并发支撑异步任务与内存队列剖析

刚才是在服务提供者上面讲的内容,现在我们服务注册中心来看一下

请求的是instance实例:这就是一个springmvc的controller,所有我们可以全文搜索 Controller,我们是instance实例吧,所以我们这里InstanceController

那之前我们用的是post请求所以我们查看post方法,这里有delete,update…,他这里是什么风格? restFul

我们发现里面没有对应的DefaultGroup,在服务注册和发现的情况下这个group是不经常用的。你用的话只是自己的规范和方便管理的。在服务注册和发现中源码中都没有用。,命名空间,服务名,然后将我们参数转化为实例。这就我们服务模型中的三层模型。

那我们看一下他的注册实例里面做了什么? 这里面我们注意我们是注册instance,我们就围绕着他,进行分析,是不是就来到addInstance了

createEmptyService

1、获取service 初次获取一定为空,我们可以进去分析一下

这里就是注册表,我们前面说过nacos服务领域模型【可以参考图】,这个map就是对应的注册表

这里面设置服务和初始化

服务初始化:心跳

看这里是个scheduleNamingHealth是一个定时任务,我们只需要看一下task任务就可以

task任务我们需要看一下run方法:

在这里我们看是获取所有的实例【可以点进去看一下】

当前时间 - 上次心跳时间 间隔超过15秒 则将实例设置为非健康, 当超过30秒没有收到心跳就直接剔除

好,我们回来,这里名字起的特别好,createEmtyService,是创建一个空服务,后面我们的实例,是不是还会注册到里面,

我们可以看一下服务模型,和我们以前说过的一样

命名空间 ,cluster 集群概念

集群中对应的实例。

我们看一下addinstance

构建对应的key:

String key = KeyBuilder.buildInstanceListKey(namespaceId, serviceName, ephemeral);

//获取注册实例的IP端口列表

List instanceList = addIpAddresses(service, ephemeral, ips);

我们进入简单的看一下,我们发现这个add,remove,这里就是新增和移除实例

我们主要出里这写注册进来的ips,那我们就点击ips,高亮来显示看看,然后他会进行循环instance,这里我们可以看到如果他是移除就从map里面移除出去,如果是新增就在instanceMap中新增一下,最后将期返回。

现类,我们可以猜测一下,或者debug进去,当然这个类,我们点击一下,在声明的地方

它指定了名称:

好,我们全文搜索看一下:

我们知道前面说过ephemeral是true所以选择第一个: 有疑问:

我们应该调用EphemeralConsistencyService对应的put方法。但是EphemeralConsistencyService只是一个接口,我们应该调用对应的实现实例。

我们看一下他的onput方法。

现在放到队列中:

这里面就是把核心的请求放到blockquene里面,也就是一个阻塞队列中

整个注册的过程就这么简单,一个请求过来,最终将服务注册的请求,放到我们的阻塞队列当中,放到则色队列之后,整个阻塞队列就返回了。那放到阻塞队列之后,哪里有访问这个阻塞队列。

大家注意这个Notifier是一个线程,老师交大家一个技巧:如果遇到一个线程就需要看他的run方法因为run方法才是他 真正执行代码的地方。

在这里进行死循环进行数据处理,不断的处理客户端注册的信息,丢进来就实现后面的异步注册信息,

这个线程会一直在转,一直运行,如果他挂了那说明整个服务就挂掉了,好,你看着里面的异常也吃掉了,所以一直会运行,如果没有数据他会阻塞,阻塞会让出cpu

注册表结构的分析:

首先当他是个change的时候,我们就进入onChange,他是个服务所以我们进入他的service里面去看:

这里面就不用看了,先看权重,权重大于多少的时候设置最大值,权重小于多少的时候设置一个最小值。然后就是核心的方法updateIP

那这个updateIPs是做什么呢? 做的就是我遍历我所有要注册的实例,然后就放到我们的clusterMap里面

那到这里大家可能就有疑问了,那什么时候启动这个线程,来实时监听我们消息的阻塞队列呢? 教大家如何找一下这个方法,我们现在看着个类叫Notifier,因为他本身就是一个线程,他会丢到一个线程池中进行运行,我们看一下他究竟是在哪里实例化的,

我们看到这个方法:这个注解就是当你的spring的一个类进行初始化之后进行调用的,那我们看一下这个init方法到底是做了什么

是一个Scheduled线程池:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UNf6cAYm-1680575213470)(E:\BaiduNetdiskWorkspace\springcloud alibaba\img\image-20211222222903941.png)]

也就是在对象初始化的时候就进行启动一个线程池,去运行notifier对应的方法。这个run方法就是这样run的。启动后就会实时监听异步队列。这样写的好处,就是将写和处理完全隔离了。通过监听高性能的内存队列,来处理这个事情,他这样的好处,1、提高性能

6.4 发送心跳机制

1、 客户端

回到客户端查看,他进行心跳机制的处理

发送心跳后,在finally里面设置延迟5秒执行,这样达到的效果就是每隔5秒执行一次心跳

2、服务端

来到InstanceController类中的beat方法。里面通过参数获取对应的实例,如果没有对应的实例则需要注册,重点我们看他是怎样处理心跳的。

=

服务端怎样处理心跳的,他启动一个线程来处理我们的心跳。

我们查看ClientBeanProcessor的Run方法:

这里我们重点看一下他这里是循环所有的实例,然后设置对应的时间。这里于上面我们处理检查心跳信息的处理对应上了。(可以参考我们画的图)

6.5、查询服务列表

1、客户端

1.1 找出获取服务列表的请求方法

客户端有个请求hostReactor.getServiceInfo获取对应的所有服务实例,

这里启动一个定时任务来定时获取数据,后面们研究Updatetask()的时候我们仔细研究

1.2 分析堆栈信息

这说明我们spring容器刷新容器的时候来获取对应的服务列表

1.3 获取服服务列表

从注册中心中获取对应的数据

1.4 定时任务获取对应的数据

2、服务端

发送请求后调用doSrvIpxt这个核心代码,前面的操作都是一些参数的解析。

返回的一些实例列表,ephemeralInstances 临时实例列表 persistentInstances持久化临时列表

七、集群搭建

1、解压Nacos

解压Nacos,复制三份

2、配置数据库

具体位置在nacos目录下的conf中,这里的操作和之前是一样的,我们可以直接打开这个文件然后拷贝到数据库中执行,当然也是要创建数据库使用数据库然后在复制脚本内容,执行即可。

create database nacos_config;

use nacos_config;

3、修改application.properties配置文件

修改每个服务数据库链接

spring.datasource.platform=mysql

db.num=1

db.url.0=jdbc:mysql://127.0.0.1:3306/nacos_config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&serverTimezone=UTC

db.user=root

db.password=123456

修改每个服务端口

server.port=8848

4、修改集群配置文件

将cluster.conf.example 改为 cluster.conf,并添加对应服务集群Ip:port,

其他文件夹也要修改

5、集群启动

D:\toolsDev\springalibaba\nacos cluster\nacos-8848\bin\startup.cmd -m cluster

D:\toolsDev\springalibaba\nacos cluster\nacos-8868\bin\startup.cmd -m cluster

D:\toolsDev\springalibaba\nacos cluster\nacos-8888\bin\startup.cmd -m cluster

6、浏览器访问一下Nacos

7、安装Nginx

修改nginx.conf

worker_processes 1;

events {

worker_connections 1024;

}

stream {

upstream nacos {

server 192.168.1.11:8848;

server 192.168.1.11:8868;

server 192.168.1.11:8888;

}

server {

listen 81;

proxy_pass nacos;

}

}

启动nginx

start nginx.exe

重新加载

nginx.exe -s reload

8、进行访问

http://localhost:8848/nacos

9、项目链接

参考文章

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: