百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术教程 > 正文

SMC-R加速TCP实践(tcp加速原理)

mhr18 2025-05-02 12:02 19 浏览 0 评论

共享内存通信SMC(Shared Memory Communication)是一种兼容socket层、使用共享内存技术实现的高性能内核网络协议栈。SMC-R,SMC over RDMA,该协议兼容socket,能够在TCP socket之间使用RDMA进行高效通讯,使得TCP 网络应用程序透明使用 RDMA(不需要做IBVerbs改造),获得高带宽、低时延的网络通信服务。SMC 是 IBM 开源到 Linux 代码中,同时 IBM 也一同提出了 IETF RFC 7609,描述 SMC-R协议是如何实现的。

SMC-R要点,高性能和透明替换:

o 是一种协议,基于共享内存模型,Linux 下为 AF_SMC,可以直接在 socket 中制定使用,和TCP等价。

o 可以借助RDMA 加速

o 混合协议:借助TCP自动建立RDMA连接,协商不成功可以回退至TCP

o 兼容socket,可以透明替换所有的 TCP 应用,应用无需改造

缺点:

  • 基于内核实现的SMC-R会走一次内核拷贝会有性能损耗。

加速的本质

关于 RDMA 的基本原理, 互联网上已经有不少资料了. 比如 RDMA杂谈 本文不再详述.

RDMA 的加速原理并不是让报文在线缆或者交换机之间传输地更快 (毕竟都是电信号, 大家没什么不同),rdma加速的原理就是硬件卸载,将本需要软件(CPU)处理的工作下放到硬件。

简单来说, RDMA 是将原本需要消耗 CPU 处理报文的工作 Offload 到网卡,CPU 不再需要花时间在 TCP 协议栈上, 而可以用省下来的 CPU 处理更多业务逻辑, 从而减少通信时延.

但要想让 RDMA 取得相较 TCP 的显著优势, 一般来说需要满足两个条件:

  • 处理业务的 CPU 资源很宝贵

反过来说, 如果业务本身并不忙, CPU 资源本身并不稀缺, 那么 RDMA 省下的 CPU 意义并不大。

  • 通信双方之间的 RTT 并不大

如果网络传输在路径上占比很大,则 RDMA 方案中将协议栈卸载到网卡的所带来的收益将变得很小。因此, RDMA 多用于数据中心内部。

另外, RDMA 其实比 TCP 对基础网络的稳定性要求更高,对丢包更难以忍受。

旧有应用的阻碍

现实的网络应用,绝大部分直接或者间接使用 posix API 与内核交互,大部分框架已经使用了socket()、bind()、listen().

RDMA 使用的 Verbs API 不一样,它的接口更多, 语义也和 posix API 大不相同。

比如 ibv_create_qp ibv_modify_qp ibv_post_send

如果决心要使用 RDMA,新的应用还可以迁就,但现存的应用怎么办?

很容易想到通过LD_PRELOAD的方式加载使用替换 TCP的协议族,直接将应用本来想创建的 TCP socket 篡改为新的 SMC-R socket。

添加图片注释,不超过 140 字(可选)

阿里云的SMC-R落地情况

参考如下网址:

https://help.aliyun.com/zh/ecs/user-guide/in-an-enterprise-x86-erdma-instance-configuration? spm=a2c4g.11186623.0.0.62b66173b0G4eo

https://help.aliyun.com/zh/ecs/user-guide/on-the-gpu-instance-configuration-erdma? spm=a2c4g.11186623.0.0.259777187tcc6I

阿里云支持小规格虚机使用smc-r,只要是以下规格族的机器就可以, 支持以下镜像

添加图片注释,不超过 140 字(可选)

还支持在GPU实例上配置smc-r, 支持以下镜像

添加图片注释,不超过 140 字(可选)

阿里云的落地场景有数据库Redis 、大数据应用Spark 、AI训练、推理场景、HPC应用等。

添加图片注释,不超过 140 字(可选)

阿里云主要加速tcp的改动

阿里云主要有两部分改动, —部分是内核改动,其实就是使内核支持smc;—部分是使用

netACC加速,看着和smc-tools的smc_run类似,都是通过LD_PRELOAD的方式加载使用替换 TCP的协议族,可能是在这个基础上进行了—些其他功能。

SMC-R配置过程

  1. 更新内核到5.10.0及以上
  2. 配置smc-r
###关闭ipv6
sysctl net.ipv6.conf.all .disable_ipv6=1
sysctl net.ipv6.conf.default.disable_ipv6=1 4
###安装smc和smc_diag模块
modprobe smc
modprobe smc_diag 8
yum install -y smc-tools
#安装完之后可以执行—下smcr d命令看smc模块是否安装成功,使用smcr -v命令查看版本
#需要smc-tools版本为1.7以上,才可以设置ueid使能smcrv2
#如果smc-tools版本低,先升级smc-tools

3. (如果两台不同的主机通信的话)添加ueid,在两台虚机(实体机同理)上都添加ueid, 而且两台虚机中的ueid必须—样才可以。

