一、RDMA基础知识
远程直接内存访问(RDMA,Remote Direct Memory Access),指可以或许访问(即读写)远程机器的内存。有多种支持 RDMA 的网络协议,包罗:Infiniband、RoCE 和 iWARP。
1.RDMA技能架构与焦点组件
一、架构分层与焦点组件
RDMA(Remote Direct Memory Access)技能通过绕过内核协议栈和零复制机制实现高效数据传输,其架构分为用户空间和内核空间两部分,焦点组件和流程如下:
1. 用户空间组件
- 用户空间套接字API:
提供类似传统Socket的编程接口,但专为RDMA优化。比方,应用程序可通过ibv_post_send()直接提交RDMA操作哀求,无需通过内核协议栈。
示例:分布式数据库(如Redis)使用此API直接向远程节点内存写入数据,避免内核拷贝。
- 用户Verbs(libibverbs):
RDMA的焦点API库,函数名以ibv_为前缀(如ibv_create_qp创建队列对)。支持三种协议:
- Infiniband:原生RDMA协议,高性能但需专用硬件。
- RoCE(RDMA over Converged Ethernet):通过以太网承载RDMA,兼容通例网络设备。
- iWARP(Internet Wide Area RDMA Protocol):基于TCP/IP实现RDMA,支持广域网但耽误较高。
示例:云计算平台(如AWS)使用RoCE在以太网中实现虚拟机间低耽误通讯。
2. 内核空间组件
- 内核Verbs:
提供内核态RDMA驱动支持,管理硬件资源(如队列对QP、内存注册MR)。
示例:当用户调用ibv_reg_mr()注册内存时,内核Verbs会锁定物理内存页供网卡直接访问。
- CM(Connection Manager):
负责创建和维护RDMA连接,包罗互换通讯参数(如QP号、GID)。
示例:两台服务器通过CM互换元数据后,可直接通过QP举行RDMA读写,无需TCP三次握手。
- RDS(Reliable Datagram Sockets):
提供可靠的数据报传输服务,支持多播和原子操作。
示例:金融生意业务体系使用RDS确保订单数据的可靠性和同等性。
- 可替换短框套接字:
一种轻量级传输层协议,减少协议头开销,提拔小包传输服从。
示例:高频生意业务场景中,短帧协议将64字节订单的传输耽误从10μs降至2μs。
3. Linux内核与用户空间交互
- 零复制(Zero-Copy):
应用程序通过ibv_reg_mr()注册内存后,网卡可直接读写用户态内存,无需内核到场数据拷贝。
示例:HDFS使用RDMA零复制加速跨节点数据块传输,吞吐量提拔3倍。
- CPU卸载:
RDMA操作(如数据传输、CRC校验)由网卡硬件完成,CPU仅负责提交哀求。
示例:AI训练集群中,GPU通过RDMA直接互换梯度数据,CPU使用率降低70%。
二、RDMA技能优势与实现原理
1. 高带宽
- 原理:RDMA绕过内核协议栈,减少TCP/IP处置惩罚开销;支持大报文(如4KB~1MB)传输。
- 示例:NVMe over Fabrics(NVMe-oF)使用RDMA实现存储网络100Gbps带宽,时延低于10μs。
2. 低耽误
- 原理:
- 零复制:数据不经过内核缓冲区。
- 硬件卸载:网卡直接处置惩罚传输使命。
- 示例:证券生意业务所的订单匹配体系接纳RDMA,端到端耽误从50μs降至5μs。
3. 跳过内核(Kernel Bypass)
- 原理:用户态程序通过Verbs API直接操作网卡,无需上下文切换。
- 示例:分布式内存数据库(如Memcached)通过RDMA实现内存级远程访问,QPS(每秒查询数)提拔至百万级。
4. 减少CPU负担
- 原理:数据传输和协议处置惩罚由网卡完成,CPU仅初始化操作。
- 示例:视频流服务器使用RDMA后,CPU占用率从80%降至20%,可同时处置惩罚更多并发哀求。
三、协议对比:RoCE vs. iWARP vs. Infiniband
特性InfinibandRoCEiWARP网络介质专用InfiniBand网络以太网(需支持DCB/PFC)TCP/IP网络耽误<1μs2~5μs10~50μs适用场景HPC超算中央数据中央(融合网络)跨广域网企业应用设置复杂度高(需专用互换机)中(需优化QoS)低(兼容现有网络) 示例:
- 超算中央:使用Infiniband连接GPU集群,训练ResNet-50模型时间缩短30%。
- 云数据中央:接纳RoCE v2(基于UDP)构建存储网络,兼容现有25G/100G以太网。
- 跨地域备份:通过iWARP在AWS差别地区间同步数据库,使用TCP/IP确保可靠性。
四、典范应用场景
1. 分布式存储
- Ceph RDMA:通过Librados直接读写OSD节点内存,IOPS提拔至百万级。
- 示例:微软Azure的存储加速服务接纳RDMA,耽误低于1ms。
2. 高性能计算(HPC)
- MPI over RDMA:MPI库(如OpenMPI)使用RDMA加速历程间通讯。
- 示例:天气模拟软件WRF通过RDMA将计算节点间通讯时间减少60%。
3. 人工智能训练
- GPU Direct RDMA:NVIDIA GPUDirect技能答应GPU显存直接到场RDMA传输。
- 示例:Meta训练LLaMA模型时,RDMA使GPU间梯度同步时间从20ms降至2ms。
五、挑战与限制
- 网络设置复杂度高:
- RoCE需启用PFC(优先级流控)和ECN(显式拥塞通知)以避免丢包。
- 示例:某银行因未设置PFC导致RoCE网络拥塞,生意业务耽误飙升至100ms。
- 硬件依赖性强:
- 需要支持RDMA的网卡(如Mellanox ConnectX-6)和互换机。
- 示例:阿里云神龙服务器搭载自研RDMA智能网卡,实现虚拟化层零损耗。
- 安全机制不足:
- RDMA默认不加密传输,需结合TLS或IPSEC。
- 示例:国防体系接纳RoCE+国密算法加密,保障数据传输安全。
2.具体数据结构以及使用
具体 API 定义包罗在内核文件如下:
头文件ib_verbs.h中包罗的函数和结构可供如下内容使用:
1.RDMA栈本身
2.RDMA设备的低级驱动程序
3.作为消耗者使用RDMA栈的内核模块
一、焦点数据结构与API解析
头文件 ib_verbs.h 是RDMA内核开发的焦点,定义了RDMA协议栈的关键数据结构和操作接口。以下结合代码片断重点解析:
1. 焦点数据结构
- union ib_gid(全局标识符):
- union ib_gid {
- u8 raw[16]; // 128位GID原始数据
- struct {
- __be64 subnet_prefix; // 子网前缀(64位)
- __be64 interface_id; // 接口标识(64位)
- } global; // 结构化GID
- };
复制代码- 作用:唯一标识RDMA网络中的设备,类似IP地点。比方,RoCEv2中GID与IPv6地点映射,实现以太网上的RDMA通讯。
示例:在云计算中,虚拟机通过GID区分差别租户的RDMA资源,避免地点辩论。
- 工作队列(Work Queue):
- extern struct workqueue_struct *ib_wq; // 通用工作队列
- extern struct workqueue_struct *ib_comp_wq; // 完成事件工作队列
复制代码 作用:异步处置惩罚RDMA操作(如发送/接收哀求、完成变乱通知)。
示例:当网卡完成数据传输后,通过ib_comp_wq触发用户态回调函数。
二、使用场景与案例解析
1. RDMA栈本身
功能:实现RDMA协议的焦点逻辑,包罗连接管理、内存注册、队列对(QP)操作等。
关键API与操作:
- ib_register_client():注册RDMA客户端(如存储驱动)。
- ib_alloc_pd():分配掩护域(Protection Domain),隔离差别应用的内存访问权限。
案例:Kubernetes容器网络
- 场景:容器集群需要跨节点直接访问内存,加速AI训练使命。
- 实现:
- RDMA栈通过ib_core模块管理容器间的QP和MR(内存地区)。
- 使用ibv_reg_mr()注册容器内存,答应其他节点直接读写。
- 效果:TensorFlow分布式训练时,梯度同步耽误从15ms降至1ms。
2. RDMA设备的低级驱动程序
功能:驱动物理网卡(如Mellanox ConnectX系列),实现硬件与RDMA栈的交互。
关键API与操作:
- ib_register_device():注册网卡设备到RDMA子体系。
- ib_post_send():将数据传输哀求提交至网卡硬件队列。
案例:Mellanox网卡驱动优化
- 场景:金融高频生意业务需亚微秒级耽误。
- 实现:
- 驱动程序通过mlx5_core模块直接操作网卡寄存器,启用“Cut-Through”模式,减少数据包处置惩罚步调。
- 使用ibv_create_qp()创建无状态QP(Queue Pair),跳过ACK确认。
- 效果:订单传输耽误从3μs降至0.8μs。
3. 作为消耗者使用RDMA栈的内核模块
功能:其他内核模块(如存储、网络协议)调用RDMA接口实现高性能数据传输。
关键API与操作:
- rdma_bind_addr():绑定本地GID和端口号。
- rdma_listen():监听远程连接哀求。
案例:NVMe over Fabrics (NVMe-oF)
- 场景:企业级分布式存储需低耽误块存储访问。
- 实现:
- nvme-rdma内核模块调用ibv_create_cq()创建完成队列(CQ),接收IO完成变乱。
- 使用ibv_post_recv()预注册接收缓冲区,实现零拷贝数据存取。
- 效果:SSD跨节点读写带宽达100Gbps,时延低于10μs。
内核的RDMA栈全部代码位于内核树:CM(通讯管理器)、verbs(内核verbs)等等。
二、Infiniband基础
1.根本概念
InfiniBand技能不是用于我们常见的网络连接,重要目标是用于服务器端的连接,InfiniBand技能应用于服务器与服务器、服务器跟存储设备。通过InfiniBand传输数据时,数据是以数据包的方式传输,这些数据包会组合成一条一条信息。这些信息操作方式可能作为远程直接内存存取的读写程序。
一、InfiniBand 的根本概念
InfiniBand(直译是“无线带宽“”技能,”简称 IB)是一种专为高性能计算计划的网络通讯标准,焦点目标是实现高吞吐量和低耽误。它广泛应用于超级计算机、数据中央和分布式存储体系,可以或许高效连接服务器、存储设备等硬件。
二、速率优势:全双工 vs. 半双工
- 理论带宽对比
- InfiniBand 1.x:基础速率为 2.5 Gb/s(单通道),支持全双工模式,即双向同时传输数据。因此,理论总带宽为 5 Gb/s(2.5 Gb/s × 2)。
- PCI 总线:
- 32 位、33 MHz PCI 总线:单方向理论带宽 1 Gb/s(半双工,同一时间只能单向传输)。
- 64 位、133 MHz PCI-X 总线:单方向理论带宽 8.5 Gb/s(仍为半双工)。
关键差异:
- 全双工 vs. 半双工:InfiniBand 的双向同步传输明显提拔了实际可用带宽。
- 实际性能:固然理论值 PCI-X 更高,但由于协议开销和半双工限制,InfiniBand 的实际吞吐量更优。
- 后续版本升级
- InfiniBand 已迭代至更高版本(如 HDR、NDR),单通道速率可达 200 Gb/s 乃至 400 Gb/s,远超早期标准。
三、虚拟高速公路与虚拟通道
- 虚拟通道(Virtual Lanes, VL)
- 功能:类似于高速公路的“多车道”,通过逻辑划分物理链路,为差别优先级的流量分配独立通道。
- 优势:
- 服务质量(QoS):保障高优先级流量(如及时数据)的带宽和低耽误。
- 避免拥塞:低优先级流量(如备份数据)不会阻塞关键使命。
- 实现原理
- 字节位元组(Credit-Based Flow Control):
- 通过“名誉机制”控制数据传输速率,确保接收端有足够缓冲空间,避免丢包。
- 结合优先级标记(Priority Tagging),动态分配虚拟通道资源。
- 物理链路复用:同一对物理线缆可承载多个虚拟通道的流量,提拔资源使用率。
- 子网管理器(Subnet Manager, SM)
- 焦点脚色:负责设置和管理虚拟通道,包罗:
- 分配带宽和优先级。
- 监控网络状态,动态调解资源。
- 确保网络拓扑的稳定性和高效性。
四、InfiniBand 的焦点优势总结
特性InfiniBand传统 PCI/PCI-X传输模式全双工(双向同步)半双工(单向瓜代)耽误极低(微秒级)较高扩展性支持大规模集群互连限于本地总线连接适用场景高性能计算、分布式存储传统服务器内部设备连接 2.InfiniBand硬件组件_编址
InfiniBand根其他互联技能一样,它的规范页描述多种硬件组件,其中一些事数据包端点(数据的始发站大概目标地),有些会在子网或子网之间转发数据包。
常见组件 :主机信道适配器(HCA)、互换机、路由器。
Infiniband编址:组件唯一是GUID,全球唯一的64位值。GID用于表示端点端口或组播组。LID是一个16位值,子网管理器给每个子网端口都分配一个LID。
一、GUID(全局唯一标识符)
GUID(Global Unique Identifier)是 InfiniBand 网络中用于标识硬件组件的基础唯一标识符,具有全局唯一性和永世性。
1. 分类与功能
- 结点GUID(Node GUID)
- 定义:每个 InfiniBand 结点(如服务器、存储设备)的全局唯一标识符,与硬件绑定,永不改变。
- 示例:一台服务器的结点GUID可能是 0x0002c9030020abcd。
- 端口GUID(Port GUID)
- 定义:每个物理端口(如主机通道适配器 HCA、互换机端口)的唯一标识符,同样永世不变。
- 示例:一台互换机的第 1 个端口GUID可能是 0x0002c9030020abce,第 2 个端口为 0x0002c9030020abcf。
- 体系GUID(System GUID)
- 定义:由多个组件(如刀片服务器中的多个结点)组成的体系共享的统一标识符。
- 示例:一个刀片机箱内全部刀片服务器共享同一个体系GUID 0x0002c9030020abcc。
2. 作用
- 唯一性:确保网络中每个结点和端口可被唯一识别。
- 硬件绑定:GUID 固化在硬件中,即使设备更换子网,标识符仍不变。
二、GID(全局标识符)
GID(Global Identifier)是端口的逻辑标识符,用于在全局范围内寻址端口。它与子网相关,可动态生成。
1. 生成规则
- 基础 GID(索引0):每个端口至少有一个 GID,位于 GID 表的索引0处,由以下两部分组成:
- 子网前缀(Subnet Prefix):子网的唯一标识符(如 0xfe80::)。
- 端口GUID:通过算法将端口GUID转换为 IPv6 格式的后缀。
- 示例:
- 子网前缀:fe80::
- 端口GUID:0002c9030020abce
- 完备 GID:fe80::0002:c903:0020:abce
2. 应用场景
- 跨子网通讯:GID 支持全局路由,答应差别子网中的设备直接通讯。
- IPv6 兼容性:GID 格式与 IPv6 兼容,便于与 IP 网络集成。
三、LID(本地标识符)
LID(Local Identifier)是子网内的本地地点,由子网管理器动态分配,仅在同一子网内有用。
1. 分配规则
- 单播 LID:范围 0x001 至 0xbfff(共 14,335 个地点),用于一对一通讯。
- 组播 LID:范围 0xc000 至 0xfffe(共 16,383 个地点),用于一对多通讯。
- 互换机特殊性:互换机仅管理端口(用于控制)分配 LID,数据端口不分配。
2. 示例场景
- 单播示例:
- 服务器 A 的 HCA 端口分配 LID 0x001。
- 服务器 B 的 HCA 端口分配 LID 0x002。
- 两者通过单播 LID 直接通讯。
- 组播示例:
- 组播组分配 LID 0xc001。
- 服务器 A、B、C 加入该组,数据包发送到 0xc001 时,全部成员同时接收。
四、GUID、GID、LID 的关系与区别
标识符作用范围唯一性生成方式示例GUID全局硬件唯一,永世硬件固化结点GUID: 0x0002c9030020abcdGID全局子网相关,动态子网前缀 + 端口GUIDfe80::0002:c903:0020:abceLID子网内子网内唯一,动态子网管理器分配单播 LID: 0x001 五、实际应用案例
场景:高性能计算集群
- 硬件连接:
- 10 台服务器通过 InfiniBand 互换机互连,组成一个子网。
- 每台服务器的 HCA 端口有唯一的端口GUID,如 0x0002c9030020abce 至 0x0002c9030020abd7。
- 子网管理器设置:
- 子网管理器为每个 HCA 端口分配单播 LID(如 0x001 至 0x00A)。
- 互换机管理端口分配 LID 0x100。
- 通讯过程:
- 服务器 A(LID 0x001)向服务器 B(LID 0x002)发送数据时,使用单播 LID 直接寻址。
- 若需广播计算效果,发送到组播 LID 0xc001,全部加入该组的服务器同时接收。
3.InfiniBand功能_数据包
InfiniBand 协议功能:
- 答应设置 HCA、互换机和路由器的端口所属的分区,从而在物理子网内实现虚拟隔离;
- 涉及队列键(Queue Key)、虚拟通道(Virtual lanes VL);
- 包罗服务等级(Service Level SL)、故障切换。
一、队列键(Q_Key)
Q_Key(Queue Key) 是 InfiniBand 中用于验证不可靠通讯的密钥,确保只有授权的队列对(QP)可以接收数据。
1. 焦点作用
- 验证通讯权限:两个不可靠的 QP 必须设置相同的 Q_Key 才能相互收发单播或组播消息。
- 防止未授权访问:类似于密码机制,避免非目标 QP 接收数据包。
2. 应用场景
- 不可靠通讯(Unreliable Datagram, UD):
- 适用于容忍丢包的场景(如广播通知、及时流媒体)。
- 示例:集群中多个节点接收同一组播消息时,需全部节点 QP 设置相同的 Q_Key。
3. 设置示例
- 节点 A 的 QP 设置 Q_Key 0x1234,节点 B 的 QP 也设置 0x1234,两者可相互通讯。
- 若节点 C 的 QP 设置 0x5678,则无法接收 A/B 的消息。
二、虚拟通道(Virtual Lanes, VL)
虚拟通道(VL) 是一种在物理链路上划分逻辑通道的机制,用于隔离差别优先级的流量并分配资源。
1. 焦点功能
- 流量隔离:将物理链路划分为多个虚拟通道(类似高速公路的车道),每个 VL 对应独立的缓冲区。
- 资源分配:每个端口支持的 VL 数量是硬件属性(如支持 4 个 VL)。
2. 实现原理
- 缓冲区管理:每个 VL 有独立的发送和接收缓冲区,避免高低优先级流量相互阻塞。
- 物理链路复用:同一对物理线缆可承载多个 VL 的数据(如 VL0 传输高优先级控制信令,VL1 传输平常数据)。
3. 应用示例
- 高性能计算集群:
- VL0:用于 MPI 历程间同步消息(高优先级,低耽误)。
- VL1:用于文件传输(低优先级,答应耽误)。
三、服务等级(Service Level, SL)
服务等级(SL) 是 InfiniBand 中定义流量优先级的参数,支持 16 个等级(0~15),通过映射到 VL 实现服务质量(QoS)。
1. QoS 实现机制
- SL 到 VL 的映射:子网管理器将差别 SL 的流量分配到差别 VL,并为每个 VL 分配带宽和缓冲区资源。
- 示例:SL15 映射到 VL0(最高优先级),SL0 映射到 VL3(最低优先级)。
- 资源分配策略:
- 高优先级 VL 分配更多带宽和缓冲区,确保低耽误和高吞吐。
2. 实际应用
- 混合负载场景:
- SL15:用于及时数据库查询(毫秒级耽误要求)。
- SL5:用于批量数据备份(答应秒级耽误)。
四、故障切换(Failover)
故障切换 是 InfiniBand 中实现路径冗余的机制,答应为连接的 QP 定义主路径和备用路径。
1. 工作原理
- 主路径与备用路径:
- 主路径:默认通讯路径(如通过互换机 A)。
- 备用路径:备用路由(如通过互换机 B)。
- 自动切换:当主路径故障(如链路停止),流量自动切换到备用路径,无需人工干预。
2. 实现优势
- 高可用性:避免单点故障导致通讯停止。
- 无缝切换:应用层无感知,不报告错误。
3. 示例场景
- 金融生意业务体系:
- 主路径:通过焦点互换机,耽误 1μs。
- 备用路径:通过边缘互换机,耽误 2μs。
- 若焦点互换机宕机,流量立即切换到边缘互换机,生意业务不绝止。
五、关键机制对比与协同
机制焦点功能协同关系Q_Key验证不可靠通讯权限确保组播/单播消息的安全性VL隔离优先级流量,分配物理资源通过 SL 映射实现 QoSSL定义流量优先级依赖 VL 实现资源分配故障切换提供路径冗余,保障通讯连续性依赖子网管理器动态调解路径 4.使用RDMA和InfiniBand的两台主机的通讯流程
一、场景描述
假设有两台主机 A 和 B,通过 InfiniBand 网络互连,目标是实现 主机 A 直接向主机 B 的内存写入数据(RDMA Write 操作)。以下是具体通讯流程:
二、通讯流程步调
1. 初始化网络环境
- 硬件预备:
- 主机 A 和 B 均安装 InfiniBand 主机通道适配器(HCA)。
- 通过 InfiniBand 互换机连接两台主机,形成子网。
- 软件设置:
- 安装 InfiniBand 驱动和 RDMA 库(如 libibverbs、librdmacm)。
- 启动子网管理器(Subnet Manager, SM),完成子网初始化(分配 LID、设置路由表)。
2. 注册内存地区(Memory Region, MR)
- 主机 B 预备接收数据:
- 主机 B 在本地内存中分配一块缓冲区(比方 1MB),用于接收数据。
- 调用 ibv_reg_mr() 注册该内存地区,生成 内存地区描述符(MR),包罗以下信息:
- 虚拟地点(Virtual Address, VA)
- 物理地点(Physical Address, PA)
- 访问权限(如本地写、远程读/写)
- 内存密钥(Memory Key, rkey/lkey)
- 示例:
- // 主机 B 注册内存区域
- struct ibv_mr *mr = ibv_reg_mr(pd, buffer, size, IBV_ACCESS_REMOTE_WRITE);
复制代码 3. 创建通讯队列对(Queue Pair, QP)
- 创建 QP:
- 主机 A 和 B 分别创建 队列对(QP),包罗:
- 发送队列(Send Queue, SQ):存储待发送的哀求。
- 接收队列(Receive Queue, RQ):存储待接收的哀求。
- QP 类型选择 RC(Reliable Connected),支持可靠传输。
- QP 状态转换:
- RESET → INIT:初始化 QP 参数(如最大传输单位 MTU、服务等级 SL)。
- INIT → RTR(Ready to Receive):设置接收端参数(如目标 LID、Q_Key)。
- RTR → RTS(Ready to Send):设置发送端参数,QP 进入可通讯状态。
- 互换 QP 信息:
- 主机 A 和 B 通过带外通讯(如 TCP/IP)互换以下信息:
- QP 号(QP Number)
- LID(本地标识符)
- GID(全局标识符,用于跨子网通讯)
- rkey(远程内存密钥,来自主机 B 的 MR)
4. 主机 A 发起 RDMA Write 操作
- 构造工作哀求(Work Request, WR):
- 主机 A 在发送队列(SQ)中提交一个 RDMA Write 哀求,包罗:
- 目标内存地点(主机 B 的 MR 虚拟地点 + 偏移)。
- 数据长度(如 1MB)。
- 远程密钥(rkey,由主机 B 提供)。
- 目标 QP 号(主机 B 的 QP)。
- 触发硬件实行:
- HCA 直接从主机 A 的内存中读取数据,封装为 InfiniBand 数据包,通过物理链路发送。
- 数据包结构:
- BTH(Base Transport Header):包罗目标 LID、QP 号、操作码(RDMA Write)。
- RETH(RDMA Extended Transport Header):包罗远程地点、长度、rkey。
- Payload:实际数据。
5. 数据通过 InfiniBand 网络传输
- 路由过程:
- 互换机根据目标 LID 查找路由表,将数据包转发到主机 B 的 HCA。
- 虚拟通道(VL)与服务质量(SL):
- 数据包的 SL 映射到特定 VL(如 VL0),确保高优先级流量低耽误传输。
6. 主机 B 接收数据
- 直接内存写入(Zero-Copy):
- 主机 B 的 HCA 解析数据包,验证 rkey 权限。
- 数据直接写入主机 B 预先注册的内存地区,无需 CPU 到场。
- 完成通知(Completion Queue, CQ):
- 主机 A 的发送队列和主机 B 的接收队列各生成一个 完成队列元素(CQE),标志操作完成。
- 应用程序可通过轮询或变乱驱动方式获取完成状态。
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |