使用NetACC加速TCP应用

对于对网络通信性能要求高、需要低延迟和高吞吐量的TCP应用,如果需要使用eRDMA加速网络通信,可以通过NetACC,无需修改应用代码即可适配eRDMA。本文为您介绍NetACC及其使用方法。

重要

NetACC当前处于公测阶段。

NetACC简介

NetACC(Network Accelerator)是一个用户态网络加速库,利用eRDMA的低时延、高吞吐等优势,通过兼容socket接口,实现对现有TCP应用的加速。

适用场景

NetACC适用于网络开销较大的场景:

  • 高PPS(Packets per Second)场景:尤其是大量收发小包的场景。使用NetACC可以降低CPU开销,提升系统吞吐能力,例如在Redis处理请求的场景中。

  • 对网络时延敏感的场景:eRDMA的网络时延比TCP更低,可以提升网络响应速度。

  • 反复创建短连接的场景:NetACC可以优化二次连接的速度,加快连接速度,提升系统性能。

安装NetACC

  • 安装方式

    • 通过eRDMA驱动安装

      安装eRDMA驱动时候,NetACC也会一并安装。关于eRDMA驱动的安装,请参见为已有实例配置eRDMA

    • 单独安装

      如果您需要使用特定版本的NetACC或者您需要临时使用NetACC等,您可以在ECS实例上执行以下命令,单独安装NetACC:

      sudo curl -fsSL https://netacc-release.oss-cn-hangzhou.aliyuncs.com/release/netacc_download_install.sh | sudo sh
  • 配置文件

    安装NetACC后默认配置文件是/etc/netacc.conf,您可以在配置文件中配置NetACC的使用参数,如线程数、日志路径等。配置文件示例如下:

    /etc/netacc.conf文件示例

    [netacc]
    # 一个buffer的size,一般发送数据块较大时适当调大这个参数可以提高性能;调小可以节省内存。
    # int
    NACC_SOR_MSG_SIZE=16384
    
    # rdma首次注册的mr大小,调小可以节省内存
    #   NACC_SOR_MSG_SIZE的2的N次幂倍,最小为1倍
    NACC_RDMA_MR_MIN_INC_SIZE=16384
    
    # rdma最大单次注册的mr大小(1MB ~ 512MB),调小可以节省内存
    #   NACC_RDMA_MR_MIN_INC_SIZE的2的N次幂倍,最小为1倍,最大为512M
    NACC_RDMA_MR_MAX_INC_SIZE=8388608
    
    # 单个QP承载的链接数,适当调大可以优化性能;特殊场景只能调成1
    # int
    NACC_SOR_CONN_PER_QP=1
    
    # netacc的线程数,如果吞吐较大可以适当增加
    # int
    NACC_SOR_IO_THREADS=1
    
    # 空QP淘汰时间,单位ms,0代表立即淘汰,-1代表不会淘汰
    NACC_EMPTY_QP_EXPIRE_MS=60000
    
    # 允许存在的空QP总数
    NACC_EMPTY_QP_MAX_ALL=100
    
    # 每个目的地址允许存在的空QP总数
    NACC_EMPTY_QP_MAX_PER=10
    
    # connect使用rdma建连的概率,0 ~ 100
    NACC_CONNECT_RDMA_PERCENT=100
    
    # 是否默认开启RDMA
    NACC_ENABLE_RDMA_DEFAULT=1
    
    # 日志级别
    # 0: TRACE
    # 1: DEBUG
    # 2: INFO
    # 3: WARN
    # 4: ERROR
    # 5: FATAL
    NACC_LOG_LEVEL=3
    
    # 日志路径
    NACC_LOG_PATH="/tmp/netacc.log"
    
    # 下面是不常用或者不需要设置的参数
    
    # 线程亲和性设置
    # string
    NACC_SOR_AFFINITY=""
    
    # 是否优先使用TCP创建链接
    # bool
    NACC_CONN_TCP_FIRST=0

使用NetACC

您可以通过netacc_run命令或者设置环境变量LD_PRELOAD的方式在应用中集成NetACC。

netacc_run命令

