Sdílet prostřednictvím


Běžné vzory použití v sadě Azure SDK for Go

Balíček Azure Core (azcore) v sadě Azure SDK for Go implementuje několik vzorů, které se použijí v celé sadě SDK:

Stránkování (metody vracející kolekce)

Mnoho služeb Azure vrací kolekce položek. Vzhledem k tomu, že počet položek může být velký, vrátí tyto klientské metody Pager, což vaší aplikaci umožňuje zpracovat jednu stránku výsledků najednou. Tyto typy jsou jednotlivě definovány pro různé kontexty, ale sdílejí společné vlastnosti, jako je NextPage metoda.

Předpokládejme například, že existuje ListWidgets metoda, která vrací WidgetPager. Pak byste použili WidgetPager toto:

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...
}

Dlouhotrvající operace

Dokončení některých operací v Azure může trvat dlouho, od několika sekund až po několik dní. Mezi příklady takových operací patří kopírování dat ze zdrojové adresy URL do objektu blob úložiště nebo trénování modelu AI pro rozpoznávání formulářů. Tyto dlouhotrvající operace (LRO) jsou špatně vhodné pro standardní tok HTTP relativně rychlého požadavku a odpovědi.

Podle konvence jsou metody, které spouští LRO, předponou Begin a vrací Poller. Poller se používá k pravidelnému dotazování služby, dokud se operace nedokončí.

Následující příklady ilustrují různé vzory pro zpracování LRO. Další informace najdete také ve zdrojovém kódu poller.go v sadě SDK.

Blokování volání PollUntilDone

PollUntilDone zpracovává celé rozpětí operace dotazování, dokud se nedosáhne stavu terminálu. Pak vrátí konečnou odpověď HTTP pro operaci dotazování s obsahem datové části v respType rozhraní.

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)

Přizpůsobená smyčka hlasování

Poll odešle požadavek na dotazování do koncového bodu dotazování a vrátí odpověď nebo chybu.

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)

Obnovení z předchozí operace

Extrahujte a uložte token životopisu z existujícího Polleru.

Pokud chcete pokračovat v dotazování, možná v jiném procesu nebo na jiném počítači, vytvořte novou PollerResponse instanci a pak ji inicializujete voláním metody Resume , která jí předá dříve uložený obnovovací token.

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)

Tok kanálu HTTP

Různí klienti sady SDK poskytují abstrakci přes rozhraní REST API Azure, aby bylo možné zajistit dokončení kódu a bezpečnost typů kompilace, takže nemusíte řešit mechanismy přenosu nižší úrovně přes protokol HTTP. Můžete ale přizpůsobit mechaniku přenosu (například opakování a protokolování).

Sada SDK provádí požadavky HTTP prostřednictvím kanálu HTTP. Kanál popisuje posloupnost kroků provedených pro každou odezvu odezvy požadavku HTTP.

Kanál se skládá z přenosu společně s libovolným počtem zásad:

  • Přenos odešle požadavek do služby a obdrží odpověď.
  • Každá zásada dokončí určitou akci v kanálu.

Následující diagram znázorňuje tok kanálu:

Diagram znázorňující tok kanálu

Všechny klientské balíčky sdílejí balíček Core s názvem azcore. Tento balíček vytvoří kanál HTTP s seřazenou sadou zásad a zajistí, aby se všechny klientské balíčky chovaly konzistentně.

Po odeslání požadavku HTTP se všechny zásady spustí v pořadí, v jakém byly přidány do kanálu před odesláním požadavku do koncového bodu HTTP. Tyto zásady obvykle přidávají hlavičky požadavků nebo protokolují odchozí požadavek HTTP.

Jakmile služba Azure odpoví, všechny zásady se spustí v opačném pořadí, než se odpověď vrátí do kódu. Většina zásad odpověď ignoruje, ale zásady protokolování zaznamenávají odpověď. Zásady opakování můžou požadavek znovu vytvořit, aby byla vaše aplikace odolnější vůči selháním sítě.

