Megosztás a következőn keresztül:


Gyakori használati minták az Azure SDK for Go-ban

Az Azure SDK for Go Azure Core (azcore) csomagja számos, az SDK-ban alkalmazott mintát valósít meg:

Lapozás (gyűjteményeket visszaadó metódusok)

Számos Azure-szolgáltatás több elemgyűjteményt ad vissza. Mivel az elemek száma nagy lehet, ezek az ügyfélmetodusok egy Pager-t adnak vissza, amely lehetővé teszi, hogy az alkalmazás egyszerre egy oldalnyi eredményt dolgoz fel. Ezek a típusok egyedileg vannak definiálva a különböző környezetekhez, de közös jellemzőkkel rendelkeznek, például egy metódussal NextPage .

Tegyük fel például, hogy van egy ListWidgets metódus, amely egy WidgetPager. Ezután használja az WidgetPager itt látható módon:

func (c *WidgetClient) ListWidgets(options *ListWidgetOptions) WidgetPager {
    // ...
}

pager := client.ListWidgets(options)

for pager.NextPage(ctx) {
    for _, w := range pager.PageResponse().Widgets {
        process(w)
    }
}

if pager.Err() != nil {
    // Handle error...
}

Hosszú ideig futó műveletek

Az Azure-beli műveletek némelyike hosszú időt vehet igénybe, akár néhány másodperctől néhány napig is. Ilyen műveletek például az adatok másolása egy forrás URL-címről egy tárolóblobba, vagy egy AI-modell betanítása az űrlapok felismerésére. Ezek a hosszú ideig futó műveletek (LPO-k) nem nyújtanak jól a viszonylag gyors kérések és válaszok szabványos HTTP-folyamatához.

Konvenció szerint az LRO-t kezdő metódusok "Start" előtaggal vannak elnevezve, és pollert adnak vissza. A Poller használatával rendszeres időközönként lekérdezhető a szolgáltatás, amíg a művelet be nem fejeződik.

Az alábbi példák az LPO-k kezelésének különböző mintáit szemléltetik. További információt az SDK poller.go forráskódjából is megtudhat.

A PollUntilDone hívásának letiltása

PollUntilDone a lekérdezési művelet teljes időtartamát kezeli, amíg el nem éri a terminálállapotot. Ezután visszaadja a lekérdezési művelet végső HTTP-válaszát a megadott felületen található hasznos adat respType tartalmával.

resp, err := client.BeginCreate(context.Background(), "blue_widget", nil)

if err != nil {
    // Handle error...
}

w, err = resp.PollUntilDone(context.Background(), nil)

if err != nil {
    // Handle error...
}

process(w)

Testreszabott lekérdezési ciklus

Poll lekérdezési kérelmet küld a lekérdezési végpontnak, és visszaadja a választ vagy a hibát.

resp, err := client.BeginCreate(context.Background(), "green_widget")

if err != nil {
    // Handle error...
}

poller := resp.Poller

for {
    resp, err := poller.Poll(context.Background())

    if err != nil {
        // Handle error...
    }

    if poller.Done() {
        break
    }

    // Do other work while waiting.
}

w, err := poller.FinalResponse(ctx)

if err != nil {
    // Handle error...
}

process(w)

Folytatás egy korábbi műveletből

Bontsa ki és mentse az önéletrajz-jogkivonatot egy meglévő Pollerből.

A lekérdezés folytatásához , esetleg egy másik folyamatban vagy egy másik számítógépen hozzon létre egy új PollerResponse példányt, majd inicializálja azt a metódus meghívásával Resume , és adja át a korábban mentett folytatási jogkivonatot.

poller := resp.Poller
tk, err := poller.ResumeToken()

if err != nil {
    // Handle error...
}

resp = WidgetPollerResponse()

// Resume takes the resume token as an argument.
err := resp.Resume(tk, ...)

if err != nil {
    // Handle error...
}

for {
    resp, err := poller.Poll(context.Background())

    if err != nil {
        // Handle error...
    }

    if poller.Done() {
        break
    }

    // Do other work while waiting.
}

w, err := poller.FinalResponse(ctx)

if err != nil {
    // Handle error...
}

process(w)

HTTP-folyamat folyamata

