企业级微服务大项目实战《学成在线》【三】(Nacos,Gateway,Minio环境搭建)
Nacos网关配置
服务器环境配置
注意下面的环境配置是针对远程服务器或自己搭建的虚拟机的,默认资料的虚拟机可以不用看!!!
先拉取1.4.1的镜像并启动:
docker pull nacos/nacos-server:1.4.1
docker run --env MODE=standalone --name nacos -d -p 8848:8848 nacos/nacos-server:1.4.1
进入nacos配置文件:
docker exec -it nacos bash
配置MySQL:
spring.datasource.platform=mysql
db.num=1
db.url.0=jdbc:mysql://xxxxxxxx:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true
db.user=root
db.password=123456
配置
先总结下:配置的时候确实很麻烦,但是以后要修改的时候还是挺好修改的。
在内容管理模块的接口工程、系统管理模块的接口工程中添加如下依赖,还有需要调用http请求的模块也要引入,引入后记得刷新Maven!!
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
先登录并访问:http://ip:8848/nacos/
账号密码:nacos/nacos
登录成功,点击左侧菜单“命名空间”进入命名空间管理界面,
点击“新建命名空间”,填写命名空间的相关信息。如下图:
使用相同的方法再创建“测试环境”、"生产环境"的命名空间。
在系统管理的接口工程的配置文件中配置如下信息:
#微服务配置
spring:
application:
name: system-service
cloud:
nacos:
server-addr: 192.168.101.65:8848
discovery:
namespace: dev
group: xuecheng-plus-project
在内容管理的接口工程的配置文件中配置如下信息:
spring:
application:
name: content-service
cloud:
nacos:
server-addr: 192.168.101.65:8848
discovery:
namespace: dev
group: xuecheng-plus-project
content-api/content-service配置
在Nacos页面新建一个配置如下:
再在pom坐标里引入config的依赖:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
再在content-api的yml里编写配置:
#微服务配置
spring:
application:
name: content-api
cloud:
nacos:
server-addr: 47.109.74.83:8848
discovery:
namespace: dev
group: xuecheng-plus-project
config:
namespace: dev
group: xuecheng-plus-project
file-extension: yaml
refresh-enabled: true
profiles:
active: dev #环境名
数据库的配置就可以去掉了,
通过dataid找到具体的配置文件,dataid有三部分组成,
比如:content-service-dev.yaml配置文件 由(content-service)-(dev). (yaml)三部分组成
content-service:第一部分,它是在application.yaml中配置的应用名,即spring.application.name的值。
dev:第二部分,它是环境名,通过spring.profiles.active指定,
Yaml: 第三部分,它是配置文件 的后缀,目前nacos支持properties、yaml等格式类型,本项目选择yaml格式类型。
所以在content-service工程 的test目录中添加bootstrap.yaml进行单元测试,内容如下:
spring:
application:
name: content-service
cloud:
nacos:
server-addr: remote.centos.com:8848
discovery:
namespace: dev #命名空间,可随意取与spring.profile不一定一致
group: xuecheng-plus-project
config:
namespace: dev #命名空间,可随意取与spring.profile不一定一致
group: xuecheng-plus-project
file-extension: yaml
refresh-enabled: true
#profiles默认为dev
profiles:
active: dev
在内容管理模块的接口工程和service工程、系统管理的接口工程和service工程配置依赖:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
配置完成,运行content-service工程 的单元测试文件,能否正常测试。
通过运行观察控制台打印出下边的信息:
[NacosRestTemplate.java:476] - HTTP method: POST, url: http://192.168.101.65:8848/nacos/v1/cs/configs/listener, body: {Listening-Configs=content-service.yaml?xuecheng-plus-project??dev?content-service-dev.yaml?xuecheng-plus-project?88459b1483b8381eccc2ef462bd59182?dev?content-service?xuecheng-plus-project??dev?, tenant=dev}
以相同的方法配置content-api工程的配置文件,在nacos中的开发环境中配置content-api-dev.yaml,内容如下:
server:
servlet:
context-path: /content # 服务访问根路径
port: 63040
# 日志文件配置路径
logging:
config: classpath:log4j2-dev.xml
# swagger 文档配置
swagger:
title: "学成在线内容管理系统"
description: "内容系统管理系统对课程相关信息进行业务管理数据"
base-package: com.xuecheng.content
enabled: true
version: 1.0.0
在content-api工程 的本地配置bootstrap.yaml,内容如下:
#微服务配置
spring:
application:
name: content-api
cloud:
nacos:
server-addr: remote.centos.com:8848
discovery:
namespace: dev #命名空间 (与profile.active有区别配置文件的拉取不是根据命名空间来拼接的)
group: xuecheng-plus-project
config:
namespace: dev
group: xuecheng-plus-project
file-extension: yaml
refresh-enabled: true
extension-configs:
- data-id: content-service-${spring.profiles.active}.yaml
group: xuecheng-plus-project
refresh: true
profiles:
active: dev
注意:因为api接口工程依赖了service工程 的jar,所以这里使用extension-configs扩展配置文件 的方式引用service工程所用到的配置文件。
如果添加多个扩展文件,继续在下添加即可,如下:
extension-configs:
- data-id: content-service-${spring.profiles.active}.yaml
group: xuecheng-plus-project
refresh: true
- data-id: 填写文件 dataid
group: xuecheng-plus-project
refresh: true
启动content-api工程,查询控制台是否打印出了请求nacos的日志,如下:
[NacosRestTemplate.java:476] - HTTP method: POST, url: http://192.168.101.65:8848/nacos/v1/cs/configs/listener
并使用Httpclient测试课程查询接口是否可以正常查询。
还有一个优化的点是如何在nacos中配置项目的公用配置呢?
nacos提供了shared-configs可以引入公用配置。
在content-api中配置了swagger,所有的接口工程 都需要配置swagger,这里就可以将swagger的配置定义为一个公用配置,哪个项目用引入即可。
单独在xuecheng-plus-common分组下创建xuecheng-plus的公用配置,进入nacos的开发环境,添加swagger-dev.yaml公用配置
删除content-api-dev.yaml
中对swagger的配置。
项目使用shared-configs可以引入公用配置。在接口工程的本地配置文件 中引入公用配置(其他配置类似,这里忽略了log4j的配置过程),如下:
#微服务配置
spring:
application:
name: content-api
cloud:
nacos:
server-addr: remote.centos.com:8848
discovery:
namespace: dev #命名空间 (与profile.active有区别配置文件的拉取不是根据命名空间来拼接的)
group: xuecheng-plus-project
config:
namespace: dev
group: xuecheng-plus-project
file-extension: yaml
refresh-enabled: true
extension-configs:
- data-id: content-service-${spring.profiles.active}.yaml
group: xuecheng-plus-project
refresh: true
shared-configs:
- data-id: swagger-${spring.profiles.active}.yaml
group: xuecheng-plus-common
refresh: true
- data-id: logging-${spring.profiles.active}.yaml
group: xuecheng-plus-common
refresh: true
profiles:
active: dev
配置完成,重启content-api接口工程,访问http://localhost:63040/content/swagger-ui.html 查看swagger接口文档是否可以正常访问,查看控制台log4j2日志输出是否正常。
配置优先级
到目前为止已将所有微服务的配置统一在nacos进行配置,用到的配置文件有本地的配置文件 bootstrap.yaml和nacos上的配置文件,引入配置文件的形式有:
1、通过dataid方式引入
2、以扩展配置文件方式引入
3、以共享配置文件 方式引入
下边测试这几种配置文件方式的优先级。
我们使用内容管理服务中的配置文件,首先在共享配置文件 swagger-dev.yaml中配置四个配置项,如下:
配置完成发布。
下边在content-api工程的启动类中添加如下代码读取这四个配置项的值
public class ContentApplication {
@Value("${test_config.a}")
String a;
@Value("${test_config.b}")
String b;
@Value("${test_config.c}")
String c;
@Value("${test_config.d}")
String d;
@Bean
public Integer getTest(){
System.out.println("a="+a);
System.out.println("b="+b);
System.out.println("c="+c);
System.out.println("d="+d);
return new Integer(1);
}
public static void main(String[] args) {
SpringApplication.run(ContentApplication.class, args);
}
}
启动content-api工程,在return new Integer(1);处打断点,运行到断点处,如下:
这说明已经成功读取到 四个配置项的值。
下边在content-api工程的扩展配置文件 conent-service-dev.yaml中配置三个配置项,如下:
再次重启content-api工程,在return new Integer(1);处打断点,运行到断点处,如下:
从结果可以看出,扩展配置文件比共享配置文件优先级高。
下边继续content-api-dev.yaml中配置两个配置项,如下:
test_config:
a: 4a
b: 4b
c: 4c
d: 4d
再次重启内容管理接口工程,在return new Integer(1);处打断点,运行到断点处,如下:
这说明本地配置文件配置的内容没有起作用,原因是nacos配置文件中的相同的配置项覆盖了本地的配置项。
到这可以总结各各配置文件 的优先级:项目应用名配置文件 > 扩展配置文件 > 共享配置文件 > 本地配置文件。
有时候我们在测试程序时直接在本地加一个配置进行测试,这时我们想让本地最优先,可以在nacos配置文件 中配置如下即可实现:
spring:
cloud:
config:
override-none: true
再次重启content-api工程,在return new Integer(1);处打断点,运行到断点处,如下:
可以看出此时本地配置最优先
除此之外,我们一般不会带本地配置写入到bootstrap.yml中而是通过jvm参数
如我们要启动两个服务进行调试,那么端口号就不能一致,因此我们可以通过添加jvm参数指定端口号:
-Dserver.port=8088
如我们现在向启动两个content服务
4.2.2.6 导入配置文件
课程资料中提供了系统用的所有配置文件nacos_config_export.zip,下边将nacos_config_export.zip导入nacos。
进入具体的命名空间,点击“导入配置”
打开导入窗口
相同的配置跳过覆盖配置。
点击“上传文件”选择nacos_config_export.zip开始导入。
远程服务器的记得修改rabbitmq-dev的ip地址~
搭建Gateway
本项目使用Spring Cloud Gateway作为网关,下边创建网关工程。
新建一个网关工程。
项目结构如下
添加依赖:
<dependencies>
<!--网关-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!--服务发现中心-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!-- 排除 Spring Boot 依赖的日志包冲突 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- Spring Boot 集成 log4j2 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
</dependencies>
配置网关的bootstrap.yaml配置文件
#微服务配置
spring:
application:
name: gateway
cloud:
nacos:
server-addr: 192.168.101.65:8848
discovery:
namespace: ${spring.profiles.active}
group: xuecheng-plus-project
config:
namespace: ${spring.profiles.active}
group: xuecheng-plus-project
file-extension: yaml
refresh-enabled: true
shared-configs:
- data-id: logging-${spring.profiles.active}.yaml
group: xuecheng-plus-common
refresh: true
profiles:
active: dev
在nacos上配置网关路由策略:
minio
一个分布式存储数据的东西啦,如果学过大数据的话就应该知道Hadoop,里面的底层就是HDFS,模式为主从结构,而minio则是相反的去中心化模式,下面是官方点的介绍:
介绍
本项目采用MinIO构建分布式文件系统,MinIO 是一个非常轻量的服务,可以很简单的和其他应用的结合使用,它兼容亚马逊 S3 云存储服务接口,非常适合于存储大容量非结构化的数据,例如图片、视频、日志文件、备份数据和容器/虚拟机镜像等。
它一大特点就是轻量,使用简单,功能强大,支持各种平台,单个文件最大5TB,兼容 Amazon S3接口,提供了 Java、Python、GO等多版本SDK支持。
中文:https://www.minio.org.cn/,http://docs.minio.org.cn/docs/
MinIO集群采用去中心化共享架构,每个结点是对等关系,通过Nginx可对MinIO进行负载均衡访问。
去中心化有什么好处?
在大数据领域,通常的设计理念都是无中心和分布式。Minio分布式模式可以帮助你搭建一个高可用的对象存储服务,你可以使用这些存储设备,而不用考虑其真实物理位置。
它将分布在不同服务器上的多块硬盘组成一个对象存储服务。由于硬盘分布在不同的节点上,分布式Minio避免了单点故障。如下图:
Minio使用纠删码技术来保护数据,它是一种恢复丢失和损坏数据的数学算法,它将数据分块冗余的分散存储在各各节点的磁盘上,所有的可用磁盘组成一个集合,上图由8块硬盘组成一个集合,当上传一个文件时会通过纠删码算法计算对文件进行分块存储,除了将文件本身分成4个数据块,还会生成4个校验块,数据块和校验块会分散的存储在这8块硬盘上。
使用纠删码的好处是即便丢失一半数量(N/2)的硬盘,仍然可以恢复数据。 比如上边集合中有4个以内的硬盘损害仍可保证数据恢复,不影响上传和下载,如果多于一半的硬盘坏了则无法恢复。
远程服务器部署minio
老师默认的虚拟是有minio环境的,这里是其它服务器或自搭虚拟机的方法~
先拉取镜像,可以在后面加上版本
docker pull minio/minio
二、创建挂载目录
1 宿主机与容器挂载映射
宿主机位置 | 容器位置 |
---|---|
/data/minio/config | /data |
/data/minio/data | /root/.minio |
2 挂载命令执行
mkdir -p /data/minio/config
mkdir -p /data/minio/data
三、运行MinIO
docker run -p 9000:9000 -p 9090:9090 --name minio \
-d --restart=always \
-e "MINIO_ACCESS_KEY=admin" \
-e "MINIO_SECRET_KEY=admin123456" \
-v /data/minio/data:/data \
-v /data/minio/config:/root/.minio \minio/minio \
server /data --console-address ":9090"
命令参数解释:
-d :后台启动
-p :端口映射
-name :为这个容器取一个名字
-e :设置环境变量
-v :文件挂载位置
--console-address ":9090" :选择静态端口号,这里注意下控制台端口号不能和静态端口号一样
目前的docker容器:
四、查看MinIO是否启动成功
- 打开
http://ip:9090
- 密码为上面设置的admin admin123456
项目文件配置
在media-service的pom里添加依赖:
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.4.3</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.8.1</version>
</dependency>
登进去网页直接创建一个bucket,然后将其访问仅限改成public,不然等下测试类访问不到:
直接搞个测试类:
/**
* @author Mr.M
* @version 1.0
* @description 测试minio的sdk
* @date 2023/2/17 11:55
*/
public class MinioTest {
MinioClient minioClient =
MinioClient.builder()
.endpoint("http://xx.xx.xx.xx:9000")
.credentials("admin", "admin123456")
.build();
@Test
public void test_upload() throws Exception {
//通过扩展名得到媒体资源类型 mimeType
//根据扩展名取出mimeType
ContentInfo extensionMatch = ContentInfoUtil.findExtensionMatch(".mp4");
String mimeType = MediaType.APPLICATION_OCTET_STREAM_VALUE;//通用mimeType,字节流
if(extensionMatch!=null){
mimeType = extensionMatch.getMimeType();
}
//上传文件的参数信息
UploadObjectArgs uploadObjectArgs = UploadObjectArgs.builder()
.bucket("testbucket")//桶
.filename("D:\\develop\\upload\\1.mp4") //指定本地文件路径
// .object("1.mp4")//对象名 在桶下存储该文件
.object("test/01/1.mp4")//对象名 放在子目录下
.contentType(mimeType)//设置媒体文件类型
.build();
//上传文件
minioClient.uploadObject(uploadObjectArgs);
}
//删除文件
@Test
public void test_delete() throws Exception {
//RemoveObjectArgs
RemoveObjectArgs removeObjectArgs = RemoveObjectArgs.builder().bucket("testbucket").object("1.mp4").build();
//删除文件
minioClient.removeObject(removeObjectArgs);
}
//查询文件 从minio中下载
@Test
public void test_getFile() throws Exception {
GetObjectArgs getObjectArgs = GetObjectArgs.builder().bucket("testbucket").object("test/01/1.mp4").build();
//查询远程服务获取到一个流对象
FilterInputStream inputStream = minioClient.getObject(getObjectArgs);
//指定输出流
FileOutputStream outputStream = new FileOutputStream(new File("D:\\develop\\upload\\1a.mp4"));
IOUtils.copy(inputStream,outputStream);
//校验文件的完整性对文件的内容进行md5
FileInputStream fileInputStream1 = new FileInputStream(new File("D:\\develop\\upload\\1.mp4"));
String source_md5 = DigestUtils.md5Hex(fileInputStream1);
FileInputStream fileInputStream = new FileInputStream(new File("D:\\develop\\upload\\1a.mp4"));
String local_md5 = DigestUtils.md5Hex(fileInputStream);
if(source_md5.equals(local_md5)){
System.out.println("下载成功");
}
}
}
看注释就看得懂了,可以修改下一些参数然后自己测试下,是没问题的。