zMemif: go语言高性能网络库

news2025/7/6 21:19:06

简介

开发zMemif的主要动机是go有很高的处理能力,但是内置的udp库的确有些寒酸, 纯c开发效率又有些低,虽然可以用nff-go来实现go和dpdk的融合,但是cgo编译的确有点烦人,而且这个项目似乎也死了。然后考虑到容器的场景和手上netDAM
ruta
两个项目的需求,使用无锁内存队列来在go和dpdk之间共享是一个不错的选择。

思科开源了memif的库,但是需要和vpp配合使用,对于很多互联网企业VPP应用部署太麻烦,而且很多功能其实并不需要。同时netDAM也需要提供用户态的无锁内存队列功能,考虑到生态的兼容性,而且dpdk已经支持了memif的PMD,因此还是选择了memif的数据结构, go的库来自于vpp/gomemif库,并做了一些修改,原来的代码组织结构不太好,同时Interface的定义和go的interface会让人混淆,因此将Interface改为了port,同时发现在dpdk中已经把master/slave政治正确到server/client了,于是也就顺手改成了同样的名称保证一致。

系统架构

如下图所示,主要是在收发包路径上提供一条基于共享内存访问的路径memif来承载UDP业务并通过memif和DPDK绕开Kernel,为Golang提供原生的高性能包处理能力。而考虑到云端虚机等场景下除了业务的socket以外还需要一些管理的SSH或者以太网本身的ARP等二层协议的支持,于是在dpdk侧创建了memif和vhost_user两个接口。

Memif原理

memif通过一个UnixSocket来通信并交互共享内存区域,Server端会发送HELLO消息,客户端响应INIT,并且使用ADD_REGION消息来共享内存区域,然后通过ADD_RING消息共享size、offset、interrupt等信息给Server,最后通过CONNECT、CONNECTED消息确认连接。

这样的共享有一个好处,作为client端可以直接在用户态纯go(native-go)编程获得极高性能的收发包能力,而把复杂的内容通过共享内存交给DPDK处理,实现了基础架构和业务逻辑的很好的分离。

(免费订阅,永久学习)学习地址: Dpdk/网络协议栈/vpp/OvS/DDos/NFV/虚拟化/高性能专家-学习视频教程-腾讯课堂

更多DPDK相关学习资料有需要的可以自行报名学习,免费订阅,永久学习,或点击这里加qun免费
领取,关注我持续更新哦! !   

当然这种结构我们在以后会通过netDAM替代DPDK的Server端,直接为Go提供原生的Memif支持。同时这样的处理方式还可以为Serverless平台减轻网络栈的压力,直接通过共享内存交互event和数据。这就是以后容器和虚机、Serverless 统一和网络的交互方式,具体在一些特定场景下的应用以后慢慢说:)

zMemif使用

server侧(DPDK)

直接编译好了执行就行,然后默认会创建一个rutasys0的vhost-user接口,您可以把它当成一个普通网口配置IP地址和外界通信。同时系统会默认创建一个/tmp/memif.sock
文件用于客户端go程序访问并建立UNIX-Socket。

client侧(native go)

首先肯定是创建UNIX Socket咯

socketName := flag.String("socket", "", "control socket filename")
ctrlSock, err := zmemif.NewSocket("foo", *socketName)
if err != nil {
 logrus.Fatal("create socket failed: %v", err)
}

然后创建memif接口配置:

cfg := &zmemif.PortCfg{
  Id:       0,
  Name:     "memif_c0",
  IsServer: false,
  MemoryConfig: zmemif.MemoryConfig{
   NumQueuePairs: 1,
  },
  ConnectedFunc: Connected,
 }

注意通常在userspace侧使用client模式,queue pair需要少于8个,如果有多核RSS的需求,请创建多个interface,具体可以参考example/dpdk_co_worker
目录,请注意里面有一个ConnectedFunc的Callback函数,主要用于实现业务逻辑,例如一个简单的Echo,通过port.GetRXQueue/port.GetTXQueue函数获取queuepair,然后调用q.WritePacket/q.ReadPacket收发包即可。

func packetprocessing(p *zmemif.Port) {
 p.Wg.Add(1)
 defer p.Wg.Done()
 pkt := make([]byte, 2048)
 rxq0, err := p.GetRxQueue(0)
 if err != nil {
  logrus.Fatal("Get RX-Queue failed.")
 }
 txq0, err := p.GetTxQueue(0)
 if err != nil {
  logrus.Fatal("Get TX-Queue failed.")
 }
 //Server simply echo result to client
 for {
  pktLen, err := rxq0.ReadPacket(pkt)
  if err != nil {
   logrus.Warn("recv error:", err)
   continue
  }
  if pktLen > 0 {
   txq0.WritePacket(pkt[:pktLen])
  }
 }
}

func Connected(p *zmemif.Port) error {
 fmt.Println("Connected: ", p.GetName())
 go packetprocessing(p)
 return nil
}