A különböző ügyfelek absztrakciót biztosítanak egy Azure-szolgáltatás HTTP API-ján keresztül a kódkiegészítés és a fordítási idő típusú biztonság érdekében. Így nem kell foglalkoznia az alacsonyabb szintű közlekedési mechanikával. De testre szabhatja a szállítási mechanikát (például újrapróbálkozások és naplózás).

Az SDK HTTP-kéréseket küld egy HTTP-folyamaton keresztül. A folyamat leírja az egyes HTTP-kérés-válasz oda-vissza utakhoz végrehajtott lépések sorrendjét.

A folyamat egy átvitelből és tetszőleges számú szabályzatból áll:

  • Az átvitel elküldi a kérést a szolgáltatásnak, és megkapja a választ.
  • Minden szabályzat végrehajt egy adott műveletet a folyamatban.

Ez az ábra egy folyamat folyamatát szemlélteti:

Diagram that shows the flow of a pipeline.

Minden ügyfélcsomag rendelkezik egy Core-csomaggal.azcore Ez a csomag a HTTP-folyamatot a szabályzatok rendezett készletével hozza létre, biztosítva, hogy minden ügyfélcsomag következetesen viselkedjen.

  • HTTP-kérés küldésekor az összes szabályzat abban a sorrendben fut, amelyben hozzáadták őket a folyamathoz, mielőtt a kérést elküldené a HTTP-végpontnak. Ezek a szabályzatok általában kérésfejléceket adnak hozzá, vagy naplózják a kimenő HTTP-kérést.
  • Az Azure-szolgáltatás válasza után az összes szabályzat fordított sorrendben fut, mielőtt a válasz visszatér a kódhoz. A legtöbb szabályzat figyelmen kívül hagyja a választ, de a naplózási szabályzat rögzíti a választ. Előfordulhat, hogy az újrapróbálkozás szabályzata újra kiadja a kérést, így az alkalmazás ellenállóbbá válik a hálózati hibáktól.

Minden szabályzathoz a szükséges kérelem- vagy válaszadatok, valamint a szabályzat futtatásához szükséges környezetek találhatók. A szabályzat végrehajtja a műveletet a megadott adatokkal, majd átadja az irányítást a folyamat következő szabályzatának.

Alapértelmezés szerint minden ügyfélcsomag létrehoz egy folyamatot, amely konfigurálva van az adott Azure-szolgáltatással való együttműködésre. Az ügyfél létrehozásakor saját egyéni szabályzatokat is meghatározhat, és beszúrhatja őket a HTTP-folyamatba.

Alapvető HTTP-folyamatszabályzatok

A Core csomag három HTTP-szabályzatot biztosít, amelyek minden folyamat részét képezik:

Egyéni HTTP-folyamatszabályzatok

Saját egyéni szabályzatot is meghatározhat, hogy a Core-csomagban szereplő lehetőségeken túli képességeket adjon hozzá. Ha például azt szeretné látni, hogy az alkalmazás hogyan kezeli a hálózati vagy szolgáltatáshibákat, létrehozhat egy szabályzatot, amely hibát ad be a tesztelés során érkező kérések során. Létrehozhat egy olyan szabályzatot is, amely egy szolgáltatás viselkedését szimulálja a teszteléshez.

Egyéni HTTP-szabályzat létrehozásához definiálja saját struktúráját egy Do olyan módszerrel, amely implementálja a Policy felületet:

  1. A szabályzat metódusának szükség szerint végre kell hajtania Do a műveleteket a bejövőn policy.Request. Ilyen műveletek például a naplózás, a hiba injektálása vagy a kérés URL-címének, a lekérdezési paramétereknek vagy a kérelemfejléceknek a módosítása.
  2. A Do metódus a kérelem metódusának meghívásával továbbítja a (módosított) kérelmet a folyamat következő szabályzatának Next .
  3. Next visszaadja a http.Response hibát. A szabályzat bármilyen szükséges műveletet végrehajthat, például naplózhatja a választ/hibát.
  4. A szabályzatnak vissza kell adnia egy választ és egy hibát a folyamat előző házirendjéhez.

Megjegyzés:

