php小编鱼仔你提到的问题涉及到在同一实例上同时使用libvirt-go包销毁虚拟机的情况。在这种情况下,会出现两个goroutine同时修改虚拟机的情况,可能会导致不可预料的结果。由于goroutine在并发执行时无法保证执行顺序,可能会导致竞态条件或数据冲突,进而导致虚拟机销毁失败、数据损坏或其他异常情况。为了避免这种情况,可以通过使用互斥锁或其他并发控制机制来确保同时只有一个goroutine可以修改虚拟机。这样可以保证操作的原子性和一致性,避免不必要的问题发生。
问题内容
众所周知,libvirt 是线程安全的。但是,同时运行两个作用于同一资源的 goroutine(例如修改和删除虚拟机)会使其处于不明确的状态。 libvirt 如何决定 goroutine 的执行顺序?
这是我尝试过的代码:
package mainimport ( "fmt" "github.com/libvirt/libvirt-go")func main() { conn, err := libvirt.NewConnect("qemu:///system") if err != nil { fmt.Printf("Failed to connect to libvirt: %v", err) return } defer conn.Close() // Create a new VM domainXML := ` myvm10485761hvm ` dom, err := createVM(conn, domainXML) if err != nil { fmt.Printf("Failed to create VM: %v", err) return } go modifyVMMemory(dom, 2*1024*1024) // 2 GiB go deleteVM(dom)}func createVM(conn *libvirt.Connect, domainXML string) (*libvirt.Domain, error) { dom, err := conn.DomainCreateXML(domainXML, 0) if err != nil { return nil, err } return dom, nil}func modifyVMMemory(dom *libvirt.Domain, newMemory uint64) error { err := dom.SetMaxMemory(newMemory) if err != nil { return err } fmt.Print("Modified VM") return nil}func deleteVM(dom *libvirt.Domain) error { err := dom.Destroy() if err != nil { return err } err = dom.Undefine() if err != nil { return err } fmt.Print("Deleted VM") return nil}
登录后复制
程序成功完成,因此域被破坏并可以重新创建但再次运行会导致以下错误:
virError(Code=9, Domain=20, Message='operation failed: domain 'myvm' already exists with uuid 32c25acb-a4c5-4bfd-b2f5-f07b3d9b8eea')
登录后复制
解决方法
线程安全只是意味着当多个线程同时使用同一个连接时,代码不会出现内存损坏问题。
您将获得的语义行为仍然是不确定的。
libvirt QEMU/KVM 驱动程序在客户端应用程序和 libvirtd(或 virtqemud)守护进程之间使用 RPC 层。所以首先你有非确定性,其中 Goroutine 首先运行。当 libvirt-go-module API 通过 CGo 调用 C ibvirt.so 库时,它们将被锁定到本机操作系统线程,然后该线程将在 libvirt.so 内部同步,以决定哪个首先将其 RPC 消息发送到网络上。在 libvirtd 守护进程中,也有很多线程,并且 RPC 消息理论上是 FIFO 处理的,但是,libvirtd 内部的 API 逻辑仍然会争夺锁,因此在与 QEMU 通信/交互时会增加更多的不确定性。基本上,您的 SetMaxMemory 和 Destroy API 调用可以按任一顺序运行。如果您需要保证顺序,则需要在应用程序中对它们进行序列化,以便仅在完成 SetMaxMemory 后调用 Destroy
最后 IIUC 你的 Go 代码并不健壮,因为 main() 方法生成了两个 goroutine,但没有等待它们中的任何一个完成。 IOW,在任一 goroutine 完全运行之前,Go 进程很可能会退出。这可能就是为什么您收到有关 VM 已存在的错误消息的原因 – deleteVM goroutine 在进程退出之前从未运行。
以上就是我运行 2 个 goroutine 来修改虚拟机并在同一实例上使用 libvirt-go 包销毁同一虚拟机会发生什么?的详细内容,更多请关注【创想鸟】其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。
发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/2485146.html