接口结构体里面还新增了一个ExtendData接口,您可以将一些和这个Memif相关的数据结构放置其中,例如example/bw_test/sender/foo.go 中的包计数器

type PortStats struct {
 PacketCnt *uint64
}
cfg := &zmemif.PortCfg{
   Id:       ifindex,
   Name:     ifName,
   IsServer: serverMode,
   MemoryConfig: zmemif.MemoryConfig{
    NumQueuePairs: queueNum,
   },
   ConnectedFunc: Connected,
   ExtendData: &PortStats{
    PacketCnt: &pktCnt,
   },
  }
func sendpkt(p *zmemif.Port, qid int) {
 p.Wg.Add(1)
 defer p.Wg.Done()

 data := p.ExtendData.(*PortStats)
 txq, err := p.GetTxQueue(qid)
 if err != nil {
  logrus.Fatal("Get TX-Queue failed.")
 }
 //Client simply send result and calculate the RTT

 for {
  select {
  case <-p.QuitChan: // channel closed
   return
  default:
   sendpkt := make([]byte, 64)
   s := txq.WritePacket(sendpkt)
   if s > 0 {
    atomic.AddUint64(data.PacketCnt, 1)
   }
  }
 }
}    

创建完接口配置后,直接使用newport函数创建接口:

port, err := zmemif.NewPort(ctrlSock, cfg, nil)
 if err != nil {
  logrus.Fatal(err)
 }

最后调用unix-socket startpolling函数使能接口

ctrlSock.StartPolling()


原文链接:https://www.modb.pro/db/193489 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/18527.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

单点登录以及实现(前后端分离和前后端不分离方式)

本文主要使用springSecurity来实现&#xff0c;其他实现请参照其原理自行研究。 一&#xff0c;单系统登录机制 1、http无状态协议 web应用采用browser/server架构&#xff0c;http作为通信协议。http是无状态协议&#xff0c;浏览器的每一次请求&#xff0c;服务器会独立处…

谷粒学院(三) 项目前端知识

一、VS Code 1、插件安装 为方便后续开发&#xff0c;建议安装如下插件&#xff08;红色矩形框标记的插件&#xff09;2、创建项目 vscode本身没有新建项目的选项&#xff0c;所以要先创建一个空的文件夹&#xff0c;如project_xxxx。 然后打开vscode&#xff0c;再在vscode里面…

二维随机向量的数学期望E与协方差σ

目录 1. 二维随机向量(X,Y)的数学期望EX, EY 2. 二维随机向量函数zg(X,Y)的数学期望EZ 3. 二维随机向量(X,Y)的方差DX, DY 4. 二维随机向量的性质&#xff08;和、积的数学期望E与方差D&#xff09; 5. 二维随机向量的协方差COV和相关系数ρ 5.1 协方差COV定义 5.2 协方…

私有数据传参

在串口工具进行输入&#xff1a; echo 1 > /dev/myled0 ---->led1灯点亮 echo 0 > /dev/myled0 ---->led1灯熄灭 echo 1 > /dev/myled1 ---->led1灯点亮 echo 0 > /dev/myled1 ---->led1灯熄灭 echo 1 > /dev/myled2 ---->led1灯点亮 echo 0 >…

java计算机毕业设计springboot+vue员工管理系统

项目介绍 本员工管理系统是针对目前村委会管理的实际需求,从实际工作出发,对过去的员工管理系统存在的问题进行分析,完善用户的使用体会。采用计算机系统来管理信息,取代人工管理模式,查询便利,信息准确率高,节省了开支,提高了工作的效率。 本系统结合计算机系统的结构、概念、…

无线蓝牙耳机什么牌子好一点?2022年蓝牙耳机推荐

喜欢听音乐&#xff0c;自然离不开耳机的支持&#xff0c;一款优质且时尚的耳机&#xff0c;能够带来极致的音效&#xff0c;可是该如何选择合适的耳机&#xff0c;成为了摆在眼前一个很重要问题如果这个问题一直萦绕在你的脑海中&#xff0c;那么下面的选择相信定不会错。 TO…

多线程异步方法Spring Security框架的SecurityContext无法获取认证信息的原因及解决方案

Spring Security是Spring生态提供的用户应用安全保护的一个安全框架&#xff0c;其提供了一种高度可定制的实现身份认证(Authentication)&#xff0c;授权&#xff08;Authorization&#xff09;以及对常见的web攻击手段做防护的方法。 之前我的博客Oauth2与Spring Security框架…

章鱼网络 Community Call #4|推进章鱼社区治理

全长5922字&#xff0c;预计阅读 15 分钟 撰文&#xff1a;MiX 微信交流&#xff1a;MixMetaverse 北京时间2022年11月8日21点&#xff0c;章鱼网络举行第4期 Community Call&#xff0c;10月8日是章鱼一周年庆典&#xff0c;所以本次 Community Call 我们讨论了最近2个月内很…

git可视化工具-sourceTree

