微服务配置规律
上次课我们学习的knows-resource注册到nacos主要有下面几个步骤
1.子项目的pom.xml文件配置
2.application.properties配置文件
3.SpringBoot启动类
我们将这3个位置的配置称之为三板斧
使用Idea启动Nacos
每次开机都需要使用dos命令启动Nacos太麻烦了
我们可以借助Idea提供的功能,在Idea启动Nacos
步骤如下
Spring Gateway网关
什么是网关
所谓网关,就是请求到当前项目时,项目为访问者提供的一个统一的入口
在这个入口处,所有请求都会被记录或检查,验证是否允许访问当前项目
网关就像公司中雇佣的保安一样,监控记录访客的进出
网关在实际项目中运行的功能如下
- 监视和监控与日志记录
- 身份的验证和权限的控制
- 根据用户请求的路径,动态路由到不同微服务
路由的近义词就是"分配"
网关项目在微服务架构中的位置和效果如下图
Spring Gateway基本使用
我们准备使用Spring Gateway作为当前项目的网关组件
Spring Gateway是Spring自己开发的,属于SpringCloud框架中的内容
它的功能就是能够实现一个网关项目
它和Nacos不同,Nacos是一个软件,SpringGateway是一个框架,需要我们创建项目,添加依赖然后启动这个项目来运行,而且在运行前还要编写各种配置让网关真正生效
创建子项目gateway
父子相认
父项目pom文件
<modules>
<module>knows-resource</module>
<module>gateway</module>
</modules>
gateway子项目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>knows</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>cn.tedu</groupId>
<artifactId>gateway</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>gateway</name>
<description>Demo project for Spring Boot</description>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!-- 注册到Nacos的依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
</dependencies>
</project>
上面相当于完成了三板斧配置的第一个步骤
下面开始第二个步骤的配置
这里我们要开始使用application.yml格式的配置文件
随笔中有application.yml和application.properties的区别介绍
在gateway项目中的resources文件夹中创建一个application.yml文件
编写配置如下内容
server:
port: 9000
spring:
application:
name: gateway
cloud:
nacos:
discovery:
server-addr: localhost:8848
gateway:
discovery:
locator:
# 启动网关的路由功能,允许进行路由配置
enabled: true
# 允许服务器名小写
lower-case-service-id: true
routes: #开始路由配置
- id: gateway-resource # 设置路由名称,和其它任何配置无关
# 配置路由目标服务器的名称resource-server
# 必须和nacos中注册的服务器名称一致
# lb:Load Balance的缩写,意思是负载均衡
uri: lb://resource-server
# 下面来定义路由特征:"什么样的路径是访问静态资源服务器的?"
# 下面的定义就是一个通配,凡是满足通配的就是访问静态资源服务器的
predicates:
- Path=/image/**
# 经过了上面的配置效果为:
# 当访问localhost:9000/image/a.jpg时
# 相当于访问了静态资源服务器的同路径资源:
# localhost:8899/image/a.jpg
最后一个步骤,也就是第三板斧
SpringBoot启动类添加注册到Nacos的配置
@SpringBootApplication
@EnableDiscoveryClient
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class, args);
}
}
在Nacos已经启动的前提下
我们就可以启动当前项目观察是否能够成功注册到Nacos
通过网关访问静态资源
上面的章节中,我们已经在Nacos中注册的网关服务
网关是当前项目所有微服务的统一入口
先来完成通过网关端口访问静态资源的效果
我们现在是确定可以使用localhost:8899/a.jpg访问静态资源图片的
但是使用localhost:9000/image/a.jpg时报了404错误
因为它的路由虽然生效的,但是访问的路径相当于localhost:8899/image/a.jpg
我们下面要实现修改访问静态资源服务器的配置
实现localhost:8899/image/a.jpg来访问静态资源图片
knows-resource的application.properties文件添加配置信息:
# 下面配置的含义是为当前项目添加一个全局路径
# 效果是之前访问的任何资源路径都需要添加配置的内容作为前缀,才能访问
# localhost:8899/a.jpg -> localhost:8899/image/a.jpg
# 配置这个的原因是需要匹配网关的路由特征/image/**
server.servlet.context-path=/image
重启knows-resource项目
保证gateway和Nacos也在启动状态
然后输入路径测试localhost:9000/image/a.jpg
观察是否能够显示静态资源图片,如果能够显示表示一切正常
网关工作流程示意图
网关项目补充
SpringGateway项目添加的依赖和SpringMvc的依赖是冲突的
这里特指spring-cloud-starter-gateway和spring-boot-starter-web冲突
原因是spring-cloud-starter-gateway自带一个服务器软件Netty
当启动项目是Netty就会启动
而spring-boot-starter-web自带一个服务器软件Tomcat
当启动项目是Tomcat就会启动
这两个服务器软件在争夺启动主导权时会发生异常
前后端分离
什么是前后端分离
所谓前后端分离就是将项目的所有前端内容单独编写在一个项目中
而后端内容也单独编写一个项目
前端的内容包括:html\css\js静态资源图片和其他静态资源文件,其实就是static目录下的内容
后端的内容就是我们编写在java文件夹中的内容,其实就是所有和java直接相关的文件和代码
当前的大部分企业开发项目,都会采用前后端分离的方式
前后端分离的开发模式并不是微服务专属的
前后端分离的好处:
- 前后端项目解耦,方便程序的扩展,能够接受各种前端访问
- 前端是单独项目,可以访问任何编程语言编写的服务器
- 后端项目专注业务,在网关项目后为各种前端项目做出响应
成熟的前端项目应该使用Vue+nodeJs技术来搭建,因为我们没有学习过这个技术,所以当前情况下我们使用一个SpringBoot项目来代替
前后端分离结构图
创建前端项目
创建子项目knows-client
父子相认
<module>knows-client</module>
knows-client的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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cn.tedu</groupId>
<artifactId>knows</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>cn.tedu</groupId>
<artifactId>knows-client</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>knows-client</name>
<description>Demo project for Spring Boot</description>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
</project>
它既然是静态资源服务器,就要把portal项目中所有的静态资源
也就是static文件夹中的所有内容复制到当前项目中
然后启动client项目,能够访问页面才算正常,但是不能进行实际操作页面也不显示内容,因为没有后端操作
创建用户管理模块项目
我们最终的目的是将原有的portal项目中的所有功能迁移到微服务的项目中
暂时的第一个小目标就是完成注册功能
也就是在微服务项目基本结构(注册中心,网关,前后端分离)中完成注册
首先来创建包含注册功能的项目模块(用户管理模块)
knows-sys项目
什么都不需要勾选,直接确定
父子相认
<module>knows-sys</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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cn.tedu</groupId>
<artifactId>knows</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>cn.tedu</groupId>
<artifactId>knows-sys</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>knows-sys</name>
<description>Demo project for Spring Boot</description>
<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-discovery</artifactId>
</dependency>
<!-- <dependency>-->
<!-- <groupId>cn.tedu</groupId>-->
<!-- <artifactId>knows-commons</artifactId>-->
<!-- </dependency>-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- nacos配置中心的依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- 验证框架 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
</dependencies>
</project>
配置中心
什么是配置中心
上面章节我们创建的用户管理模块knows-sys
但是还没有编写项目的配置
而这里,我们将学习怎么将配置编写在配置中心
所谓配置中心:将项目需要的配置信息保存在配置中心,需要读取时直接从配置中心读取,方便配置管理的微服务工具
为什么使用配置中心
如果当前微服务有多个项目,每个项目的配置如果都保存在配置中心,那么修改配置时,直接在配置中心中维护即可,不需要在找到对应的项目去修改配置,可以提高项目配置的易维护性
配置中心的使用
Nacos既可以做注册中心,也可以做配置中心
Nacos作为配置中心,支持多种配置文件的格式
properties\yaml(yml)\txt\json\xml …
Nacos软件保存数据的结构
上图所示
Nacos软件支持创建多个命名空间Namespace
一个Namespace可以创建多个Group(分组)
一个Group可以添加多个条配置信息(DataId)
所以在Nacos中要定位一个配置文件需要
Namespace->Group->DataId
Nacos提供了一个默认的命名空间:public, 它不能被删除
将sys项目的配置保存到Nacos
Nacos首页->配置管理->配置列表->添加配置(右侧的大"+"号)
添加在public命名空间中
点击发布就能够将配置信息保存在Nacos中了
SpringBoot启动配置加载过程
我们使用过的配置文件有application.properties和application.yml
这两个配置文件都会被加载
但是他们的加载是有顺序的
- 先加载yml
- 后加载properties
- 当两个配置文件配置同一个信息时,后加载的覆盖先加载的
在SpringCloud环境下,还会多出一组配置文件
bootstrap.yml和bootstrap.properties
这一组的加载实际是整体早于application那一组
而且必须等待bootstrap这组配置完全加载完毕之后,application这组才会开始加载
只有SpringCloud框架依赖下才有上面的加载顺序
左侧bootstrap所有信息加载完毕之后,才会开始加载右侧application的信息
所以我们将读取配置中心信息的配置编写在bootstrap中
以保证在程序运行时,配置中心的配置已经加载到当前项目
编写读取配置中心的配置信息
创建bootstrap.yml文件来读取配置中心的配置信息
knows-sys项目中的resources文件夹在创建bootstrap.yml文件
server:
port: 8001
spring:
application:
name: sys-service
cloud:
nacos:
discovery:
server-addr: localhost:8848
config:
# 指定配置中心的配置
server-addr: localhost:8848
# 编写读取的配置所在的组名
# 命名空间名称不用写,因为默认就是public
group: DEFAULT_GROUP
# 指定配置文件的后缀名
# 指定后缀名后,项目会从配置中心中自动读取对应的配置
# [项目名称] . [后缀名称] 构成的DataId,作为读取的配置文件
# sys-service.properties
file-extension: properties
到此为止,配置信息成功加载到sys项目
@SpringBootApplication
@EnableDiscoveryClient
@MapperScan("cn.tedu.knows.sys.mapper")
public class KnowsSysApplication {
public static void main(String[] args) {
SpringApplication.run(KnowsSysApplication.class, args);
}
}
@MapperScan注解的设置不要忘记
然后就可以启动sys项目了(Nacos启动状态下)
启动不报错,表示读取了配置中心的内容
迁移注册功能
我们已经完成了knows-sys项目的创建和基本信息的配置
下面要开始为注册功能迁移代码
将portal项目中的相关代码和类复制到sys模块
我们的迁移计划步骤
1.Mapper(数据访问层)
2.Service(业务逻辑层)
3.Contoller(控制层)
创建通用项目
在我们的微服务项目中
可能有一些类是每个微服务项目都需要使用的(例如实体类User等)
我们可以新建一个项目,在这个项目中保存实体类和所有项目都需要的通用类
这样的话,哪个项目需要这些资源,哪些项目就添加这个通用资源项目的依赖即可
创建knows-commons
因为是通用资源项目,不需要勾选其它内容
父子相认
<module>knows-commons</module>
子项目依赖
<?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>knows</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>cn.tedu</groupId>
<artifactId>knows-commons</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>knows-commons</name>
<description>Demo project for Spring Boot</description>
<dependencies>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus</artifactId>
</dependency>
</dependencies>
</project>
下面我们要删除一些没有必要的内容
删除test测试文件夹
删除SpringBoot启动类
这个项目一旦将需要有的资源复制完毕
其他项目就可以添加这个项目的依赖了
打开knows-sys项目的pom.xml文件
解除对knows-commons依赖的注释,并刷新maven
随笔
两种配置文件
我们在学习过程中使用较多的是application.properties
但是在配置比较多,比较复杂时,程序员更愿意使用application.yml文件
因为application.yml在配置相同内容是更加简洁
例如数据连接池的配置在properties文件中:
spring.datasource.url=jdbc:mysql://localhost:3306/knows?characterEncoding=utf8
spring.datasource.username=root
spring.datasource.password=root
yml文件配置可以简化为
spring:
datasource:
url: jdbc:mysql://localhost:3306/knows?characterEncoding=utf8
username: root
password: root
我们可以看出,yml格式的配置冗余更少
但是要遵守更严格的格式
现在再企业中,为了更简洁的配置设计,更多配置文件开始使用yml格式
SpringBoot项目启动时会解析
application.properties和application.yml两个文件
负载均衡
所谓负载均衡就是一个能够使当前微服务所有服务器处理任务尽量平均分配的算法
当一个业务又多个服务器时
新的请求总是会请求比较闲的服务器
英文
Balance:平衡\均衡