Home
  • 计算机网络
  • 操作系统
  • 数据结构与算法
  • 设计模式
  • JavaSE
  • JVM
  • JUC
  • Netty
  • CPP
  • QT
  • UE
  • Go
  • Gin
  • Gorm
  • HTML
  • CSS
  • JavaScript
  • vue2
  • TypeScript
  • vue3
  • react
  • Spring
  • SpringMVC
  • Mybatis
  • SpringBoot
  • SpringSecurity
  • SpringCloud
  • Mysql
  • Redis
  • 消息中间件
  • RPC
  • 分布式锁
  • 分布式事务
  • 个人博客
  • 弹幕视频平台
  • API网关
  • 售票系统
  • 消息推送平台
  • SaaS短链接系统
  • Linux
  • Docker
  • Git
GitHub (opens new window)
Home
  • 计算机网络
  • 操作系统
  • 数据结构与算法
  • 设计模式
  • JavaSE
  • JVM
  • JUC
  • Netty
  • CPP
  • QT
  • UE
  • Go
  • Gin
  • Gorm
  • HTML
  • CSS
  • JavaScript
  • vue2
  • TypeScript
  • vue3
  • react
  • Spring
  • SpringMVC
  • Mybatis
  • SpringBoot
  • SpringSecurity
  • SpringCloud
  • Mysql
  • Redis
  • 消息中间件
  • RPC
  • 分布式锁
  • 分布式事务
  • 个人博客
  • 弹幕视频平台
  • API网关
  • 售票系统
  • 消息推送平台
  • SaaS短链接系统
  • Linux
  • Docker
  • Git
GitHub (opens new window)
  • 项目架构
  • 网络通信层
  • 注册中心
  • 配置中心
  • 过滤器链
  • 路由转发过滤器
  • 重试与限流
  • 熔断与降级
  • 用户鉴权
  • 缓存优化
    • 为什么使用缓存?
    • Caffeine性能为什么更好?
      • 分段锁
      • 内存淘汰策略
    • 过滤器链缓存
  • Disruptor缓冲区优化
  • 客户端—dubbo接口
  • 网关上下文
  • 负载均衡
  • API网关
Nreal
2024-03-04
目录

缓存优化

# 为什么使用缓存?

  • 减少后端服务器压力:网关通常负责处理大量的请求流量,并将请求路由到后端的服务。通过在网关上使用缓存,可以避免重复的请求传递给后端服务,从而减轻后端服务的压力;
  • 提高请求响应速度:缓存允许网关快速返回之前存储的响应,而无需再次向后端服务发起请求;
  • 增强系统可用性:当后端服务发生故障或不可用时,缓存可以继续提供之前缓存的响应,保障系统的一部分功能仍然可用,有助于降低单点故障风险;

# Caffeine性能为什么更好?

# 分段锁

将缓存的键值对存储在多个分段中,每个分段独立加锁,以提高并发性;这使得在多线程环境下,多个线程可以同时读取不同的分段,从而减小了锁的粒度,提高了并发读取的性能;

# 内存淘汰策略

Window Tiny LFU算法,进一步提高了内存淘汰策略的效率和精确性;

W-TinyLFU 算法的主要特点和原理:

  • 基于Counter的访问频率追踪: W-TinyLFU 和 TinyLFU 一样,通过使用计数器来追踪每个缓存项的访问频率。每个缓存项都有一个计数器,表示它被访问的次数。
  • Adaptive Counting: W-TinyLFU 使用 Adaptive Counting(自适应计数)的方式,而不是传统的精确计数。Adaptive Counting 允许在占用更小空间的情况下估计元素的访问频率。这对于大规模的缓存系统来说是一种效率优化。
  • 时间窗口: W-TinyLFU 引入了时间窗口的概念,将计数器的增加限制在一个固定的时间窗口内。这个时间窗口可以是固定大小的,也可以是根据缓存的大小和访问模式动态调整的。这样做的目的是适应访问模式的变化,让缓存更加灵活地适应不同的工作负载。
  • 定期清零计数器: 在时间窗口的末尾,W-TinyLFU 对所有计数器进行一次定期清零操作。这意味着在每个时间窗口内,计数器只反映了最近一段时间内的访问情况。这样可以防止计数器过于陈旧,更好地适应动态变化的访问模式。
  • 缓存淘汰策略: W-TinyLFU 根据计数器的值来选择淘汰缓存项。具有较低计数器值的缓存项更容易被淘汰,以保留访问频率较高的缓存项。

# 过滤器链缓存

根据固定的请求信息,缓存固定的过滤器链,避免每次请求进入后都需要根据完整的请求信息去构建过滤器链;

/**
 * 使用Caffeine缓存 并且设定过期时间10min
 */
private Cache<String,GatewayFilterChain> chainCache = Caffeine.newBuilder().recordStats().expireAfterWrite(10, TimeUnit.MINUTES).build();

@Override
public GatewayFilterChain buildFilterChain(GatewayContext ctx) throws Exception {
    return chainCache.get(ctx.getRule().getId(),k->doBuildFilterChain(ctx.getRule()));
}



public GatewayFilterChain doBuildFilterChain(Rule rule) {
    GatewayFilterChain chain = new GatewayFilterChain();
    List<Filter> filters = new ArrayList<>();
    //filters.add(getFilterInfo(FilterConst.GRAY_FILTER_ID));
    //filters.add(getFilterInfo(FilterConst.MONITOR_FILTER_ID));
    //filters.add(getFilterInfo(FilterConst.MONITOR_END_FILTER_ID));
    //filters.add(getFilterInfo(FilterConst.MOCK_FILTER_ID));
    if(rule != null){
        Set<Rule.FilterConfig> filterConfigs =   rule.getFilterConfigs();
        Iterator iterator = filterConfigs.iterator();
        Rule.FilterConfig filterConfig;
        while(iterator.hasNext()){
            filterConfig = (Rule.FilterConfig)iterator.next();
            if(filterConfig == null){
                continue;
            }
            String filterId = filterConfig.getId();
            if(StringUtils.isNotEmpty(filterId) && getFilterInfo(filterId) != null){
                Filter filter = getFilterInfo(filterId);
                filters.add(filter);
            }
        }
    }
    //添加路由过滤器-这是最后一步
    filters.add(getFilterInfo(FilterConst.ROUTER_FILTER_ID));
    //排序
    filters.sort(Comparator.comparingInt(Filter::getOrder));
    //添加到链表中
    chain.addFilterList(filters);
    return chain;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
用户鉴权
Disruptor缓冲区优化

← 用户鉴权 Disruptor缓冲区优化→

Theme by Vdoing | Copyright © 2021-2024
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式