内存数据库中的 VMWare ESXi 在单个 blade 上跨 VM 共享

VMWare ESXi in memory database shared across VMs on a single blade

可能是个愚蠢的问题(抱歉!)但是在 VMWare ESXi 中,有什么方法可以让我在同一个 blade 上的 VM 之间共享内存,这样两个 VM 就可以通过共享内存块而不是执行进程间通信比使用消息?我知道我可以跨 VM 共享内存,但我感兴趣的是进程间通信。目的是两个 VM 可以非常快速地访问内存中的数据库,但是(与托管 OS 解决方案不同)如果 VM宕机了,另一台虚拟机还能愉快地继续运行。

VMCI 是您所需要的。遗憾的是,vSphere 6 及更高版本的 VM 之间已弃用 VMCI。

根据 vSockets API 文档,它说:

"The original VMCI library was released as an experimental C language interface with Workstation 6.0. VMCI included a datagram API and a shared memory API. Both interfaces were discontinued in Workstation 6.5."

所以现在看来​​您只能使用 vmci SOCK_DGRAM 或 SOCK_STREAM 套接字。它们的行为很像 tcp/ip 套接字,网上有很多关于如何编写使用它们的代码的信息,你基本上只需要 header vmci_sockets.h 就可以了。

您会发现 vsocket 通信的来宾端很简单,但是您需要在 ESXi 主机上向 运行 编写某种服务器来托管您的数据库,这是棘手的部分。如果您在 ESXi 上启用 ssh 并四处嗅探,您会发现一个带有 /dev/vsock 设备的非常 unix-like 系统,您可以查询该设备以获取 vsocket 协议系列(对于您的客人来说可能有所不同,您需要调用 ioctl)。不幸的是(我试过了)简单地编译一个 64 位静态链接的 Linux 二进制文件只会给你一个段错误,因为 ESXi OS 与 Linux 不够相似。

有一个 SDK,您可以尝试使用它来创建程序,但是它不适合胆小的人,有些人花了好几天的时间只是试图让它编译,所以如果您愿意,可以尝试这条路线,但我不推荐它。 Google 对于 "VMWare ESXi toolchain".

但是,如果您正在寻找在 ESXi 上获得自己的服务器 运行ning 的更快途径,并且准备使用 Python,您会发现 5.5 和 6.0 都带有相当 up-to-date Python(Python ESXi v6.0 上的 2.7.9)。 VMWare 无益地删除了 .py 库文件,只留下 .pyc 文件,因此您无法轻易看出这是否与标准版本不同,但它的功能肯定足以获得基本的套接字服务器 运行ning.

Python 套接字模块不理解 vmci 套接字系列,因此您需要使用 ctypes 绕过它直接调用 c 库套接字函数。您可以使用纯 python 创建套接字,甚至可以调用 listen() 但例如bind() 隐含地希望您处理 sockaddr_in 结构。

因此您需要检查 vmci_sockets.h header,并提出 Python ctypes 结构和函数来反映您从 C 中使用的结构和函数,例如:

class sockaddr_vm(Structure):
    _fields_ = [("svm_family", c_ushort),
                ("svm_reserved1", c_ushort),
                ("svm_port", c_uint),
                ("svm_cid", c_uint),
                ("svm_zero", c_uint),
               ]

然后可以将其传递到 libc bind/recvfrom/sendto 调用中,您可以通过以下方式访问:

libc = cdll.LoadLibrary("libc.so.6")

然后您可以绕过 Pythons 套接字模块绑定到您的套接字,即

addr = sockaddr_vm()
addr.svm_family = af     # address family obtained from ioctl
addr.svm_reserved1 = 0
addr.svm_cid = VMADDR_CID_ANY    # 0xffffffff
addr.svm_port = port
addr.svm_zero = 0

# s is the socket, created with python socket.socket()
out = libc.bind(s.fileno(), pointer(addr), sizeof(addr))

ESXi 上 Python 的一个警告是,您似乎可以使用的内存有限:我尝试分配 16MB 缓冲区,但 Python 拒绝给我内存错误,但这对我当时正在做的事情来说不是问题,所以我没有费心去寻找解决方法。我怀疑有一个设置可以解决这个问题。

让您的脚本在 ESXi 启动时启动留作 reader 的练习,但这应该能让您入门。玩得开心!