netacc_run是一个工具,用于启动应用程序时加载NetACC库,通过在应用程序命令之前增加netacc_run,用户可以比较方便地启动应用程序并应用NetACC加速。

netacc_run提供了很多配置选项,比如IO线程数(-t)、QP复用数(-p)等,这些参数可以帮助优化NetACC的性能。通过netacc_run命令设置的参数会覆盖配置文件中的参数。

netacc_run命令参数说明

netacc_run -h
Usage: netacc_run [ OPTIONS ] COMMAND

Run COMMAND using NetACC for TCP sockets

OPTIONS:
   -f <path>   set config file, default /etc/netacc.conf
   -p <num>    set max connections per QP, default 1
   -t <num>    set netacc io threads, default 4
   -s <num>    set netacc message size, default 16384
   -F <num>    fast connect mode, default 0
   -d          enable debug mode
   -T          use TCP first in connect
   -P <num>    polling cq time ms
   -A <str>    affinity CPU list, 0 | 1-3 | 1,3,4
   -i <num>    set cq comp_vector, default 0
   -h          display this message
   -v          display version info
  • 使用示例:

    以本文中Redis应用为例,在Redis命令之前增加netacc_run即可实现应用NetACC。

    • 启动Redis服务

      netacc_run redis-server
    • 启动Redis基准测试

      netacc_run redis-benchmark

设置LD_PRELOAD环境变量

LD_PRELOAD是一个环境变量,用于指定在程序启动时预先加载的共享库。如果您需要在脚本中自动化NetACC的加载,您可以通过LD_PRELOAD指定NetACC加速库。

  1. 执行以下命令,查看NetACC动态库的位置:

    ldconfig -p | grep netacc

    返回信息如下所示:

    image

  2. 执行以下命令,设置LD_PRELOAD环境变量来指定预加载库:

    LD_PRELOAD=/lib64/libnetacc-preload.so your_application

    此处your_application是您想要加速的应用程序。

    使用示例:以本文中Redis应用常用命令为例:

    • 启动Redis服务

      LD_PRELOAD=/lib64/libnetacc-preload.so redis-server
    • 启动Redis基准测试

      LD_PRELOAD=/lib64/libnetacc-preload.so redis-benchmark

    在脚本中设置LD_PRELOAD环境变量

    如果您经常需要使用NetACC加速某个应用程序,或者您希望通过脚本统一管理多个应用程序在启动时候利用NetACC进行网络加速,您可以在脚本中设置LD_PRELOAD环境变量。例如,您可以创建一个名为run_with_netacc的脚本:

    #!/bin/bash
    LD_PRELOAD=/lib64/libnetacc-preload.so $@

    然后,您可以通过执行以下命令,运行应用程序:

    ./run_with_netacc.sh your_application

    使用示例:以本文中Redis应用常用命令为例:

    • 启动Redis服务

      ./run_with_netacc.sh redis-server
    • 启动Redis基准测试

      ./run_with_netacc.sh redis-benchmark

NetACC监控

netacc_ss是NetACC中自带的监控工具,您可以执行netacc_ss命令监控使用了NetACC加速的TCP应用进程收发数据的状态。在Server端和Client端均可以执行该命令进行监测。netacc_ss命令详细说明如下:

netacc_ss命令说明

netacc_ss -h
Usage:
 netacc_ss: [-p] <pid> [options]...
 Show monitoring information of specified netacc process

Options:
 -c   clear unused sock file
 -h   display this help
 -s   display specified monitoring metric[s]. [all|cfg|cnt|mem|qp|sock]
      all: all monitoring information
      cfg: configuration information
      cnt: counter information[default]
      mem: memory information
      qp : queue pair information
      sock: socket information
 -v   display netacc version

Examples:
 netacc_ss -p 12345 -s mem,cnt

执行如下命令,查看使用了NetACC加速的TCP应用进程收发数据的状态

netacc_ss -s all -p <进程ID>
说明

您可以通过执行ps -ef | grep <进程名称>命令查询进程ID。

Redis应用中使用NetACC

NetACC在Redis应用中的作用

  • 提升系统吞吐能力

    NetACC适用于处理每秒需要处理大量数据包的场景,在Redis处理大量请求时,可以降低CPU开销并提升系统吞吐量。

  • 提升网络响应速度

    对于需要快速网络响应的Redis应用,NetACC利用eRDMA提供的低时延特性,可以显著提升网络响应速度。

Redis性能基准测试中使用NetACC

redis-benchmark是Redis自带的一个性能测试工具,它可以模拟多个客户端同时对Redis发送请求,以此来评估Redis服务器在不同负载下的性能表现。

测试场景

redis-benchmark中使用NetACC,模拟100个clients,4个threads,循环5000000次set操作。

redis-server常用命令参数说明

redis-server是启动Redis服务器的命令。您可以在实例上执行redis-server -h查看具体参数说明,本文中用到的参数说明如下:

redis-server --port 6379 --protected-mode no
  • --port 6379:指定Redis服务的启动端口,默认不指定,为6379。

  • --protected-mode no:这个参数用来设置Redis服务器是否运行在保护模式下。保护模式是一种安全特性,当启用时,Redis只允许在本地主机(127.0.0.1 或 localhost)上进行连接,从而防止远程连接。使用no作为参数值表示禁用保护模式,允许Redis接受来自任何 IP 地址的连接。

    重要

    关闭Redis服务的保护模式,这在生产环境中可能带来安全风险,因此在开放的网络环境中使用时需要谨慎。

redis-benchmark常用命令参数说明

redis-benchmark是Redis自带的压力测试工具,用于模拟多个客户端向Redis发送大量请求,以测试Redis的性能。您可以在实例上执行redis-benchmark --help查看具体参数说明,本文中用到的参数说明如下:

redis-benchmark -h 172.17.0.90 -p 6379 -c 100 -n 5000000 -r 10000 --threads 4 -d 512 -t set
  • -h 172.17.0.90:指定Redis服务所在服务器的主机名或 IP 地址,这里是172.17.0.90

  • -p 6379:指定Redis服务的启动端口,如果使用了默认端口6379,则可以省略此配置,如果您的Redis服务启动时候指定了其他端口,需要指定。

    说明

    您可以在Redis服务端通过sudo grep "^port" /<redis.conf文件路径>/redis.conf命令查询,Redis默认配置文件路径为/etc/redis.conf

  • -c 100:指定并发连接数,这里是100个并发连接。

  • -n 5000000:指定请求总数,这里是5000000个请求。

  • -r 10000:使用随机键的范围,这里指定了10000个不同的键的范围。这意味着测试中的SET命令将使用从0到9999的随机整数作为键的一部分。

  • --threads 4:指定线程数,这里是4个线程。redis-benchmark默认是单线程的,但某些系统可能允许使用多线程来模拟并发。

  • -d 512:指定SET命令值的数据大小,这里是512字节。

  • -t set:指定只运行set测试。-t参数后面跟的是测试命令的名称,这里只测试set命令的性能。

这个命令的意思是,使用4个线程,每个线程100个并发连接,总共发送5000000个set请求到IP地址为172.17.0.90的Redis服务器,每个请求的值是一个512字节的随机数据,并且使用的键是0到9999之间的随机整数。

redis-benchmark常用测试结果指标说明

  • 吞吐量(Throughput Summary):

    每秒请求数rps(requests per second):表示在测试期间服务器每秒能够处理的请求数量。例如332933.81 requests per second表示服务器每秒可以处理约332934个请求。

  • 延迟(Latency Summary),单位为毫秒:

    • avg:平均延迟,即所有请求的平均响应时间。

    • min:最小延迟,即所有请求中的最小响应时间。

    • p50(50th percentile,中位数):一半的请求响应时间低于这个值。

    • p95(95th percentile):95%的请求响应时间低于这个值。

    • p99(99th percentile):99%的请求响应时间低于这个值。

    • max:最大延迟,即所有请求中的最大响应时间。

准备工作

购买两台支持eRDMA的实例,勾选自动安装eRDMA驱动,并且在主网卡开启eRDMA网络接口。两台ECS实例分别作为Redis的服务端和客户端。

本示例参数如下所示:

  • 镜像:均为Alibaba Cloud Linux 3

  • 实例规格:均为ecs.g8ae.4xlarge

  • 实例主网卡的私网IP地址:Server端(172.17.0.90)、Client端(172.17.0.91)。在以下测试中,您需要根据实际情况替换IP地址。

    说明
    • 本文以在实例的主网卡上开启eRDMA网络接口为例进行测试,那么这里的172.17.0.90即Redis服务端所在ECS实例的主网卡的私网IP地址。

    • 如果您是通过辅助弹性网卡上开启eRDMA网络接口进行测试,那么这里的IP地址,需要改为您实际的辅助弹性网卡的私网IP地址。更多信息,请参见创建新实例时配置eRDMA

创建过程重要参数示例

创建过程中需注意以下配置项(其他参数,请参见自定义购买实例):

  • 实例规格和镜像:请参见使用限制

  • 扩展程序:选中eRDMA驱动。实例启动过程中会自动安装eRDMA驱动,无需您再手动安装。您在购买Alibaba Cloud Linux操作系统的倚天实例时,还可以选择安装性能加速类扩展程序。更多信息,请参见性能加速扩展程序

    image

  • 弹性网卡:在主网卡右侧选中弹性RDMA接口

    重要

    创建实例时,仅支持为主网卡启用弹性RDMA接口,且单台ECS实例最多只能绑定一个启用弹性RDMA接口的网卡。如果您需要使用辅助网卡配置eRDMA,只能在创建实例后,单独创建辅助弹性网卡并为其启用弹性RDMA接口,然后绑定至ECS实例上使用。具体操作,请参见创建辅助弹性网卡绑定辅助弹性网卡

    image

具体操作

  1. 分别远程连接Server端和Client端的ECS实例。

    具体操作,请参见通过密码或密钥认证登录Linux实例

  2. 确认两台ECS实例的eRDMA驱动安装完成。

    在实例启动后,您可以通过ibv_devinfo命令确认已安装完毕:

    • 如果正确安装完成后,命令返回如下所示:

      image

    • 如果尚未完成安装,命令返回如下所示(eRDMA相关驱动程序的安装可能需要几分钟,您可以稍后再尝试):

      image

  3. 在两台ECS实例上分别执行以下命令安装Redis。

    sudo yum install -y redis

    安装完成后,返回信息如下所示:

    image

  4. 通过redis-benchmark进行Redis性能的基准测试。

    使用NetACC加速测试
    1. 在Server端的ECS实例上,执行以下命令,以NetACC加速的方式启动Redis服务:

      netacc_run redis-server --port 6379 --protected-mode no
      说明

      正确启动后,返回如下所示:

      image

    2. 在Client端的ECS实例上,执行以下命令,开启Redis基准测试:

       netacc_run redis-benchmark -h 172.17.0.90 -p 6379 -c 100 -n 5000000 -r 10000 --threads 4 -d 512 -t set
      说明
      • 您需要替换对应的172.17.0.906379为您实际启动Redis服务的服务器的IP地址和端口号,详见redis-benchmark常用命令参数说明

      • 不同的网络环境下测试结果不同,本文测试数据仅供参考,具体执行结果以您的实际环境为准。

      测试结束后,返回示例内容如下

      ====== SET ======                                                      
        5000000 requests completed in 6.52 seconds
        100 parallel clients
        512 bytes payload
        keep alive: 1
        host configuration "save": 3600 1 300 100 60 10000
        host configuration "appendonly": no
        multi-thread: yes
        threads: 4
      
      Latency by percentile distribution:
      0.000% <= 0.039 milliseconds (cumulative count 3)
      50.000% <= 0.127 milliseconds (cumulative count 2677326)
      75.000% <= 0.143 milliseconds (cumulative count 3873096)
      87.500% <= 0.151 milliseconds (cumulative count 4437348)
      93.750% <= 0.159 milliseconds (cumulative count 4715347)
      96.875% <= 0.175 milliseconds (cumulative count 4890339)
      98.438% <= 0.183 milliseconds (cumulative count 4967042)
      99.609% <= 0.191 milliseconds (cumulative count 4991789)
      99.902% <= 0.207 milliseconds (cumulative count 4995847)
      99.951% <= 0.263 milliseconds (cumulative count 4997733)
      99.976% <= 0.303 milliseconds (cumulative count 4998853)
      99.988% <= 0.343 milliseconds (cumulative count 4999403)
      99.994% <= 0.367 milliseconds (cumulative count 4999704)
      99.997% <= 0.391 milliseconds (cumulative count 4999849)
      99.998% <= 2.407 milliseconds (cumulative count 4999924)
      99.999% <= 5.407 milliseconds (cumulative count 4999962)
      100.000% <= 6.847 milliseconds (cumulative count 4999981)
      100.000% <= 8.423 milliseconds (cumulative count 4999991)
      100.000% <= 8.919 milliseconds (cumulative count 4999996)
      100.000% <= 9.271 milliseconds (cumulative count 4999998)
      100.000% <= 9.471 milliseconds (cumulative count 4999999)
      100.000% <= 9.583 milliseconds (cumulative count 5000000)
      100.000% <= 9.583 milliseconds (cumulative count 5000000)
      
      Cumulative distribution of latencies:
      18.820% <= 0.103 milliseconds (cumulative count 941003)
      99.917% <= 0.207 milliseconds (cumulative count 4995847)
      99.977% <= 0.303 milliseconds (cumulative count 4998853)
      99.998% <= 0.407 milliseconds (cumulative count 4999879)
      99.998% <= 0.503 milliseconds (cumulative count 4999903)
      99.998% <= 0.703 milliseconds (cumulative count 4999904)
      99.998% <= 0.807 milliseconds (cumulative count 4999905)
      99.998% <= 0.903 milliseconds (cumulative count 4999906)
      99.998% <= 1.007 milliseconds (cumulative count 4999908)
      99.998% <= 1.103 milliseconds (cumulative count 4999909)
      99.998% <= 1.207 milliseconds (cumulative count 4999912)
      99.998% <= 1.407 milliseconds (cumulative count 4999913)
      99.998% <= 1.503 milliseconds (cumulative count 4999915)
      99.998% <= 1.607 milliseconds (cumulative count 4999916)
      99.998% <= 1.703 milliseconds (cumulative count 4999917)
      99.998% <= 1.807 milliseconds (cumulative count 4999918)
      99.998% <= 1.903 milliseconds (cumulative count 4999919)
      99.998% <= 2.103 milliseconds (cumulative count 4999920)
      99.999% <= 3.103 milliseconds (cumulative count 4999931)
      99.999% <= 4.103 milliseconds (cumulative count 4999944)
      99.999% <= 5.103 milliseconds (cumulative count 4999958)
      99.999% <= 6.103 milliseconds (cumulative count 4999971)
      100.000% <= 7.103 milliseconds (cumulative count 4999984)
      100.000% <= 8.103 milliseconds (cumulative count 4999989)
      100.000% <= 9.103 milliseconds (cumulative count 4999996)
      100.000% <= 10.103 milliseconds (cumulative count 5000000)
      
      Summary:
        throughput summary: 767341.94 requests per second
        latency summary (msec):
                avg       min       p50       p95       p99       max
              0.126     0.032     0.127     0.167     0.183     9.583

      可以看到最下面的Summary信息,最后打印的是77万左右的rps。关于指标详细说明,详见redis-benchmark常用测试结果指标说明

    测试过程中通过netacc_ss查看服务端监控

    在测试过程中,您可以在Server端的ECS实例上通过netacc_ss查看目前服务端监控信息:

    • 执行以下命令,查看目前Redis服务的进程ID:

      ps -ef | grep redis-server

      返回信息如下,可以看到redis-server的进程ID为114379:

      image

    • 执行以下命令,查看Redis服务目前的连接信息及收发数据的状态:

      netacc_ss -p 114379 -s all
      说明

      您需要将命令中的114379替换为您实际环境中Redis服务的进程的PID。详见netacc_ss命令说明

      命令返回信息如下,可以看到目前建立的socket连接都是RDMA连接。最右侧4列是收发的数据量:

      image

    未使用NetACC加速测试
    1. 在Server端的ECS实例上,执行以下命令,启动Redis服务:

      redis-server --port 6379 --protected-mode no --save
      说明

      您需要替换对应的6379为您实际启动Redis服务的端口号,详见redis-server常用命令参数说明

      正确启动后,返回如下所示:

      image

    2. 在Client端的ECS实例上,执行以下命令,开启Redis基准测试:

       redis-benchmark -h 172.17.0.90 -c 100 -n 5000000 -r 10000 --threads 4 -d 512 -t set
      说明
      • 您需要替换对应的172.17.0.906379为您实际启动Redis服务的服务器的IP地址和端口号, 详见redis-benchmark常用命令参数说明

      • 不同的网络环境下测试结果不同,本文测试数据仅供参考,具体执行结果以您的实际环境为准。

      测试结束后,返回示例内容如下

      ====== SET ======                                                         
        5000000 requests completed in 15.02 seconds
        100 parallel clients
        512 bytes payload
        keep alive: 1
        host configuration "save": 
        host configuration "appendonly": no
        multi-thread: yes
        threads: 4
      
      Latency by percentile distribution:
      0.000% <= 0.055 milliseconds (cumulative count 27)
      50.000% <= 0.287 milliseconds (cumulative count 2635010)
      75.000% <= 0.335 milliseconds (cumulative count 3782931)
      87.500% <= 0.367 milliseconds (cumulative count 4459136)
      93.750% <= 0.391 milliseconds (cumulative count 4720397)
      96.875% <= 0.415 milliseconds (cumulative count 4855130)
      98.438% <= 0.439 milliseconds (cumulative count 4936478)
      99.219% <= 0.455 milliseconds (cumulative count 4965765)
      99.609% <= 0.471 milliseconds (cumulative count 4984031)
      99.805% <= 0.487 milliseconds (cumulative count 4993326)
      99.902% <= 0.495 milliseconds (cumulative count 4995579)
      99.951% <= 0.511 milliseconds (cumulative count 4997659)
      99.976% <= 0.551 milliseconds (cumulative count 4998848)
      99.988% <= 0.599 milliseconds (cumulative count 4999468)
      99.994% <= 0.631 milliseconds (cumulative count 4999722)
      99.997% <= 0.663 milliseconds (cumulative count 4999862)
      99.998% <= 0.695 milliseconds (cumulative count 4999924)
      99.999% <= 0.759 milliseconds (cumulative count 4999964)
      100.000% <= 0.807 milliseconds (cumulative count 4999982)
      100.000% <= 1.935 milliseconds (cumulative count 4999993)
      100.000% <= 2.071 milliseconds (cumulative count 4999996)
      100.000% <= 2.111 milliseconds (cumulative count 4999998)
      100.000% <= 2.119 milliseconds (cumulative count 4999999)
      100.000% <= 2.143 milliseconds (cumulative count 5000000)
      100.000% <= 2.143 milliseconds (cumulative count 5000000)
      
      Cumulative distribution of latencies:
      0.028% <= 0.103 milliseconds (cumulative count 1377)
      0.985% <= 0.207 milliseconds (cumulative count 49228)
      60.094% <= 0.303 milliseconds (cumulative count 3004705)
      96.325% <= 0.407 milliseconds (cumulative count 4816230)
      99.938% <= 0.503 milliseconds (cumulative count 4996887)
      99.991% <= 0.607 milliseconds (cumulative count 4999546)
      99.999% <= 0.703 milliseconds (cumulative count 4999927)
      100.000% <= 0.807 milliseconds (cumulative count 4999982)
      100.000% <= 0.903 milliseconds (cumulative count 4999987)
      100.000% <= 1.903 milliseconds (cumulative count 4999990)
      100.000% <= 2.007 milliseconds (cumulative count 4999995)
      100.000% <= 2.103 milliseconds (cumulative count 4999997)
      100.000% <= 3.103 milliseconds (cumulative count 5000000)
      
      Summary:
        throughput summary: 332955.97 requests per second
        latency summary (msec):
                avg       min       p50       p95       p99       max
              0.292     0.048     0.287     0.399     0.447     2.143

      可以看到最下面的Summary信息,最后打印的是33万左右的rps。关于指标详细说明,详见redis-benchmark常用测试结果指标说明