智能BI(后端)-- 系统优化(安全性,数据存储,限流)

文章目录

安全性

问题引入:如果用户上传一个超大的文件怎么办?比如1000G?

预防:
只要涉及到用户自主上传的操作,一定要校验文件(图像)

校验什么?

  • 文件的大小
  • 文件的后缀
  • 文件的内容(成本高一点)
  • 文件的合规性,比如敏感内容(建议用第三方审核功能),todo 接入腾讯云的图片万象数据审核(COS对象存储的审核功能)

代码校验实现:

java 复制代码
        //校验文件大小
        long ONE_MB = 1024 * 1024l;
        long size = multipartFile.getSize();
        ThrowUtils.throwIf(size > ONE_MB,ErrorCode.PARAMS_ERROR,"文件过大");
        //校验后缀名
        String originalFilename = multipartFile.getOriginalFilename();
        String suffix = FileUtil.getSuffix(originalFilename);
        List<String> validSuffix = Arrays.asList("png","jpg","svg","webp","jpeg");
        ThrowUtils.throwIf(!validSuffix.contains(suffix),ErrorCode.PARAMS_ERROR,"文件后缀非法");

todo 数据存储

现状:我们把每个图表的原始数据全部放在了同一个数据表(chart表)的字段里

问题:

  1. 如果用户上传的原始数据量很大,图表数日益增多,查询chart表就会很慢
  2. 对于BI平台,用户是有查看原始数据,对原始数据进行简单查询的需求的,现在如果把所有数据放在一个字段(列)中,查询时,只能取出这个列的所有内容

**解决方案:分库分表:

**把每个图表对应的原始数据单独保存为一个新的数据表,而不是都存在一个字段里

优点:

  1. 存储时,能够分开存储,互不影响(也能增加安全性)
  2. 查询时,可以使用各种sql语句灵活取出需要的字段,查询性能更快

todo 实现:动态sql,这里鱼皮也实现了,不过没有应用,只是测试,等等复习下知识再说

限流

现在的问题 :使用系统是需要消耗成本的,用户有可能疯狂刷量,让你破产
解决问题:

  1. 控制成本 -> 限制用户调用总次数
  2. 用户在短时间内疯狂使用,导致服务器资源被占满,其他用户无法使用->限流

思考:限流阈值多大合适?参考正常用户的使用,比如限制单个用户在每秒只能使用一次

限流的几种算法

  1. 固定窗口限流
  2. 滑动窗口限流
  3. 漏桶限流
  4. 领令牌桶限流

限流粒度

  1. 针对某个方法限流
  2. 针对某个用户限流
  3. 针对用户调用某个方法限流

限流的实现

本地限流(单机限流)

每个服务器单独限流,一般适用于单体项目,你的项目只有一个服务器

Guava RateLimiter

java 复制代码
import com.google.common.util.concurrent.RateLimiter;

public static void main(String[] args) {
    // 每秒限流5个请求
    RateLimiter limiter = RateLimiter.create(5.0);
    while (true) {
        if (limiter.tryAcquire()) {
            // 处理请求
        } else {
            // 超过流量限制,需要做何处理
        }
    }
}

Redisson实现分布式限流(多机限流)

[官方项目仓库和文档]

  1. 引入依赖
java 复制代码
<dependency>
   <groupId>org.redisson</groupId>
   <artifactId>redisson</artifactId>
   <version>3.28.0</version>
</dependency>  
  1. 创建Redisson配置类
java 复制代码
package com.yupi.springbootinit.config;

import io.lettuce.core.RedisClient;
import io.swagger.models.auth.In;
import lombok.Data;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@ConfigurationProperties("spring.redis")
@Data
public class RedissonConfig {

    private Integer database;

    private String host;

    private Integer port;

    // spring启动时,会自动创建一个RedissonClient对象
    @Bean
    public RedissonClient getRedissonClient() {
        // 1.创建配置对象
        Config config = new Config();
        // 2. 添加单机Redisson配置
        config.useSingleServer()
        // 设置数据库
                .setDatabase(1)
        //设置redis的地址
                .setAddress("redis://" + host + ":" + port);
        //3..创建Redisson实例
        RedissonClient redissonClient = Redisson.create(config);
        return redissonClient;
    }

}
  1. 创建通用限流管理类RedisLimiterManager

(专门提供 RedisLimiter 限流基础服务),manager包存放通用模版,没有业务逻辑,可以放在任何一个项目里

java 复制代码
package com.yupi.springbootinit.manager;

import com.yupi.springbootinit.common.ErrorCode;
import com.yupi.springbootinit.exception.BusinessException;
import org.redisson.api.RRateLimiter;
import org.redisson.api.RateIntervalUnit;
import org.redisson.api.RateType;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

@Service
public class RedisLimiterManager {
    @Resource
    private RedissonClient redissonClient;

    public void doRateLimit(String key){
        // 创建一个名称为rateLimiter的限流器
        RRateLimiter rateLimiter = redissonClient.getRateLimiter(key);
        // 限流器的统计规则(每秒2个请求;连续的请求,最多只能有1个请求被允许通过)
        // RateType.OVERALL表示速率限制作用于整个令牌桶,即限制所有请求的速率
        rateLimiter.trySetRate(RateType.OVERALL,2,1, RateIntervalUnit.SECONDS);
        // 每当一个操作来了后,请求一个令牌
        boolean canop = rateLimiter.tryAcquire(1);
        // 如果没有令牌,还想执行操作,就抛出异常
        if(!canop){
            throw new BusinessException(ErrorCode.TOO_MANY_REQUEST);
        }

    }
}
  1. 测试后整合进项目(一行代码解决)
java 复制代码
 //限流判断,每个用户一个限流器
redisLimiterManager.doRateLimit("genChartByAi_" + loginUser.getId());
相关推荐
一颗花生米。19 分钟前
深入理解JavaScript 的原型继承
java·开发语言·javascript·原型模式
问道飞鱼20 分钟前
Java基础-单例模式的实现
java·开发语言·单例模式
热爱嵌入式的小许3 小时前
Linux基础项目开发1:量产工具——显示系统
linux·运维·服务器·韦东山量产工具
ok!ko4 小时前
设计模式之原型模式(通俗易懂--代码辅助理解【Java版】)
java·设计模式·原型模式
2402_857589364 小时前
“衣依”服装销售平台:Spring Boot框架的设计与实现
java·spring boot·后端
吾爱星辰5 小时前
Kotlin 处理字符串和正则表达式(二十一)
java·开发语言·jvm·正则表达式·kotlin
yufei-coder5 小时前
掌握 C# 中的 LINQ(语言集成查询)
windows·vscode·c#·visual studio
哎呦没6 小时前
大学生就业招聘:Spring Boot系统的架构分析
java·spring boot·后端
编程、小哥哥6 小时前
netty之Netty与SpringBoot整合
java·spring boot·spring
IT学长编程7 小时前
计算机毕业设计 玩具租赁系统的设计与实现 Java实战项目 附源码+文档+视频讲解
java·spring boot·毕业设计·课程设计·毕业论文·计算机毕业设计选题·玩具租赁系统