A szabályzatnak goroutine-safenek kell lennie. A Goroutine biztonsága lehetővé teszi, hogy egyszerre több goroutine is hozzáférhessen egyetlen ügyfélobjektumhoz. A szabályzatok létrehozása után gyakran előfordul, hogy nem módosíthatók. Ez a megváltoztathatatlanság biztosítja, hogy a goroutine biztonságos legyen.

Az alábbi szakasz bemutatja, hogyan definiálhat egyéni szabályzatokat.

Szabályzatsablon

type MyPolicy struct {
    LogPrefix string
}

func (m *MyPolicy) Do(req *policy.Request) (*http.Response, error) {
	// Mutate/process request.
	start := time.Now()
	// Forward the request to the next policy in the pipeline.
	res, err := req.Next()
	// Mutate/process response.
	// Return the response & error back to the previous policy in the pipeline.
	record := struct {
		Policy   string
		URL      string
		Duration time.Duration
	}{
		Policy:   "MyPolicy",
		URL:      req.Raw().URL.RequestURI(),
		Duration: time.Duration(time.Since(start).Milliseconds()),
	}
	b, _ := json.Marshal(record)
	log.Printf("%s %s\n", m.LogPrefix, b)
	return res, err
}

func ListResourcesWithPolicy(subscriptionID string) error {
	cred, err := azidentity.NewDefaultAzureCredential(nil)
	if err != nil {
		return err
	}

	mp := &MyPolicy{
		LogPrefix: "[MyPolicy]",
	}
	options := &arm.ConnectionOptions{}
	options.PerCallPolicies = []policy.Policy{mp}
	options.Retry = policy.RetryOptions{
		RetryDelay: 20 * time.Millisecond,
	}

	con := arm.NewDefaultConnection(cred, options)
	if err != nil {
		return err
	}

	client := armresources.NewResourcesClient(con, subscriptionID)
	pager := client.List(nil)
	for pager.NextPage(context.Background()) {
		if err := pager.Err(); err != nil {
			log.Fatalf("failed to advance page: %v", err)
		}
		for _, r := range pager.PageResponse().ResourceListResult.Value {
			printJSON(r)
		}
	}
	return nil
}

Egyéni HTTP-átvitel

Az átvitel HTTP-kérést küld, és visszaadja a válaszát/hibáját. Az átvitelt a folyamat utolsó szabályzata hívja meg. Ez az első szabályzat, amely kezeli a választ, mielőtt visszaküldené a választ/hibát a folyamat szabályzatainak (fordított sorrendben).

Alapértelmezés szerint az ügyfelek a Go standard kódtárából származó megosztottat http.Client használják.

Egyéni állapotalapú vagy állapot nélküli átvitelt ugyanúgy hozhat létre, mint egy egyéni szabályzatot. Az állapotalapú esetben a Do Transporter felülettől örökölt metódust implementálja. Mindkét esetben a függvény vagy Do metódus ismét kap egy azcore.Request, egy visszaadott azCore.Response, és a műveletet ugyanabban a sorrendben hajtja végre, mint egy szabályzat.

JSON-mező törlése Azure-művelet meghívásakor

Olyan műveletek, mint például JSON-MERGE-PATCH a JSON null küldése egy mező törlésének jelzésére (az értékével együtt):

{
    "delete-me": null
}

Ez a viselkedés ütközik az SDK alapértelmezett marshalingjával, amely a kizárandó mező és a nulla érték közötti kétértelműség feloldására szolgál omitempty .

type Widget struct {
    Name *string `json:",omitempty"`
    Count *int `json:",omitempty"`
}

Az előző példában Name egy hiányzó érték (nil) és Count egy nulla (0) közötti egyértelműsítés érdekében mutató-típusként vannak definiálva, amelynek szemantikai eltérései lehetnek.

HTTP PATCH-művelet esetén minden olyan mező, amelynek értéke nil nem befolyásolja a kiszolgáló erőforrásának értékét. Widget mezőjének Count frissítésekor adja meg az új értéket Count, és hagyja a Name következőt: nil.

A JSON nullküldésére vonatkozó követelmény teljesítéséhez a függvény a NullValue következőt használja:

w := Widget{
    Count: azcore.NullValue(0).(*int),
}

Ez a kód explicit JSON-értékre nullvan halmazvaCount. Amikor a kérést elküldi a kiszolgálónak, az erőforrás mezője Count törlődik.

Kapcsolódó információk