Každá zásada se poskytuje s potřebnými daty požadavků nebo odpovědí spolu s jakýmkoliv nezbytným kontextem pro spuštění zásady. Zásada dokončí svou operaci s danými daty a pak předá řízení další zásadě v kanálu.

Ve výchozím nastavení každý klientský balíček vytvoří kanál nakonfigurovaný tak, aby fungoval s danou konkrétní službou Azure. Můžete také definovat vlastní zásady a vložit je do kanálu HTTP při vytváření klienta.

Základní zásady kanálu HTTP

Balíček Core poskytuje tři zásady HTTP, které jsou součástí každého kanálu:

Vlastní zásady kanálu HTTP

Můžete definovat vlastní zásady pro přidání funkcí nad rámec obsahu balíčku Core. Pokud například chcete zjistit, jak se vaše aplikace zabývá selháním sítě nebo služby, můžete vytvořit zásadu, která při testování vloží chybu. Nebo můžete vytvořit zásadu, která napodobení chování služby při testování.

Pokud chcete vytvořit vlastní zásadu HTTP, definujte vlastní strukturu pomocí Do metody, která implementuje Policy rozhraní:

  1. Metoda vaší zásady Do by měla provádět operace podle potřeby na příchozích policy.Request. Mezi příklady operací patří protokolování, vložení selhání nebo úprava adresy URL požadavku, parametrů dotazu nebo hlaviček požadavků.
  2. Metoda Do předá (změněný) požadavek na další zásadu v kanálu zavoláním metody požadavku Next .
  3. Nexthttp.Response vrátí chybu a chybu. Vaše zásada může provádět jakoukoli nezbytnou operaci, jako je protokolování odpovědi nebo chyby.
  4. Vaše zásada musí vrátit odpověď a chybu zpět na předchozí zásadu v kanálu.

Poznámka:

Zásady musí být goroutově bezpečné. Goroutine safety umožňuje více goroutin současně přistupovat k jednomu klientskému objektu. Zásady se dají po vytvoření neměnně měnit. Tato neměnnost zajišťuje, že goroutin je bezpečný.

Šablona vlastních zásad

Následující kód lze použít jako výchozí bod k definování vlastních zásad.

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
}

Vlastní přenos HTTP

Přenos odešle požadavek HTTP a vrátí odpověď nebo chybu. První zásadou pro zpracování požadavku je také poslední zásada, která zpracovává odpověď před vrácením odpovědi nebo chyby zpět do zásad kanálu (v obráceném pořadí). Poslední zásada v kanálu vyvolá přenos.

Ve výchozím nastavení používají klienti sdílené http.Client ze standardní knihovny Go.

Vlastní stavový nebo bezstavový přenos vytvoříte stejným způsobem jako vlastní zásadu. Ve stavovém případě implementujete metodu Do zděděnou z rozhraní Transporteru. V oboupřípadechch Doazcore.RequestazCore.Response

Jak odstranit pole JSON při vyvolání operace Azure

Operace, jako je JSON-MERGE-PATCH odeslání JSON null , označující, že pole by se mělo odstranit (spolu s jeho hodnotou):

{
    "delete-me": null
}

Toto chování je v konfliktu s výchozím zařazováním sady SDK, které určuje omitempty způsob řešení nejednoznačnosti mezi polem, které se má vyloučit, a jeho nulovou hodnotou.

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

V předchozím příkladu a Count jsou definovány jako ukazatel na typ, Name aby se rozlišily mezi chybějící hodnotou (nil) a nulou (0), která může mít sémantické rozdíly.

V operaci HTTP PATCH nemají žádná pole s hodnotou nil vliv na hodnotu v prostředku serveru. Při aktualizaci pole widgetu Count zadejte novou hodnotu , Countkterá bude ponechána Name jako nil.

Ke splnění požadavku na odeslání JSON nullse NullValue použije funkce:

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

Tento kód nastaví Count explicitní JSON null. Po odeslání požadavku na server se pole zdroje Count odstraní.

Viz také