Maison > développement back-end > Golang > Que se passe-t-il si j'exécute 2 goroutines pour modifier une VM et détruire la même VM à l'aide du package libvirt-go sur la même instance ?

Que se passe-t-il si j'exécute 2 goroutines pour modifier une VM et détruire la même VM à l'aide du package libvirt-go sur la même instance ?

王林
Libérer: 2024-02-08 21:48:12
avant
1293 Les gens l'ont consulté

我运行 2 个 goroutine 来修改虚拟机并在同一实例上使用 libvirt-go 包销毁同一虚拟机会发生什么?

php小编鱼仔你提到的问题涉及到在同一实例上同时使用libvirt-go包销毁虚拟机的情况。在这种情况下,会出现两个goroutine同时修改虚拟机的情况,可能会导致不可预料的结果。由于goroutine在并发执行时无法保证执行顺序,可能会导致竞态条件或数据冲突,进而导致虚拟机销毁失败、数据损坏或其他异常情况。为了避免这种情况,可以通过使用互斥锁或其他并发控制机制来确保同时只有一个goroutine可以修改虚拟机。这样可以保证操作的原子性和一致性,避免不必要的问题发生。

问题内容

众所周知,libvirt 是线程安全的。 但是,同时运行两个作用于同一资源的 goroutine(例如修改和删除虚拟机)会使其处于不明确的状态。 libvirt 如何决定 goroutine 的执行顺序?

这是我尝试过的代码:

package main

import (
    "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\n", err)
        return
    }
    defer conn.Close()

    // Create a new VM
    domainXML := `
        <domain type='kvm'>
            <name>myvm</name>
            <memory unit='KiB'>1048576</memory>
            <vcpu placement='static'>1</vcpu>
            <os>
                <type arch='x86_64' machine='pc-i440fx-2.9'>hvm</type>
                <boot dev='hd'/>
            </os>
            <devices>
                <disk type='file' device='disk'>
                    <driver name='qemu' type='qcow2'/>
                    <source file='path/to/disk'/>
                    <target dev='vda' bus='virtio'/>
                    <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
                </disk>
            </devices>
        </domain>`

    dom, err := createVM(conn, domainXML)
    if err != nil {
        fmt.Printf("Failed to create VM: %v\n", 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
}

Copier après la connexion

程序成功完成,因此域被破坏并可以重新创建 但再次运行会导致以下错误:

virError(Code=9, Domain=20, Message='operation failed: domain 'myvm' already exists with uuid 32c25acb-a4c5-4bfd-b2f5-f07b3d9b8eea')
Copier après la connexion

解决方法

线程安全只是意味着当多个线程同时使用同一个连接时,代码不会出现内存损坏问题。

您将获得的语义行为仍然是不确定的。

libvirt QEMU/KVM 驱动程序在客户端应用程序和 libvirtd(或 virtqemud)守护进程之间使用 RPC 层。所以首先你有非确定性,其中 Goroutine 首先运行。当 libvirt-go-module API 通过 CGo 调用 C ibvirt.so 库时,它们将被锁定到本机操作系统线程,然后该线程将在 libvirt.so 内部同步,以决定哪个首先将其 RPC 消息发送到网络上。在 libvirtd 守护进程中,也有很多线程,并且 RPC 消息理论上是 FIFO 处理的,但是,libvirtd 内部的 API 逻辑仍然会争夺锁,因此在与 QEMU 通信/交互时会增加更多的不确定性。基本上,您的 SetMaxMemoryDestroy API 调用可以按任一顺序运行。如果您需要保证顺序,则需要在应用程序中对它们进行序列化,以便仅在完成 ​​SetMaxMemory 后调用 Destroy

最后 IIUC 你的 Go 代码并不健壮,因为 main() 方法生成了两个 goroutine,但没有等待它们中的任何一个完成。 IOW,在任一 goroutine 完全运行之前,Go 进程很可能会退出。这可能就是为什么您收到有关 VM 已存在的错误消息的原因 - deleteVM goroutine 在进程退出之前从未运行。

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal