前言
本章内容是关于SpringCloud概述以及(Nacos)注册中心和配置中心
一、SpringCloud
1、 SpringCloud-------背景
随着互联网的快速发展,单体架构的软件系统已经不能够满足6.18以及双十一这样的高并发,大流量的性能要求;系统架构逐步走上了分布式 ,但是分布式系统天生就复杂,不像单体应用那样把几个框架整合起来就可以了,因此各大互联网公司都投入技术力量研发自己的基础设施,比如比较有名的:阿里的开源项目dubbo和Netflix开发的一系列服务框架;在这种“百花齐放”、重复造轮子的状况下,必然要出现一种统一的标准来简化分布式系统的开发,Spring Cloud就应运而生。
2、系统架构的演变
2.1、单体框架
在企业发展初期,一般公司的网站流量小,单体框架应用就可以满足需求,将所有的功能打包成一个服务,这样也能减少开发,部署和后期维护的成本。
比如,大家都很熟悉的电商系统,里面涉及的业务主要有:用户管理、商品管理、订单管理、支付管理、库存管理、物流管理等等模块,初期我们会将所有模块写到一个Web项目中,然后统一部署到一台tomcat服务器上。
单体框架存在的问题:
- 代码耦合:代码之间的耦合太大,依赖关系不清晰,代码修改的难度大,每次修改代码都心惊胆战的;
- 迭代困难:每次某个功能要变更或者修复bug都需要重新部署整个应用,随着代码的增多,构建、测试和部署的时间也会增多;
- 扩展受限:单体应用只能作为一个整体进行扩展,无法根据业务模块的需要单独扩展
- 技术债务:随着时间的推移,需求的变更和开发人员的更迭,会形成应用程序的技术债务,并且形成一种“只要代码能跑起来就不动代码”,技术债务会越来越多
2.2分布式架构
随着企业业务的发展,单体架构已经不足以支撑义务的发展,于是企业将单体应用部署多份,分别放在不同的服务器上。但是,此时会发现不是所有的模块都会有比较大的访问量。如果想针对项目中的某些模块进行优化和性能提升,此时对于单体应用来说,是做不到的。于是乎,分布式架构诞生了。
分布式架构,就是将原来一个项目应用进行拆分,将其拆分为互不想干的几个应用,以此来提升系统的整体性能。
同样以电商系统为例,在分布式架构下,我们可以将整个电商项目拆分为:电商交易系统、后台管理系统、CMS管理系统等。
但是分布式架构也存在很大的问题,像在电商项目下有电商交易系统和后台管理系统中都用用户管理,就需要写两次同样的业务,代码会过于重复,很显著也不是我们想要的效果,因此就演变出来SOA框架
2.3、SOA框架
我们将系统演变为分布式架构之后,当业务越来越多,重复编写的业务代码就会越来越多。此时,我们需要将重复的代码抽象出来,形成统一的服务供其他系统或者业务模块来进行调用。此时,系统就会演变为SOA架构。
在SOA架构中,我们会将系统整体拆分为服务层和表现层。服务层封装了具体的业务逻辑供表现层调用,表现层则负责处理与页面的交互操作。
当部署的服务越来越多,就会出现服务集群地址硬编码的问题,此时,我们就需要增加一个
注册中心来解决各个服务之间的注册与发现。(我用的是zookeeper注册中心)
听着SOA框架就很完美,但是呢还是有不足的地方,存在的问题:
-
服务提供方与调用方接口耦合度较高
-
抽取服务的粒度较大
通俗的讲就是:一个电商项目分成多个系统,系统和系统之间有的业务需要调用同一个服务,同样就会引发一个问题,如果其中一个服务挂了,那么整个项目也会挂掉
2.4、微服务
随着业务的发展,我们在SOA架构的基础上进一步扩展,将其彻底拆分为一个个小的可以独立部署的微服务。
微服务架构特征:
- - 隔离性强:服务调用的隔离、容错、避免出现级联问题 (服务和服务之间有隔离性,一个服务挂掉,不会影响其他服务的正常运行,修复是只需要针对出错的服务)
- - 面向服务:微服务对外暴露Restful等轻量协议的接口
- - 单一职责:微服务拆分粒度更小,每一个服务都对应唯一的业务能力,做到单一职责,避免重复业务开发
- - 自治:独立打包、部署和升级,小团队的交付周期将缩短,运维成本也将大幅度下降
3、什么是SpringCloud?
Spring Cloud是一系列框架的有序集合如服务发现注册、配置中心、消息总线、负载均衡、熔断器、数据监控等。
SpringCloud是一套微服务开发的全家桶;Spring没有重复造轮子,只是基于springboot将其他公司(Netflix)的服务框架组合起来
通俗的说就是Springboot整合了Netflix众多组件形成了SpringCloud!
4、Spring Cloud Alibaba概述
4.1、为什么使用Spring Cloud Alibaba?什么是 Spring Cloud Alibaba?
因为在2020年Netflix众多组件停止维护(闭源了),所以急需其他的一些替代产品,也就是spring cloud alibaba,目前正处于蓬勃发展的态式,马老师左手双十一,右手阿里开源组件,不仅占据了程序员的购物车,还要攻占大家的开发工具 。
Spring Cloud Alibaba 就是 Springboot加上了alibaba开发的众多组件整合取来形成的Spring Cloud Alibaba
4.2、Spring Boot和Spring Cloud的版本号说明
Spring Cloud Alibaba Version | Spring Cloud Version | Spring Boot Version |
---|---|---|
2021.0.1.0 | Spring Cloud 2021.0.1 | 2.6.3 |
2.2.7.RELEASE | Spring Cloud Hoxton.SR12 | 2.3.12.RELEASE |
2021.1 | Spring Cloud 2020.0.1 | 2.4.2 |
2.2.6.RELEASE | Spring Cloud Hoxton.SR9 | 2.3.2.RELEASE |
2.1.4.RELEASE | Spring Cloud Greenwich.SR6 | 2.1.13.RELEASE |
2.2.1.RELEASE | Spring Cloud Hoxton.SR3 | 2.2.5.RELEASE |
2.2.0.RELEASE | Spring Cloud Hoxton.RELEASE | 2.2.X.RELEASE |
2.1.2.RELEASE | Spring Cloud Greenwich | 2.1.X.RELEASE |
2.0.4.RELEASE(停止维护,建议升级) | Spring Cloud Finchley | 2.0.X.RELEASE |
1.5.1.RELEASE(停止维护,建议升级) | Spring Cloud Edgware | 1.5.X.RELEASE |
二、Nacos的概述和安装
2.1.Nacos简介
2.1.1.为什么叫Nacos
前面四个字母分别表示 Naming 和 Configuration 的前两个字母, 最后一个s 为 Service
2.1.2.Nacos是什么
Nacos 是阿里巴巴的新开源项目,其核心定位是 “一个更易于帮助构建云原生应用的集注册中心与配置中心于一体的管理平台”。
2.2.Nacos安装和启动
2.2.1.下载
下载地址:https://github.com/alibaba/nacos/tags
2.2.2.安装
解压安装包:
[root@localhost ~]# cd /usr/upload [root@localhost upload]# tar -zxvf nacos-server-1.4.1.tar.gz -C /usr/local
2.2.3.启动和关闭
启动:
[root@localhost local]# cd nacos/bin/ [root@localhost bin]# ./startup.sh -m standalone #非集群模式启动 ... ... nacos is starting with standalone nacos is starting,you can check the /usr/java/nacos/logs/start.out
关闭:
[root@localhost bin]# ./shutdown.sh The nacosServer(3543) is running... Send shutdown request to nacosServer(3543) OK [root@localhost bin]
2.2.4.测试
浏览器访问:http://192.168.209.129:8848/nacos,默认用户名/密码为: nacos/nacos
3.Nacos注册中心
3.1.什么是Nacos注册中心
注册中心就是用于服务提供者注册服务、服务调用者从中拉取服务列表然后采用负载均衡策略(如Ribbon)从列表中选出一个服务,从而完成请求调用。
注册中心主要有三部分组成:
Nacos-Server:注册中心
提供服务的注册和发现。
Nacos-Provider:服务提供方
把自身的服务实例注册到 Nacos Server 中
Nacos-Consumer:服务调用方
通过 Nacos Server 获取服务列表,消费服务。
3.2、为什么要使用注册中心?
①地址硬编码
②不能负载均衡
4、准备一个案例,根据案例分析
创建一个项目:springclou_parent
项目结构:
springcloud_common:存放公共的实体类
nacos_provider: 是服务的提供者
nacos_consumer:是服务的消费者也就调用者
nacos_config 配置中心
4.1、springcloud_parent,父工程pom.xml
~指定项目的编码和JDK版本
<properties>
<!-- 项目源码及编译输出的编码 -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<!-- 项目编译JDK版本 -->
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
所需的依赖
<dependencies>
<!--Spring Boot-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.3.2.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--spring cloud Netflix-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR9</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--spring cloud 阿里巴巴-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.2.6.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
4.2 springcloud_common:存放公共的实体类
4.2.1 pom.xml
<?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">
<parent>
<artifactId>springcloud_parent</artifactId>
<groupId>com.bjpowernode</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>springcloud_common</artifactId>
</project>
4.2.2 pojo 实体类
public class User {
private Integer id;
private String name;
private Integer age;
public User() {
}
public User(Integer id, String name, Integer age) {
this.id = id;
this.name = name;
this.age = age;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
4.3 nacos_provider: 是服务的提供者
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.bjpowernode</groupId>
<artifactId>springcloud_common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!--nacos客户端-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
</dependencies>
application.yml
server:
port: 9090
spring:
cloud:
nacos:
discovery:
server-addr: 192.168.209.129:8848 #nacos服务的地址
application:
name: nacos-provider #向注册中心注册的名字
启动类
@SpringBootApplication
@EnableDiscoveryClient//向注册中心注册该服务,并可以获取其他服务的调用地址
public class NacosProviderApp {
public static void main(String[] args) {
SpringApplication.run(NacosProviderApp.class,args);
}
}
测试
4.2 nacos_consumer:是服务的消费者也就调用者
4.2.1 pom.xml 依赖关系
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.bjpowernode</groupId>
<artifactId>springcloud_common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!--nacos客户端-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
</dependencies>
application.yml
server:
port: 80
spring:
cloud:
nacos:
discovery:
server-addr: 192.168.209.129:8848 #nacos服务的地址
application:
name: nacos-consumer #向注册中心注册的名字
启动类
@SpringBootApplication
@EnableDiscoveryClient//向注册中心注册该服务,并可以获取其他服务的调用地址
public class ConsumerApp {
public static void main(String[] args) {
SpringApplication.run(ConsumerApp.class);
}
}
controller层
@RestController
@RequestMapping("/consumer")
public class ConsumerController {
@Autowired
private RestTemplate restTemplate;
@Autowired
private DiscoveryClient discoveryClient;
@RequestMapping(value="/getUserById/{id}")
public User getUserById(@PathVariable Integer id){
//获取nacos中注册的所有服务信息
List<String> serviceList = discoveryClient.getServices();
for (String service : serviceList) {
System.out.println(service);
}
//获取nacos中注册的指定服务信息
ServiceInstance instance = discoveryClient.getInstances("nacos-provider").get(0);
//路径
String url = "http://"+ serviceInstance.getHost()+":"+ serviceInstance.getPort()+"/provider/getUserById/"+id;
return restTemplate.getForObject(url, User.class);
}
}
测试
5 、Nacos配置中心
5.1 为什么用 Nacos 配置中心
微服务架构下关于配置文件的一些问题 :
- 配置文件相对分散。在一个微服务架构下,配置文件会随着微服务的增多变的越来越多,而且分散在各个微服务中,不好统一配置和管理。
- 配置文件无法区分环境。微服务项目可能会有多个环境,例如:测试环境、预发布环境、生产环境。每一个环境所使用的配置理论上都是不同的,一旦需要修改,就需要我们去各个微服务下手动维护,这比较困难。
- 配置文件无法实时更新。我们修改了配置文件之后,必须重新启动微服务才能使配置生效,这对一个正在运行的项目来说是非常不友好的。
基于上面这些问题,我们就需要配置中心的加入来解决这些问题,配置中心的思路是:
-
首先把项目中各种配置全部都放到一个集中的地方进行统一管理。
-
当各个服务需要获取配置的时候,就来配置中心的接口拉取自己的配置。
-
当配置中心中的各种参数有更新的时候,也能通知到各个服务实时的过来同步最新的信息,使之动态更新。
配置中心案例:
5.2.创建nacos_config :
5.2.1 pom.xml依赖:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
</dependencies>
5.2.2 bootstrap.yml
-
注意:
-
客户端配置文件的名称必须为
bootstrap.yml
-
-
bootstrap/ application 的应用场景:
-
bootstrap.yml
比applicaton.yml
优先加载,应用于系统级别参数配置,一般不会变动; -
application.yml
应用于SpringBoot项目的自动化配置;
-
spring:
cloud:
nacos:
config:
server-addr: 192.168.204.129:8848
file-extension: yaml #后缀名,只支持 properties 和 yaml 类型
prefix: nacos-config #文件名,如果没有配置则默认为 注册到注册中心的服务名
启动类:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient //该服务注册到nacos服务中心,并发现其他服务的地址
public class NacosConfigApp {
public static void main(String[] args) {
SpringApplication.run(NacosConfigApp.class,args);
}
}
controller
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RefreshScope //重新从BeanFactory获取一个新的实例(该实例使用新的配置)
public class ConfigController {
@Value("${spring.datasource.driver-class-name}")
private String driverClassName;
@Value("${spring.datasource.url}")
private String url;
@Value("${spring.datasource.username}")
private String username;
@Value("${spring.datasource.password}")
private String password;
@Value("${spring.datasource.type}")
private String type;
@GetMapping("/config/info")
public String getConfigInfo() {
System.out.println(this);
String configInfo = driverClassName+"<br>"+url+"<br>"+username+"<br>"
+password+"<br>"+type;
return configInfo;
}
}
5.3 在Nacos中添加配置信息
5.3.1 Nacos 中,dataId(配置文件的命名的规则) 的完整格式如下:
${spring.cloud.nacos.config.prefix}.${spring.cloud.nacos.config.file-extension}
spring.cloud.nacos.config.prefix:默认是当前服务的服务名称
spring.cloud.nacos.config.file-extension:配置文件的格式(后缀),目前只支持yaml和properties
步骤:
6、隔离
6.1Nacos配置管理模型
Namespace Group DataId介绍:
-
Namespace: 代表不同的环境的配置隔离, 如: 开发、测试, 生产等
-
Group: 可以代表某个项目, 如XX医疗项目, XX电商项目
-
DataId: 每个项目下往往有若干个工程, 每个配置集(DataId)是一个工程的主配置文件
-
获取配置集需要指定:
-
nacos服务地址,必须指定
-
namespace,如不指定默认public
-
group,如不指定默认 DEFAULT_GROUP
-
dataId,必须指定
-
6.2 新建.namespace
建立好所有namespace后,在配置管理与服务管理模块下所有页面,都会包含用于切换namespace的选项卡
6.3 克隆配置文件
读取配置文件
spring:
cloud:
nacos:
config:
server-addr: 192.168.204.129:8848
file-extension: yaml
prefix: nacos-config
namespace: dev #开发环境
6.4group隔离
读取配置类
spring:
cloud:
nacos:
config:
server-addr: 192.168.204.129:8848
file-extension: yaml
prefix: nacos-config
namespace: a66ca122-fb24-46ba-bde0-58508c2d6689
group: NACOS_GROUP #nacos项目
6.5.服务隔离
6.5.1修改配置文件
测试: