Skip to content

性能基准测试

概述

CoSky 通过将 Redis 作为底层存储与本地进程内一致性缓存相结合(通过 Redis PubSub 保持同步),实现了卓越的吞吐量。以下基准测试结果使用 JMH(Java Microbenchmark Harness)获得,证明一致性层为配置读取带来了 800 倍以上的提升,为服务发现带来了 250 倍以上的提升,与标准 Redis 操作相比。本文档记录了基准测试方法、环境、原始结果以及一致性层如此快速的架构解释。

基准测试方法

所有基准测试使用 JMH (Java Microbenchmark Harness) 版本 1.29 进行。每个基准测试运行配置为:

  • 模式:吞吐量(thrpt
  • 线程:25-50 个并发线程
  • 预热:1 次迭代,10 秒
  • 测量:1 次迭代,10 秒
  • Forks:1

CI 流水线通过 GitHub Actions 在每次推送时运行基准测试,为每次提交启用性能回归检测。

mermaid
flowchart LR
    subgraph ci_pipeline["CI 基准测试流水线"]
        style ci_pipeline fill:#161b22,stroke:#30363d,color:#e6edf3
        P["推送事件"] --> CH["代码检出"]
        CH --> JDK["设置 JDK 17"]
        JDK --> R["启动 Redis 服务"]
        R --> J1["gradle cosky-config:jmh"]
        R --> J2["gradle cosky-discovery:jmh"]
        J1 --> R1["配置基准测试结果"]
        J2 --> R2["发现基准测试结果"]
    end

    P:::node
    CH:::node
    JDK:::node
    R:::node
    J1:::node
    J2:::node
    R1:::node
    R2:::node

    classDef node fill:#2d333b,stroke:#6d5dfc,color:#e6edf3

测试环境

组件规格
硬件MacBook Pro (Apple M1)
JDKZulu 11.0.11 (OpenJDK 64-Bit Server VM)
Redis部署在同一台机器上
JMH 版本1.29
方法thrpt 模式,50 线程,1 fork,10 秒预热 + 测量

配置服务基准测试

bash
# 运行配置基准测试
gradle cosky-config:jmh
# 或直接使用 JMH jar
java -jar cosky-config/build/libs/cosky-config-lastVersion-jmh.jar \
  -bm thrpt -t 25 -wi 1 -rf json -f 1
基准测试模式得分单位提升
ConsistencyRedisConfigServiceBenchmark.getConfigthrpt256,733,987ops/s1,062 倍
RedisConfigServiceBenchmark.getConfigthrpt241,787ops/s基准
RedisConfigServiceBenchmark.setConfigthrpt140,461ops/s-

服务发现基准测试

bash
# 运行发现基准测试
gradle cosky-discovery:jmh
# 或直接使用 JMH jar
java -jar cosky-discovery/build/libs/cosky-discovery-lastVersion-jmh.jar \
  -bm thrpt -t 25 -wi 1 -rf json -f 1
基准测试模式得分单位提升
ConsistencyRedisServiceDiscoveryBenchmark.getInstancesthrpt76,621,729ops/s338 倍
ConsistencyRedisServiceDiscoveryBenchmark.getServicesthrpt455,760,632ops/s1,495 倍
RedisServiceDiscoveryBenchmark.getInstancesthrpt226,909ops/s基准
RedisServiceDiscoveryBenchmark.getServicesthrpt304,979ops/s基准
RedisServiceRegistryBenchmark.registerthrpt110,664ops/s-
RedisServiceRegistryBenchmark.deregisterthrpt255,305ops/s-
RedisServiceRegistryBenchmark.renewthrpt210,960ops/s-

性能对比图

以下图表比较了标准 Redis 操作与一致性缓存层的性能。注意对数刻度 -- 一致性层的性能高出数个数量级。

mermaid
xychart-beta
    title "配置服务:标准模式 vs 一致性模式 (ops/s)"
    x-axis ["getConfig (Redis)", "setConfig (Redis)", "getConfig (一致性)"]
    y-axis "每秒操作数" 0 --> 260000000
    bar [241787, 140461, 256733987]

一致性层为何更快

关键架构洞察在于一致性层从内存中的 ConcurrentHashMap 缓存读取,而不是进行 Redis 网络往返。缓存通过 Redis PubSub 实时同步,因此它始终反映最新状态而无需轮询。

mermaid
flowchart TB
    subgraph redis_path["标准 Redis 路径"]
        style redis_path fill:#161b22,stroke:#30363d,color:#e6edf3
        A1["客户端请求"] -->|"1. 网络往返"| R1["Redis"]
        R1 -->|"2. 响应"| A1
    end
    subgraph cache_path["一致性缓存路径"]
        style cache_path fill:#161b22,stroke:#30363d,color:#e6edf3
        A2["客户端请求"] -->|"1. 读取本地缓存"| C["ConcurrentHashMap<br>(进程内)"]
        C -->|"2. 立即返回"| A2
        R2["Redis PubSub"] -->|"异步:缓存失效"| C
    end

    A1:::node
    R1:::node
    A2:::node
    C:::node
    R2:::node

    classDef node fill:#2d333b,stroke:#6d5dfc,color:#e6edf3

一致性层架构

ConsistencyRedisServiceDiscovery 类包装了标准的 ServiceDiscovery 委托,并通过基于 Redis PubSub 的失效机制添加了本地缓存:

mermaid
sequenceDiagram
    autonumber
    participant C as 客户端
    participant CRD as ConsistencyRedisServiceDiscovery
    participant Cache as ConcurrentHashMap 缓存
    participant RSD as RedisServiceDiscovery
    participant Redis as Redis
    participant PubSub as Redis PubSub

    Note over CRD,PubSub: 缓存初始化(首次调用)
    C->>CRD: getInstances(namespace, serviceId)
    CRD->>Cache: computeIfAbsent(key)
    Cache-->>CRD: 缓存未命中
    CRD->>PubSub: 订阅实例变更
    CRD->>RSD: delegate.getInstances()
    RSD->>Redis: SMEMBERS / GET
    Redis-->>RSD: 实例列表
    RSD-->>CRD: Flux~ServiceInstance~
    CRD->>Cache: 存储为 CopyOnWriteArraySet
    CRD-->>C: Flux~ServiceInstance~

    Note over CRD,PubSub: 后续调用(缓存命中)
    C->>CRD: getInstances(namespace, serviceId)
    CRD->>Cache: get(key)
    Cache-->>CRD: 缓存的实例
    CRD-->>C: Flux~ServiceInstance~(无 Redis 调用)

    Note over CRD,PubSub: 通过 PubSub 缓存失效
    Redis->>PubSub: 实例变更事件
    PubSub->>CRD: onInstanceChanged(event)
    CRD->>Cache: 更新 CopyOnWriteArraySet

缓存失效事件

一致性层处理多种类型的实例变更事件,每种事件触发特定的缓存更新策略:

mermaid
stateDiagram-v2
    direction LR
    [*] --> Cached: 首次从 Redis 读取
    Cached --> Updated: REGISTER 事件
    Cached --> Updated: SET_METADATA 事件
    Cached --> TTLRefreshed: RENEW 事件
    Cached --> Removed: DEREGISTER 事件
    Cached --> Removed: EXPIRED 事件
    Updated --> Cached: 从 Redis 刷新
    TTLRefreshed --> Cached: 就地更新 TTL
    Removed --> [*]: 从缓存移除

    state Cached {
        [*] --> InMemory: ConcurrentHashMap
        InMemory --> InMemory: 读取(无网络)
    }

如何在本地运行基准测试

前提条件

  • 已安装 JDK 17+
  • Redis 在本地运行,端口 6379

配置基准测试

bash
# 运行完整的配置基准测试套件
./gradlew cosky-config:jmh

# 使用自定义线程数运行
./gradlew cosky-config:jmh -PjmhThreads=10

# 运行特定基准测试
java -jar cosky-config/build/libs/cosky-config-*-jmh.jar \
  -bm thrpt \
  -t 25 \
  -wi 1 \
  -rf json \
  -f 1 \
  -p CONFIG_ID=my-config

发现基准测试

bash
# 运行完整的发现基准测试套件
./gradlew cosky-discovery:jmh

# 使用自定义线程数运行
./gradlew cosky-discovery:jmh -PjmhThreads=10

注意:上述 JMH 基准测试结果是在 MacBook Pro (M1) 上使用本地部署的 Redis 获得的。在 GitHub Actions 运行器上运行相同的基准测试,由于共享资源限制,得分大约低 2 倍。然而,标准操作与一致性操作之间的相对比较在任何环境中都是有效的。

与竞品的功能对比

功能CoSkyEurekaConsulCoreDNSZookeeperNacosApollo
CAPCP+APAPCPCPCPCP+APCP+AP
健康检查客户端心跳客户端心跳TCP/HTTP/gRPCKeep AliveKeep AliveTCP/HTTP/客户端心跳客户端心跳
负载均衡权重/选择器RibbonFabioRoundRobinRoundRobin权重/元数据RoundRobin
自动注销
访问协议HTTP/RedisHTTPHTTP/DNSDNSTCPHTTP/DNSHTTP
监听支持
多数据中心
跨注册中心同步
Spring Cloud
K8S 集成
持久化Redis----MySQLMySQL

关键洞察

  • 通过一致性层的配置读取达到 2.56 亿 ops/s -- 相比直接 Redis 读取的 24.1 万 ops/s,提升了 1,062 倍
  • 通过一致性层的服务发现达到 7660 万 ops/s(实例)和 4.56 亿 ops/s(服务)-- 分别提升了 338 倍和 1,495 倍
  • 写操作(register、deregister、renew、setConfig)受 Redis 网络延迟限制,达到 11 万 - 25.5 万 ops/s
  • 一致性层的性能优势来自用内存中的 ConcurrentHashMap 查找替代网络往返,通过 Redis PubSub 保持同步
  • CoSky 的混合 CP+AP 模型既为写入提供了强一致性,又为读取提供了最终一致性和极致的读取性能。
mermaid
flowchart LR
    subgraph perf_overview["性能特征"]
        style perf_overview fill:#161b22,stroke:#30363d,color:#e6edf3
        subgraph consistency_layer["读取 - 一致性层"]
            style consistency_layer fill:#161b22,stroke:#30363d,color:#e6edf3
            C1["配置 getConfig<br>2.56 亿 ops/s"]
            C2["发现 getInstances<br>7660 万 ops/s"]
            C3["发现 getServices<br>4.56 亿 ops/s"]
        end
        subgraph standard_redis["读取 - 标准 Redis"]
            style standard_redis fill:#161b22,stroke:#30363d,color:#e6edf3
            R1["配置 getConfig<br>24.1 万 ops/s"]
            R2["发现 getInstances<br>22.6 万 ops/s"]
            R3["发现 getServices<br>30.5 万 ops/s"]
        end
        subgraph writes["写入"]
            style writes fill:#161b22,stroke:#30363d,color:#e6edf3
            W1["setConfig<br>14 万 ops/s"]
            W2["register<br>11 万 ops/s"]
            W3["deregister<br>25.5 万 ops/s"]
            W4["renew<br>21 万 ops/s"]
        end
    end

    C1:::node
    C2:::node
    C3:::node
    R1:::node
    R2:::node
    R3:::node
    W1:::node
    W2:::node
    W3:::node
    W4:::node

    classDef node fill:#2d333b,stroke:#6d5dfc,color:#e6edf3

相关页面

参考

基于 Apache License 2.0 许可发布。