企业级微服务大项目实战《学成在线》【三】(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

登录成功,点击左侧菜单“命名空间”进入命名空间管理界面,

image-20230308162543252

点击“新建命名空间”,填写命名空间的相关信息。如下图:

image-20230308162554064

使用相同的方法再创建“测试环境”、"生产环境"的命名空间。

image-20230308162608472

image-20230308162612150

 

在系统管理的接口工程的配置文件中配置如下信息:

#微服务配置
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

以相同的方法配置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
 

image-20230308214237689

在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公用配置

image-20230308215015982

删除content-api-dev.yaml中对swagger的配置。

image-20230308215550366

项目使用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中配置四个配置项,如下:

image-20230309134210974

配置完成发布。

下边在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);处打断点,运行到断点处,如下:

image-20230309134251802

这说明已经成功读取到 四个配置项的值。

下边在content-api工程的扩展配置文件 conent-service-dev.yaml中配置三个配置项,如下:

image-20230309135407678

再次重启content-api工程,在return new Integer(1);处打断点,运行到断点处,如下:

image-20230309135419829

从结果可以看出,扩展配置文件比共享配置文件优先级高。

下边继续content-api-dev.yaml中配置两个配置项,如下:

test_config:
  a: 4a
  b: 4b
  c: 4c
  d: 4d
 

再次重启内容管理接口工程,在return new Integer(1);处打断点,运行到断点处,如下:

image-20230309135654218

这说明本地配置文件配置的内容没有起作用,原因是nacos配置文件中的相同的配置项覆盖了本地的配置项。

到这可以总结各各配置文件 的优先级:项目应用名配置文件 > 扩展配置文件 > 共享配置文件 > 本地配置文件。

有时候我们在测试程序时直接在本地加一个配置进行测试,这时我们想让本地最优先,可以在nacos配置文件 中配置如下即可实现:

spring:
 cloud:
  config:
    override-none: true
 

再次重启content-api工程,在return new Integer(1);处打断点,运行到断点处,如下:

image-20230309135741633

可以看出此时本地配置最优先

除此之外,我们一般不会带本地配置写入到bootstrap.yml中而是通过jvm参数

如我们要启动两个服务进行调试,那么端口号就不能一致,因此我们可以通过添加jvm参数指定端口号:

-Dserver.port=8088
 

如我们现在向启动两个content服务

image-20230309145108805

image-20230309145353006

image-20230309145419800

image-20230309145613692

4.2.2.6 导入配置文件

课程资料中提供了系统用的所有配置文件nacos_config_export.zip,下边将nacos_config_export.zip导入nacos。

进入具体的命名空间,点击“导入配置”

image-20230309140250256

打开导入窗口

image-20230309140325306

相同的配置跳过覆盖配置。

点击“上传文件”选择nacos_config_export.zip开始导入。

 远程服务器的记得修改rabbitmq-dev的ip地址~

搭建Gateway

本项目使用Spring Cloud Gateway作为网关,下边创建网关工程。

新建一个网关工程。

image-20230309141037907

项目结构如下

image-20230309141934603

添加依赖:

<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上配置网关路由策略:

image-20230309141606145

 

 minio

一个分布式存储数据的东西啦,如果学过大数据的话就应该知道Hadoop,里面的底层就是HDFS,模式为主从结构,而minio则是相反的去中心化模式,下面是官方点的介绍:

介绍

本项目采用MinIO构建分布式文件系统,MinIO 是一个非常轻量的服务,可以很简单的和其他应用的结合使用,它兼容亚马逊 S3 云存储服务接口,非常适合于存储大容量非结构化的数据,例如图片、视频、日志文件、备份数据和容器/虚拟机镜像等。

它一大特点就是轻量,使用简单,功能强大,支持各种平台,单个文件最大5TB,兼容 Amazon S3接口,提供了 Java、Python、GO等多版本SDK支持。

官网:https://min.io

中文:https://www.minio.org.cn/,http://docs.minio.org.cn/docs/

MinIO集群采用去中心化共享架构,每个结点是对等关系,通过Nginx可对MinIO进行负载均衡访问。

去中心化有什么好处?

在大数据领域,通常的设计理念都是无中心和分布式。Minio分布式模式可以帮助你搭建一个高可用的对象存储服务,你可以使用这些存储设备,而不用考虑其真实物理位置。

它将分布在不同服务器上的多块硬盘组成一个对象存储服务。由于硬盘分布在不同的节点上,分布式Minio避免了单点故障。如下图:

image-20230309164159781

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("下载成功");
        }

    }

}

看注释就看得懂了,可以修改下一些参数然后自己测试下,是没问题的。

posted @ 2024-02-02 06:21  何平安  阅读(131)  评论(0编辑  收藏  举报
浏览器标题切换end