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:
- Tok kanálu HTTP, což je základní mechanismus HTTP používaný klientskými knihovnami sady SDK.
- Stránkování (metody vracející kolekce)
- Dlouhotrvající operace (LRO)
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:
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í:
- Metoda vaší zásady
Do
by měla provádět operace podle potřeby na příchozíchpolicy.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ů. - Metoda
Do
předá (změněný) požadavek na další zásadu v kanálu zavoláním metody požadavkuNext
. Next
http.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.- 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 Do
azcore.Request
azCore.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 , Count
která bude ponechána Name
jako nil
.
Ke splnění požadavku na odeslání JSON null
se 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í.