Nacos是Spring Cloud Alibaba提供的一个软件
这个软件主要具有注册中心和配置中心(课程最后讲解)的功能
我们先学习它注册中心的功能
微服务中所有项目都必须注册到注册中心才能成为微服务的一部分
注册中心和企业中的人力资源管理部门有相似
当前微服务项目中所有的模块,在启动前,必须添加注册到Nacos的配置
所谓注册,就是将自己的信息,提交到Nacos来保存
Nacos的下载
https://github.com/alibaba/nacos/releases/download/1.4.3/nacos-server-1.4.3.zip
因为Nacos是java开发的
我们要启动Nacos必须保证当前系统配置了java环境变量
简单来说就是要环境变量中,有JAVA_HOME的配置,指向安装jdk的路径
确定了支持java后,就可以启动Nacos了
将nacos-server-1.4.2.zip压缩包解压
双击打开解压得到的文件夹后,再双击打开其中的bin目录
cmd结尾的文件是windows版本的
sh结尾的文件是linux和mac版本的
startup是启动文件,shutdown是停止文件
Windows下启动Nacos不能直接双击cmd文件
需要在dos窗口运行
在当前资源管理器地址栏输入cmd
E:\tools\nacos\bin>startup.cmd -m standalone
startup.cmd:windows启动nacos的命令文件
-m 表示要设置启动参数
standalone:翻译为标准的孤独的,意思是正常的使用单机模式启动
运行成功默认占用8848端口,并且在代码中提示
如果不输入standalone运行会失败
如果报了
"please set JAVA_HOME......."
表示当前项目没有配置java环境变量(主要是没有设置JAVA_HOME)
如果运行没有报错
打开浏览器输入地址
http://localhost:8848/nacos
如果是首次访问,会出现这个界面
登录系统
用户名:nacos
密码:nacos
登录之后可以进入后台列表
不能关闭启动nacos的dos窗口
我们要让我们编写的项目注册到Nacos,才能真正是微服务项目
创建csmall父项目
创建项目名称csmall
我们微服务开发过程中,一般都会使用一个Idea中包含多个项目的形式
这个形式就是先创建一个"父项目",再向这个父项目中创建多个子项目的操作
我们首先创建一个项目:csmall
注意细节的修改
不要选择springBoot 3.0.x,要选择2开头的版本
上面图片next之后直接点击finish即可
首先,将当前csmall项目修剪为父项目的格式
- 删除csmall项目的src文件夹,因为父项目不写代码
- 修改pom文件
最终csmall的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 https://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.5.9</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>cn.tedu</groupId>
<artifactId>csmall</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>csmall</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<!--
父子项目结构是Maven提供的,而pom.xml文件就是maven的配置
所以要将当前项目声明为父项目,需要在pom文件中编写下面的配置
-->
<packaging>pom</packaging>
</project>
创建子项目
创建csmall-stock项目
我们每次创建一个子项目之后
都要进行"父子相认"
在父项目的pom文件中,编写子项目的存在
<!--
父子项目结构是Maven提供的,而pom.xml文件就是maven的配置
所以要将当前项目声明为父项目,需要在pom文件中编写下面的配置
-->
<packaging>pom</packaging>
<!--
设置当前父项目有哪些子项目(子模块) module就是模块的意思
-->
<modules>
<module>csmall-stock</module>
</modules>
还需要在子项目的pom文件中对父项目进行继承操作
父项目的第11行到第13行
复制到子项目的第6行到第8行
子项目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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cn.tedu</groupId>
<artifactId>csmall</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>cn.tedu</groupId>
<artifactId>csmall-stock</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>csmall-stock</name>
<description>Demo project for Spring Boot</description>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
</dependencies>
</project>
父子相认完成
这样当前子项目就可以读取父项目中的pom文件信息了
删除stock模块src\test文件夹
父项目管理依赖版本
在我们现在使用maven添加依赖的认知中
有些依赖时必须添加版本号才能执行
有些依赖则不必添加版本号
原因是我们继承的SpringBoot(2.5.9)父项目中,定义了一些常用依赖的版本号
如果我们自己编写的父项目想定义我们项目中需要的依赖版本号的话,也是可以实现的
这样做可以统一所有子项目的版本,在更新版本时,只需要修改父项目中定义的版本号即可
父项目的pom文件添加如下内容
<!--
设置当前父项目有哪些子项目(子模块) module就是模块的意思
-->
<modules>
<module>csmall-stock</module>
</modules>
<!-- 在 properties标签中,声明需要使用的各个框架的版本号 -->
<properties>
<java.version>1.8</java.version>
<!-- 这些标签实际上就是变量的定义, 这里就是定义了一个名为mybatis.version值为2.2.0的变量 -->
<mybatis.version>2.2.0</mybatis.version>
</properties>
<!-- 下面的标签用来定义子项目中添加依赖时,选用哪个版本号,也称之为"锁版本" -->
<!-- dependencyManagement标签中的内容,不是添加依赖,而是指定依赖的版本,子项目添加依赖时才会添加依赖内容-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
子项目中如果需要mybatis的依赖只需要添加如下内容即可,无需再指定版本号
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
上面的操作也称之为"锁版本"
加载正式项目pom文件
因为我们学习微服务的过程中需要很多微服务相关的依赖
这些依赖都需要在父项目中进行版本的管理的
所以我们直接使用分享给大家的完整版项目的父项目pom文件即可
父项目完整最终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 https://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.5.9</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>cn.tedu</groupId>
<artifactId>csmall</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>csmall</name>
<description>Demo project for Spring Boot</description>
<!--
父子项目结构是Maven提供的,而pom.xml文件就是maven的配置
所以要将当前项目声明为父项目,需要在pom文件中编写下面的配置
-->
<packaging>pom</packaging>
<!--
设置当前父项目有哪些子项目(子模块) module就是模块的意思
-->
<modules>
<module>csmall-stock</module>
</modules>
<!-- 在 properties标签中,声明需要使用的各个框架的版本号 -->
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>2020.0.3</spring-cloud.version>
<spring-cloud-alibaba.version>2.2.2.RELEASE</spring-cloud-alibaba.version>
<spring-boot.version>2.5.4</spring-boot.version>
<spring-boot-configuration-processor.version>2.3.0.RELEASE</spring-boot-configuration-processor.version>
<spring-security-jwt.version>1.0.10.RELEASE</spring-security-jwt.version>
<mybatis-spring-boot.version>2.2.0</mybatis-spring-boot.version>
<mybaits-plus.version>3.4.1</mybaits-plus.version>
<pagehelper-spring-boot.version>1.4.0</pagehelper-spring-boot.version>
<mysql.version>8.0.26</mysql.version>
<lombok.version>1.18.20</lombok.version>
<knife4j-spring-boot.version>2.0.9</knife4j-spring-boot.version>
<spring-rabbit-test.version>2.3.10</spring-rabbit-test.version>
<spring-security-test.version>5.5.2</spring-security-test.version>
<fastjson.version>1.2.45</fastjson.version>
<druid.version>1.1.20</druid.version>
<jjwt.version>0.9.0</jjwt.version>
<seata-server.version>1.4.2</seata-server.version>
</properties>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
<!-- 依赖管理 -->
<dependencyManagement>
<dependencies>
<!--seata-all-->
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata-all</artifactId>
<version>${seata-server.version}</version>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
<!-- MySQL -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
<scope>runtime</scope>
</dependency>
<!-- Alibaba Druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${druid.version}</version>
</dependency>
<!-- MyBatis Spring Boot:数据访问层MyBatis编程 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis-spring-boot.version}</version>
</dependency>
<!-- MyBatis Plus Spring Boot:MyBatis增强 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybaits-plus.version}</version>
</dependency>
<!-- MyBatis Plus Generator:代码生成器 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>${mybaits-plus.version}</version>
</dependency>
<!-- PageHelper Spring Boot:MyBatis分页 -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>${pagehelper-spring-boot.version}</version>
</dependency>
<!-- Spring Boot:基础框架 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>${spring-boot.version}</version>
</dependency>
<!-- Spring Boot Web:WEB应用 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${spring-boot.version}</version>
</dependency>
<!-- Spring Boot Freemarker:MyBaits Plus Generator的辅助项 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
<version>${spring-boot.version}</version>
</dependency>
<!-- Spring Boot Validation:验证请求参数 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
<version>${spring-boot.version}</version>
</dependency>
<!-- Spring Boot Security:认证授权 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<version>${spring-boot.version}</version>
</dependency>
<!-- Spring Boot Oauth2:认证授权 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
<version>${spring-boot.version}</version>
</dependency>
<!-- Spring Boot配置处理器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<version>${spring-boot-configuration-processor.version}</version>
</dependency>
<!-- Spring Security JWT -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-jwt</artifactId>
<version>${spring-security-jwt.version}</version>
</dependency>
<!-- Knife4j Spring Boot:在线API -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>${knife4j-spring-boot.version}</version>
</dependency>
<!-- Spring Boot Data Redis:缓存 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>${spring-boot.version}</version>
</dependency>
<!-- Spring Boot Data MongoDB:缓存 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
<version>${spring-boot.version}</version>
</dependency>
<!-- Spring Boot Data Elasticsearch:文档搜索 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
<version>${spring-boot.version}</version>
</dependency>
<!-- Spring Boot AMQP:消息队列 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
<version>${spring-boot.version}</version>
</dependency>
<!-- Spring Boot Actuator:健康监测 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<version>${spring-boot.version}</version>
</dependency>
<!-- Spring Cloud家族 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- Spring Cloud Alibaba -->
<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>
<!-- Alibaba FastJson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<!-- JJWT -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>${jjwt.version}</version>
</dependency>
<!-- Spring Boot Test:测试 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>${spring-boot.version}</version>
<scope>test</scope>
</dependency>
<!-- Spring Rabbit Test:消息队列测试 -->
<dependency>
<groupId>org.springframework.amqp</groupId>
<artifactId>spring-rabbit-test</artifactId>
<version>${spring-rabbit-test.version}</version>
<scope>test</scope>
</dependency>
<!-- Spring Security Test:Security测试 -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<version>${spring-security-test.version}</version>
<scope>test</scope>
</dependency>
<!--seata整合springboot-->
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata-spring-boot-starter</artifactId>
<version>${seata-server.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
配置yml文件内容
server:
port: 20000
#公共配置
mybatis:
configuration:
cache-enabled: false # 不启用mybatis缓存
map-underscore-to-camel-case: true # 映射支持驼峰命名法
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 将运行的sql输出到控制台
knife4j:
# 开启增强配置
enable: true
# 生产环境屏蔽,开启将禁止访问在线API文档
production: false
# Basic认证功能,即是否需要通过用户名、密码验证后才可以访问在线API文档
basic:
# 是否开启Basic认证
enable: false
# 用户名,如果开启Basic认证却未配置用户名与密码,默认是:admin/123321
username: root
# 密码
password: root
spring:
profiles:
active: dev
上面的配置含义是让SpringBoot读取额外配置文件
我们参数值编写的是dev,是可以随意修改的,这里定义的名称,就是指定配置文件的名称
例如当前我们编写的dev,SpringBoot就会额外加载名称为application-dev.yml文件
我们创建application-dev.yml文件,以备添加配置
将项目注册到Nacos
我们已经讲过,一个项目要想成为微服务项目体系的一部分
必须将当前项目的信息注册到Nacos
我们要添加一些配置,实现business模块启动时注册到Nacos的效果
<!-- 支持项目注册到Nacos注册中心的依赖 discovery 是发现的意思(微服务项目的发现) -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
我们在创建好的application-dev.yml中编写对nacos注册的配置信息
spring:
application:
# 设置当前应用的名称,这个名字会提交到Nacos,作为当前微服务模块的名称
name: nacos-business
cloud:
nacos:
discovery:
# 配置nacos的位置,用于提交当前项目的注册信息
server-addr: localhost:8848
按照学习Nacos时的方式,启动一下nacos
启动之后,
重启business模块,如果启动也正常,就应该将当前项目的信息提交给Nacos
在Nacos的服务管理->服务列表中,能看到nacos-business的名称
Nacos心跳机制
常见面试题
心跳:周期性的操作,来表示自己是健康可用的机制
注册到Nacos的微服务项目(模块)都是会遵循这个心跳机制的
心跳机制的目的
1.是表示当前微服务模块运行状态正常的手段
2.是表示当前微服务模块和Nacos保持沟通和交换信息的机制
默认情况下,服务启动开始每隔5秒会向Nacos发送一个"心跳包",这个心跳包中包含了当前服务的基本信息
Nacos接收到这个心跳包,首先检查当前服务在不在注册列表中,如果不在按新服务的业务进行注册,如果在,表示当前这个服务是健康状态
如果一个服务连续3次心跳(默认15秒)没有和Nacos进行信息的交互,就会将当前服务标记为不健康的状态
如果一个服务连续6次心跳(默认30秒)没有和Nacos进行信息的交互,Nacos会将这个服务从注册列表中剔除
这些时间都是可以通过配置修改的
实例类型分类
实际上Nacos的服务类型还有分类
- 临时实例(默认)
- 持久化实例(永久实例)
默认每个服务都是临时实例
如果想标记一个服务为永久实例
cloud:
nacos:
discovery:
# ephemeral设置当前项目启动时注册到nacos的类型 true(默认):临时实例 false:永久实例
ephemeral: false
持久化实例启动时向nacos注册,nacos会对这个实例进行持久化处理
心跳包的规则和临时实例一致,只是不会将该服务从列表中剔除
一般情况下,我们创建的服务都是临时实例
只有项目的主干业务才会设置为永久实例
使用Idea启动Nacos
之前我们启动Nacos都是使用dos命令行
启动过程比较复杂,命令比较长
Idea实际上支持我们更加方便的启动Nacos
步骤1:
步骤2:
步骤3:
配置成功之后
Nacos就会出现在idea的启动选项中了
这种方法实际上只是为了简便大家启动nacos的操作,还是需要掌握命令行的启动方式的!
创建项目
创建csmall-cart子项目
父子相认
子项目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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cn.tedu</groupId>
<artifactId>csmall</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>cn.tedu</groupId>
<artifactId>csmall-cart</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>csmall-cart</name>
<description>Demo project for Spring Boot</description>
<dependencies>
<!--web实例-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--mybatis整合springboot-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<!--alibaba 数据源德鲁伊-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
</dependency>
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--all-common依赖-->
<dependency>
<groupId>cn.tedu</groupId>
<artifactId>csmall-commons</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!--在线api文档-->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
</dependency>
<!-- Nacos注册依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
</dependencies>
</project>
创建application.yml文件,内容如下,注意修改了端口号20001
server:
port: 20001
#公共配置
mybatis:
configuration:
cache-enabled: false # 不启用mybatis缓存
map-underscore-to-camel-case: true # 映射支持驼峰命名法
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 将运行的sql输出到控制台
knife4j:
# 开启增强配置
enable: true
# 生产环境屏蔽,开启将禁止访问在线API文档
production: false
# Basic认证功能,即是否需要通过用户名、密码验证后才可以访问在线API文档
basic:
# 是否开启Basic认证
enable: false
# 用户名,如果开启Basic认证却未配置用户名与密码,默认是:admin/123321
username: root
# 密码
password: root
spring:
profiles:
active: dev
创建application-dev.yml
spring:
application:
# 设置当前应用的名称,这个名字会提交到Nacos,作为当前微服务模块的名称
name: nacos-cart
cloud:
nacos:
discovery:
# 配置nacos的位置,用于提交当前项目的注册信息
server-addr: localhost:8848
datasource:
url: jdbc:mysql://localhost:3306/csmall_db?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&allowMultiQueries=true
username: root
password: root