• fileserverMinio(进行中)


    fileserver

    1,功能概述

    在公司做需求开发的时候独立做过一个文件管理微服务(fileserver这个也是我开发的第一个组件),当时有几个缺点:

    • 没有做负载均衡
    • 没有联合文件索引系统
    • api接口定义不太完善
    • 没有做热点数据处理
    • 没有做断点续传
    • 只支持minio实现
    • 没有使用到零拷贝技术
    • 没有考虑到select\poll\epoll技术

    优点:

    • 预览功能,支持word、xml、pdf、图片、html、json等
    • 功能稳定、日志全面
    • 部署方便
    • 支持docker容器化、k8s部署
    • 日志清晰

    http://47.98.35.29:8099/acfileserver/swagger-ui.html#/
    http://47.98.35.29:8500

    由于公司的代码不能拿出来二次开发,所以我这边抽时间自己重新开发一遍,并且优化上述缺点。

    当前开发分支:V1.0.1

    更新说明:

    • 使用md5码实现union filesystem
    • 集成redis+caffeine热点数据缓存
    • 集成支持阿里云oss实现文件的上传下载

    2,构架描述

    整体概览:

    image-20220309004131262

    service解耦与多实现:

    image-20220309004303993

    通过fileCode获取实体文件(参考docker的联合文件索引):

    image-20220309004226163

    使用技术:

    springBoot、minio、postgres、redis、caffeine、swagger

    2.1,上传文件:

    ​ 上传文件包括更新文件操作,上传文件的【操作频率相对较低】!

    ​ 先在数据库中查询一下,是否已存在该文件,如果存在且一致,则新增索引(不重复上传文件浪费内存)!

    2.2,下载文件:

    ​ 下载文件包括预览操作(只有特定格式的文件格式才支持预览操作),下载文件的操作频率相对较高需要考虑高并发与防止攻击的情况!

    ​ 外部请求进入系统:

    ​ ①先保存ip信息,校验是否是非法攻击;

    ​ ②查询Redis中是否存在该数据,如果存在则直接下载并阅览值+1,退出;否则,进入pg库查询,查询出结果则直接下载并将该数据(小于5mb)刷新至Redis;

    ​ ③Redis使用caffeine高性能缓存进行热点数据操作!

    3,实现难点

    4,web接口说明

    5,细节

    5.1,flyway

    ​ base是数据库表修改目录、patch是数据修改目录

    6,遇到问题解决

    6.1,minio启动报错(已解决)

    ***************************
    APPLICATION FAILED TO START
    ***************************
    
    Description:
    
    An attempt was made to call a method that does not exist. The attempt was made from the following location:
    
        io.minio.S3Base.<clinit>(S3Base.java:105)
    
    The following method did not exist:
    
        okhttp3.RequestBody.create([BLokhttp3/MediaType;)Lokhttp3/RequestBody;
    
    The method's class, okhttp3.RequestBody, is available from the following locations:
    
        jar:file:/D:/apache-maven-3.6.3/repo/com/squareup/okhttp3/okhttp/3.14.9/okhttp-3.14.9.jar!/okhttp3/RequestBody.class
    
    It was loaded from the following location:
    
        file:/D:/apache-maven-3.6.3/repo/com/squareup/okhttp3/okhttp/3.14.9/okhttp-3.14.9.jar
    

    minio使用的最新版,但是其依赖的okhttp版本不是最新的,重新引用依赖即可解决

            <!-- minio文件 -->
            <dependency>
                <groupId>io.minio</groupId>
                <artifactId>minio</artifactId>
                <version>8.3.6</version>
            </dependency>
            <dependency>
                <groupId>com.squareup.okhttp3</groupId>
                <artifactId>okhttp</artifactId>
                <version>4.9.3</version>
            </dependency>
    

    6.2,mybatis 转义符(已解决)

    mapper文件格式为 xml

    <、>符号是特殊的保留符号,必须通过转译才能使用

    <![CDATA[符号未知]]>
    样例:
    <![CDATA[<]]>   <![CDATA[>]]>
    

    6.3,获取请求者的真实ip(未解决)

        public String getIpAddr(HttpServletRequest request) {
            String ip = null;
            // 处理代理情况
            ip = request.getHeader("x-forwarded-for");
            if (!StringUtils.hasLength(ip) || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("Proxy-Client-IP");
            }
            if (!StringUtils.hasLength(ip) || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getHeader("WL-Proxy-Client-IP");
            }
            if (!StringUtils.hasLength(ip) || "unknown".equalsIgnoreCase(ip)) {
                ip = request.getRemoteAddr();
                if (ip.equals("127.0.0.1")) {
                    InetAddress inet = null;// 根据网卡取本机配置的IP
                    try {
                        inet = InetAddress.getLocalHost();//idea-PC/192.168.212.144
                    } catch (UnknownHostException e) {
                        e.printStackTrace();
                    }
                    ip = inet.getHostAddress();//192.168.212.144
                }
            }
            // 对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割,多级代理的时候会得到多个以,分割的ip,
            //这时候第一个是真实的客户端ip
            if (ip != null && ip.length() > 15) { // "***.***.***.***".length()
                if (ip.indexOf(",") > 0) {
                    ip = ip.substring(0, ip.indexOf(","));
                }
            }
            return ip;
        }
    

    但是,使用frp网络代理依然没办法直接获取到真实ip地址

    6.4,jmeter聚合报告导出时乱码的解决(已解决)

    先使用记事本打开后,选择编码格式后,得新保存既可

    使用编码器打开后选择另存为,将编码从原来的UTF-8改变成ANSI格式。

    再次使用excel打开就可以正常显示中文了

    6.5,预览md文件格式中文乱码(待)

    6.6,视频播放功能(待)

    6.7,swagger-ui 3.0.0无法显示(待)

    该问题其实可以跳过去,但是又想研究研究

    6.8,frp代理本地127.0.0.1的端口进行tcp连接被拒绝(已解决)

    frpc中的本地ip不能直接配置为127.0.0.1,需要使用真实ip(例如window中的ipconfig、linux中的ip addr查看)

    6.9,systemLog日志记录请求url、参数等(已解决)

    6.10,spring.profiles.active不生效(已解决)

    target中的classes/config目录中没有正常生成配置文件

    image-20220226002619102

    6.11,WARN s.d.s.w.readers.parameter.ParameterDataTypeReader(已解决)

    日志警告:

    2022-02-26 00:25:07.914 [main] WARN  s.d.s.w.readers.parameter.ParameterDataTypeReader - Trying to infer dataType java.util.List<java.lang.String>
    

    原因(未使用spring规定的基本类型接受前端传送来的数据):

        @ApiOperation(value = "批量删除")
        @GetMapping("/deleteBatchByGet")
        @ResponseBody
        public BaseResponse deleteBatchByGet(List<String> fileCodeList) {
           fileService.deleteBatch(fileCodeList);
            return success("批量删除");
        }
    

    修改为List[] fileCodeList即可消除警告

    6.12,阿里云oss bucket连接权限不够(待)

    不能够直接通过java SDK创建bucket!

    当前是直接在阿里云OSS官网上手动创建的bucket,直接调用上传是成功的!

    阿里云OSS自己的一个缺陷吧!我直接连接北京的节点不能创建bucket,要求我必须使用杭州的节点!

    [ErrorCode]: AccessDenied
    [RequestId]: 621B67A25B40CC383520371F
    [HostId]: test.oss-cn-beijing.aliyuncs.com
    [ResponseError]:
    <?xml version="1.0" encoding="UTF-8"?>
    <Error>
      <Code>AccessDenied</Code>
      <Message>The bucket you are attempting to access must be addressed using the specified endpoint. Please send all future requests to this endpoint.</Message>
      <RequestId>621B67A25B40CC383520371F</RequestId>
      <HostId>test.oss-cn-beijing.aliyuncs.com</HostId>
      <Bucket>test</Bucket>
      <Endpoint>oss-cn-hangzhou.aliyuncs.com</Endpoint>
    </Error>
    

    备注:后续专门出一篇相关api接口研究的博文

    7,性能调优

    7.1,V1.0.0版本 2022.02.20

    更新说明:

    • 项目基础实体类、工具类、web相关代码编写
    • 集成springBoot、minio、postgres、redis、swagger

    输入文件code——查询PG数据库——调用minio——返回

    Label # 样本 平均值 最小值 最大值 标准偏差 异常 % 吞吐量 接收 KB/sec 发送 KB/sec 平均字节数
    HTTP请求 1000 4432 260 5993 1066.56 0.00% 143.4103 47810.67 27.17 341385
    总体 1000 4432 260 5993 1066.56 0.00% 143.4103 47810.67 27.17 341385

    并发:1000

    接收:46.68MB/sec

    平均响应时间:4.432s

    可以优化的点:

    • 查询code的逻辑:使用热点数据缓存redis+caffeine
    • 异步操作:除核心操作以外,其他操作异步执行

    7.2,V1.0.1版本

    更新说明:

    • 使用md5码实现union filesystem
    • 集成redis+caffeine热点数据缓存
    • 集成阿里云oss实现文件的上传下载

    8,参考链接

    该项目的github仓库地址:https://github.com/mufasa007/fileserverMinio.git

    1,jmeter聚合报告导出时乱码的解决

    2,阿里云OSS 官网api文档

  • 相关阅读:
    笔记——文档在线阅读的解决方案(未完待续)
    杂记之web篇
    对针对接口编程的理解
    汇编笔记之 ret 、retf和call
    electron桌面应用
    wepack打包时出错不压缩代码及使用es7(async await)新语法问题
    npm install 时发生错误
    create-react-app 后使用babel/polyfill
    webpack3.x--react,jsx多页配置
    webpack--打包scss
  • 原文地址:https://www.cnblogs.com/Mufasa/p/15916915.html
Copyright © 2020-2023  润新知