Was passiert, wenn ich zwei Goroutinen ausführe, um eine VM zu ändern und dieselbe VM mithilfe des libvirt-go-Pakets auf derselben Instanz zu zerstören?

王林
Freigeben: 2024-02-08 21:48:12
nach vorne
1113 Leute haben es durchsucht

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

php-Editor Yuzai Das von Ihnen erwähnte Problem besteht darin, das libvirt-go-Paket zu verwenden, um gleichzeitig die virtuelle Maschine auf derselben Instanz zu zerstören. In diesem Fall ändern möglicherweise zwei Goroutinen gleichzeitig die virtuelle Maschine, was zu unvorhersehbaren Ergebnissen führen kann. Da Goroutinen bei gleichzeitiger Ausführung die Ausführungsreihenfolge nicht garantieren können, kann es zu Race Conditions oder Datenkonflikten kommen, die zu Fehlschlägen bei der Zerstörung virtueller Maschinen, Datenbeschädigung oder anderen Anomalien führen können. Um diese Situation zu vermeiden, können Sie mithilfe einer Mutex-Sperre oder eines anderen Mechanismus zur Parallelitätskontrolle sicherstellen, dass jeweils nur eine Goroutine die virtuelle Maschine ändern kann. Dies kann die Atomizität und Konsistenz von Vorgängen sicherstellen und unnötige Probleme vermeiden.

Frageninhalt

Wie wir alle wissen, ist libvirt threadsicher. Wenn jedoch zwei Goroutinen gleichzeitig ausgeführt werden, die auf dieselbe Ressource einwirken (z. B. das Ändern und Löschen einer virtuellen Maschine), bleibt diese in einem mehrdeutigen Zustand. Wie entscheidet libvirt über die Ausführungsreihenfolge von Goroutinen?

Das ist der Code, den ich ausprobiert habe:

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
}

Nach dem Login kopieren

Der Vorgang wurde erfolgreich abgeschlossen, sodass die Domain zerstört wurde und neu erstellt werden kann Aber eine erneute Ausführung führt zu folgendem Fehler:

virError(Code=9, Domain=20, Message='operation failed: domain 'myvm' already exists with uuid 32c25acb-a4c5-4bfd-b2f5-f07b3d9b8eea')
Nach dem Login kopieren

Workaround

Thread-Sicherheit bedeutet einfach, dass der Code keine Speicherbeschädigungsprobleme aufweist, wenn mehrere Threads gleichzeitig dieselbe Verbindung verwenden.

Das semantische Verhalten, das Sie erhalten, ist noch undefiniert.

libvirt QEMU/KVM-Treiber in der Client-Anwendung und 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

Schließlich ist IIUC Ihr Go-Code nicht robust, weil main() 方法生成了两个 goroutine,但没有等待它们中的任何一个完成。 IOW,在任一 goroutine 完全运行之前,Go 进程很可能会退出。这可能就是为什么您收到有关 VM 已存在的错误消息的原因 - deleteVM die Goroutine erst dann ausgeführt wird, wenn der Prozess beendet wird.

Das obige ist der detaillierte Inhalt vonWas passiert, wenn ich zwei Goroutinen ausführe, um eine VM zu ändern und dieselbe VM mithilfe des libvirt-go-Pakets auf derselben Instanz zu zerstören?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:stackoverflow.com
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!