1. 下载 官网的下载地址&#xff0c;可以根据自己的电脑操作系统选择合适的版本下载&#xff0c;我下载的是windows版本 Sourcetree | Free Git GUI for Mac and Windows A Git GUI that offers a visual representation of your repositories. Sourcetree is a free Git clie…

ArcGIS提取图斑四至点,可不再是四至范围哦

上一期我们向大家介绍了 ArcGIS计算图斑四至坐标原来这么简单&#xff01;可不要在走弯路哦_GIS思维的博客-CSDN博客​​ArcGIS计算图斑四至坐标原来这么简单&#xff01;可不要在走弯路哦https://blog.csdn.net/kinghxj/article/details/127941005 今天我们要向大家介绍一下 …

Gem5 for Ubuntu20.04

一、安装Ubuntu 参考教程&#xff1a;史上最全最新Ubuntu20.04安装教程&#xff08;图文&#xff09; - 知乎 (zhihu.com) 1. 查看Ubuntu版本号命令&#xff1a; lsb_release -a 显示如下&#xff1a; Distributor ID: Ubuntu //类别是ubuntu Description: Ubuntu 2…

LeetCode力扣刷题——指针三剑客之二:树

树 一、数据结构介绍 作为&#xff08;单&#xff09;链表的升级版&#xff0c;我们通常接触的树都是二叉树&#xff08;binary tree&#xff09;&#xff0c;即每个节点最多有 两个子节点&#xff1b;且除非题目说明&#xff0c;默认树中不存在循环结构。LeetCode 默认的树表示…

树的孩子兄弟链存储表示创建、遍历等算法

【实验目的】 1. 掌握树的孩子兄弟链存储表示。 2. 掌握树的创建、遍历等算法。 【问题描述】 树的创建及其操作。 【基本要求】 1. 创建树的孩子兄弟链式存储表示。假设以二元组(F,C)的形式输入一颗树的诸边&#xff0c;其中F表示双亲结点标识&#xff0c;C表示孩子结点…

python的opencv操作记录(九)——图像清晰度计算

文章目录图像清晰度计算的一般思路图像梯度图像梯度绝对值与梯度角度基于梯度的方式计算梯度算子1——Sobel算子计算梯度算子2——Laplacian算子梯度统计评分平均梯度梯度总和Demo图像清晰度计算的一般思路 定义图像清晰度是一个比较定制化&#xff0c;或者说比较偏业务属性的…

MySql面试

0. InnoDB与MyISAM的区别 1&#xff09;InnoDB支持事务&#xff0c;MyISAM不支持&#xff0c;对于InnoDB每一条SQL语言都默认封装成事务&#xff0c;自动提 交&#xff0c;这样会影响速度&#xff0c;所以最好把多条SQL语言放在begin和commit之间&#xff0c;组成一个事务&…

【Vue3+TS】Axios拦截器封装及跨域 [cors] 解决方案

【Vue3TS】Axios拦截器封装及跨域 [cors] 解决方案简述封装过程文件路径拦截器封装 —— Interceptor.tsAPI请求管理前端跨域的解决方案后端跨域的解决方案效果结语简述 我的项目采用 Vue3TypeScriptViteElement Plus 的组合&#xff0c;这个组合也是Vue版本退出3.x后官方推荐版…

记一次服务宕机、优化全流程(以后也可以装X了)

视频地址&#xff1a; https://www.bilibili.com/video/BV1924y1y7jN 221115上午10点的时候客户反应进入小程序慢&#xff0c;打开监控发现服务pv已经超过了历史之最&#xff08;印象中最高的是100w&#xff09;&#xff0c;这次到了400w。原因是因为推广了一个发红包的活动。 …

Java练习题第二十七期:幸运的袋子

作者&#xff1a;有只小猪飞走啦 博客地址&#xff1a;文章目录前言一&#xff0c;题目二&#xff0c;解析三&#xff0c;代码前言 本博客是小博主在做Java算法题的过程中一些觉得可以分享的题目&#xff0c;希望对你们有帮助&#xff0c;如果哪里写错了或者有更好的解法&…

详解Unity中的Nav Mesh新特性|导航寻路系统 (一)

前言 之前我们讲解过Unity的Nav Mesh系统&#xff0c;其中提到过这个新版的Nav Mesh&#xff0c;它解决现有Nav Mesh的几个缺陷&#xff0c;比如无法动态烘焙&#xff0c;无法按照Agent的半径和高度适当的判断可行路径。现在新版Nav Mesh可以彻底解决这个问题&#xff01;某种…

实验送样、数据分析样品、组名命名规范

俗话说巧妇难为无米之炊&#xff0c;而样品就是“米”&#xff0c;没有样品&#xff0c;就无法开展实验&#xff0c;无法获得数据&#xff0c;无法毕业&#xff0c;无法发文章。鉴于样品的重要性&#xff0c;非常有必要对样品进行详细且规范的记录&#xff0c;方便他人也方便自…