smcr ueid add WFS  ##WFS可以随意指定,但是两台虚机中的ueid名字必须—样
###添加pnet
smc_pnet -a ABC	-I eth1	-D mlx5_1 -P 1

查看是否成功添加映射

添加图片注释,不超过 140 字(可选)

HCA即支持RDMA的网卡, driver loaded表示驱动已加载

添加图片注释,不超过 140 字(可选)

perftest测试,测试RDMA网卡

添加图片注释,不超过 140 字(可选)

添加图片注释,不超过 140 字(可选)

测试SMC-R

server.c

#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>

#define PORT 16000
#define BACKLOG 5
#define AF_SMC 43

int main()
{
    int iSocketFD = 0;
    int iRecvLen = 0;
    int new_fd = 0;
    char buf[4096] = {0};
    struct sockaddr_in stLocalAddr = {0};
    struct sockaddr_in stRemoteAddr = {0};
    socklen_t socklen = 0;
    int ret = 0;
    iSocketFD = socket(AF_SMC, SOCK_STREAM, 0);
    if(0 > iSocketFD)
    {
        printf("创建socket失败!\n");
        return 0;
    }
    char *host = "192.168.255.3"; //当前RDMA网卡的ip地址
    inet_pton(AF_INET, host, &stLocalAddr.sin_addr);
    stLocalAddr.sin_family = AF_INET;
    stLocalAddr.sin_port = htons(PORT);
    ret = bind(iSocketFD, (void *)&stLocalAddr,
    sizeof(stLocalAddr));
    if (ret < 0)
    {
        printf("绑定失败!, ret = %d\n", ret);
        return 0;
    }
    else
    {
        printf("绑定成功!, ret = %d\n", ret);
    }

    if(0 > listen(iSocketFD, BACKLOG))
    {
        printf("监听失败!\n");
        return 0;
    }

    printf("iSocketFD: %d\n", iSocketFD);
    new_fd = accept(iSocketFD, (void *)&stRemoteAddr, &socklen);
    if(0 > new_fd)
    {
        printf("接收失败!\n");
        return 0;
    }
    else
    {
        printf("接收成功!\n");
        memset(buf, 0x42, 1024);
        send(new_fd, buf, sizeof(buf), 0);
    }
    printf("new_fd: %d\n", new_fd);
    iRecvLen = recv(new_fd, buf, sizeof(buf), 0);
    if(0 >= iRecvLen)
    {
        printf("接收失败或者对端关闭连接!\n");
    }
    else
    {
        printf("buf: %s\n", buf);
    }
    close(new_fd);
    close(iSocketFD);
    return 0;
}

client.c

#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#define PORT 16000
#define ADDR "192.168.255.3" //server端设置的ip地址
#define AF_SMC 43
int main()
{
    int iSocketFD = 0;
    unsigned int iRemoteAddr = 0;
    struct sockaddr_in stRemoteAddr = {0};
    socklen_t socklen = 0;
    char buf[4096] = {0};
    iSocketFD = socket(AF_SMC, SOCK_STREAM, 0);
    if(0 > iSocketFD)
    {
        printf("创建socket失败!\n");
        return 0;
    }
    stRemoteAddr.sin_family = AF_INET;
    stRemoteAddr.sin_port = htons(PORT);
    inet_pton(AF_INET, ADDR, &iRemoteAddr);
    stRemoteAddr.sin_addr.s_addr=iRemoteAddr;
    if(0 > connect(iSocketFD, (void *)&stRemoteAddr,sizeof(stRemoteAddr)))
    {
        printf("连接失败!\n");
    }
    else
    {
        printf("连接成功!\n");
        recv(iSocketFD, buf, sizeof(buf), 0);
        printf("Received:%s\n", buf);
    }
    while(1);
    close(iSocketFD);
    return 0;
}

在两台主机上分别编译:

##在两台虚机上分别编译client和server文件
gcc -o smc_client client.c
gcc -o smc_server server.c
##启动server端
./smc_server
##启动clien端
./smc_client

在client端执行smcss命令出现以下结果,Mode为SMCR说明smc-r跑通。

添加图片注释,不超过 140 字(可选)

更简单的改造SMC-R替换

刚刚是手动将环境变为scm-r,还是有很多不方便的地方。如果安装了smc-tools,直接应用前面添加smc_run即可。

以redis为例:

###在server执行,ip地址为当前RDMA网卡的ip地址
smc_run ./redis-server --bind 192.168.255.3 --port 6379 --protected-mode no --save

###在client执行,ip地址为server中设置的地址
smc_run ./redis-benchmark -h 192.168.255.3 -p 6379 -n 1000000 -t set -c 100

执行效果如下,性能有明显提升(相较于不使用smc_run)

添加图片注释,不超过 140 字(可选)

总结

SMC-R是一种优雅的加速后端的方法,可以不改动代码加速应用。缺点是会走一次内核,性能和原生rdma应用差了一点,但是如果实现SMC-R是在纯用户态(猜测阿里的netAcc即是如此实现)则没有损耗。

引用文章:

http://switch-route.gitee.io/

Savir:0. 《RDMA杂谈》专栏索引

相关推荐

redis 7.4.3更新!安全修复+性能优化全解析

一、Redis是什么?为什么选择它?Redis(RemoteDictionaryServer)是一款开源的高性能内存键值数据库,支持持久化、多数据结构(如字符串、哈希、列表等),广泛应用于缓存、消...

C# 读写Redis数据库的简单例子

CSRedis是一个基于C#的Redis客户端库,它提供了与Redis服务器进行交互的功能。它是一个轻量级、高性能的库,易于使用和集成到C#应用程序中。您可以使用NuGet包管理器或使用以下命令行命令...

十年之重修Redis原理

弱小和无知并不是生存的障碍,傲慢才是。--------面试者总结Redis可能都用过,但是从来没有理解过,就像一个熟悉的陌生人,本文主要讲述了Redis基本类型的使用、数据结构、持久化、单线程模型...

高频L2行情数据Redis存储架构设计(含C++实现代码)

一、Redis核心设计原则内存高效:优化数据结构,减少内存占用低延迟访问:单次操作≤0.1ms响应时间数据完整性:完整存储所有L2字段实时订阅:支持多客户端实时数据推送持久化策略:RDB+AOF保障数...

Magic-Boot开源引擎:零代码玩转企业级开发,效率暴涨!

一、项目介绍基于magic-api搭建的快速开发平台,前端采用Vue3+naive-ui最新版本搭建,依赖较少,运行速度快。对常用组件进行封装。利用Vue3的@vue/compiler-sfc单文...

项目不行简历拉胯?3招教你从面试陪跑逆袭大厂offer!

项目不行简历拉胯?3招教你从面试陪跑逆袭大厂offer!老铁们!是不是每次面试完都感觉自己像被大厂面试官婉拒的渣男?明明刷了三个月题库,背熟八股文,结果一被问项目就支支吾吾,简历写得像大学生课程设计?...

谷歌云平台:开发者部署超120个开源包

从国外相关报道了解,Google与Bitnami合作为Google云平台增加了一个新的功能,为了方便开发人员快捷部署程序,提供了120余款开源应用程序云平台的支持。这些应用程序其中包括了WordPre...

知名互联网公司和程序员都看好的数据库是什么?

2017年数据库领域的最大趋势是什么?什么是最热的数据处理技术?学什么数据库最有前途?程序员们普遍不喜欢的数据库是什么?本文都会一一揭秘。大数据时代,数据库的选择备受关注,此前本号就曾揭秘国内知名互联...

腾讯云发布云存储MongoDB服务

近日,著名安全专家兼Shodan搜索引擎的创建者JohnMatherly发现,目前至少有35000个受影响的MongoDB数据库暴露在互联网上,它们所包含的数据暴露在网络攻击风险之中。据估计,将近6...

已跪,Java全能笔记爆火,分布式/开源框架/微服务/性能调优全有

前言程序员,立之根本还是技术,一个程序员的好坏,虽然不能完全用技术强弱来判断,但是技术水平一定是基础,技术差的程序员只能CRUD,技术不深的程序员也成不了架构师。程序员对于技术的掌握,除了从了解-熟悉...

面试官:举个你解决冲突的例子?别怂!用这个套路……

面试官:举个你解决冲突的例子?别怂!用这个套路……最近收到粉丝私信,说被问到:团队技术方案有分歧怎么办?当场大脑宕机……兄弟!这不是送命题,是展示你情商+技术判断力的王炸题!今天教你们3招,用真实案例...

面试碰到MongoDB?莫慌,跟面试官这样吹MongoDB 复制集

推荐阅读:吊打MySQL:21性能优化实践+学习导图+55面试+笔记+20高频知识点阿里一线架构师分享的技术图谱,进阶加薪全靠它十面字节跳动,依旧空手而归,我该放弃吗?文末会分享一些MongoDB的学...

SpringBoot集成扩展-访问NoSQL数据库之Redis和MongoDB!

与关系型数据库一样,SpringBoot也提供了对NoSQL数据库的集成扩展,如对Redis和MongoDB等数据库的操作。通过默认配置即可使用RedisTemplate和MongoTemplate...

Java程序员找工作总卡项目关?

Java程序员找工作总卡项目关?3招教你用真实经历写出HR抢着要的简历!各位Java老哥,最近刷招聘软件是不是手都划酸了?简历投出去石沉大海,面试邀请却总在飞别人的简历?上周有个兄弟,13年经验投了5...

Java多租户SaaS系统实现方案

嗯,用户问的是Java通过租户id实现的SaaS方案。首先,我需要理解用户的需求。SaaS,也就是软件即服务,通常是指多租户的架构,每个租户的数据需要隔离。用户可能想知道如何在Java中利用租户ID来...

取消回复欢迎 发表评论: