Vanliga användningsmönster i Azure SDK för Go
Azure Core-paketet (azcore
) i Azure SDK för Go implementerar flera mönster som tillämpas i hela SDK:t:
- HTTP-pipelineflödet, som är den underliggande HTTP-mekanismen som används av SDK:s klientbibliotek.
- Sidnumrering (metoder som returnerar samlingar).
- Långvariga åtgärder (LRO:er).
Sidnumrering (metoder som returnerar samlingar)
Många Azure-tjänster returnerar samlingar med objekt. Eftersom antalet objekt kan vara stort returnerar dessa klientmetoder en pager, vilket gör att appen kan bearbeta en sida med resultat i taget. Dessa typer definieras individuellt för olika kontexter men har gemensamma egenskaper, till exempel en NextPage
metod.
Anta till exempel att det finns en ListWidgets
metod som returnerar en WidgetPager
. Du använder sedan som WidgetPager
du ser här:
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...
}
Tidskrävande åtgärder
Vissa åtgärder i Azure kan ta lång tid att slutföra, allt från några sekunder till några dagar. Exempel på sådana åtgärder är att kopiera data från en käll-URL till en lagringsblob eller träna en AI-modell för att identifiera formulär. Dessa långvariga åtgärder (LRO: er) lämpar sig inte bra för standard-HTTP-flödet för en relativt snabb begäran och ett relativt snabbt svar.
Enligt konvention är metoder som startar en LRO prefix med "Begin" och returnerar en Poller. Poller används för att regelbundet avsöka tjänsten tills åtgärden har slutförts.
Följande exempel illustrerar olika mönster för hantering av LRI:er. Du kan också lära dig mer från källkoden poller.go i SDK:et.
Blockera anrop till PollUntilDone
PollUntilDone
hanterar hela intervallet för en avsökningsåtgärd tills ett terminaltillstånd har nåtts. Den returnerar sedan det slutliga HTTP-svaret för avsökningsåtgärden med innehållet i nyttolasten i det respType
angivna gränssnittet.
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)
Anpassad avsökningsloop
Poll
skickar en avsökningsbegäran till avsökningsslutpunkten och returnerar svaret eller ett fel.
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)
Återuppta från en tidigare åtgärd
Extrahera och spara meritförteckningstoken från en befintlig Poller.
Om du vill återuppta avsökningen, kanske i en annan process eller på en annan dator, skapar du en ny PollerResponse
instans och initierar den genom att anropa dess Resume
metod och skicka den den tidigare sparade återställningstoken.
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-pipelineflöde
De olika klienterna tillhandahåller en abstraktion över en Azure-tjänsts HTTP-API för att möjliggöra kodkomplettering och kompilering av tidstypsäkerhet. Så du behöver inte ta itu med transportmekanik på lägre nivå. Men du kan anpassa transportmekaniken (till exempel återförsök och loggning).
SDK:t gör HTTP-begäranden via en HTTP-pipeline. Pipelinen beskriver sekvensen med steg som utförs för varje http-begärandesvar tur och retur.
Pipelinen består av en transport tillsammans med valfritt antal principer:
- Transporten skickar begäran till tjänsten och tar emot svaret.
- Varje princip slutför en specifik åtgärd i pipelinen.
Det här diagrammet illustrerar flödet i en pipeline:
Alla klientpaket delar ett Core-paket med namnet azcore
. Det här paketet konstruerar HTTP-pipelinen med sin ordnade uppsättning principer, vilket säkerställer att alla klientpaket fungerar konsekvent.
- När en HTTP-begäran skickas körs alla principer i den ordning de lades till i pipelinen innan begäran skickas till HTTP-slutpunkten. Dessa principer lägger vanligtvis till begärandehuvuden eller loggar den utgående HTTP-begäran.
- När Azure-tjänsten har svarat körs alla principer i omvänd ordning innan svaret återgår till koden. De flesta principer ignorerar svaret, men loggningsprincipen registrerar svaret. Återförsöksprincipen kan utfärda begäran igen, vilket gör din app mer motståndskraftig mot nätverksfel.
Varje princip tillhandahålls med nödvändiga begärande- eller svarsdata, tillsammans med alla nödvändiga kontexter för att köra principen. Principen slutför sin åtgärd med angivna data och skickar sedan kontroll till nästa princip i pipelinen.
Som standard skapar varje klientpaket en pipeline som är konfigurerad för att fungera med den specifika Azure-tjänsten. Du kan också definiera dina egna anpassade principer och infoga dem i HTTP-pipelinen när du skapar en klient.
Grundläggande HTTP-pipelineprinciper
Core-paketet innehåller tre HTTP-principer som ingår i varje pipeline:
Anpassade HTTP-pipelineprinciper
Du kan definiera din egen anpassade princip för att lägga till funktioner utöver vad som ingår i Core-paketet. Om du till exempel vill se hur din app hanterar nätverks- eller tjänstfel kan du skapa en princip som matar in fel när begäranden görs under testningen. Eller så kan du skapa en princip som hånar en tjänsts beteende för testning.
Om du vill skapa en anpassad HTTP-princip definierar du din egen struktur med en Do
metod som implementerar Policy
gränssnittet:
- Principens
Do
metod bör utföra åtgärder efter behov på inkommandepolicy.Request
. Exempel på åtgärder är loggning, inmatning av ett fel eller ändring av någon av begärans URL,frågeparametrar eller begärandehuvuden. - Metoden
Do
vidarebefordrar (ändrad) begäran till nästa princip i pipelinen genom att anropa metoden för begäranNext
. Next
http.Response
returnerar felet och . Din princip kan utföra alla nödvändiga åtgärder, som att logga svaret/felet.- Principen måste returnera ett svar och ett fel tillbaka till den tidigare principen i pipelinen.
Kommentar
Politiken måste vara goroutine-säker. Goroutine-säkerhet gör att flera goroutines kan komma åt ett enda klientobjekt samtidigt. Det är vanligt att en princip är oföränderlig när den har skapats. Denna oföränderlighet säkerställer att goroutinen är säker.
I följande avsnitt visas hur du definierar en anpassad princip.
Principmall
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
}
Anpassad HTTP-transport
En transport skickar en HTTP-begäran och returnerar svaret/felet. Transporten anropas av den sista principen i pipelinen. Det är den första principen som hanterar svaret innan svaret/felet returneras till pipelinens principer (i omvänd ordning).
Som standard använder klienterna det delade http.Client
från Gos standardbibliotek.
Du skapar en anpassad tillståndskänslig eller tillståndslös transport på samma sätt som du skapar en anpassad princip. I det tillståndskänsliga fallet implementerar du metoden Do
som ärvts från transportörgränssnittet . I båda fallen tar funktionen eller Do
metoden återigen emot en azcore.Request
, returnerar en azCore.Response
och utför åtgärder i samma ordning som en princip.
Ta bort ett JSON-fält när du anropar en Azure-åtgärd
Åtgärder som JSON-MERGE-PATCH
att skicka en JSON null
för att ange att ett fält ska tas bort (tillsammans med dess värde):
{
"delete-me": null
}
Det här beteendet står i konflikt med SDK:ts standardmarsering som anger omitempty
som ett sätt att lösa tvetydigheten mellan ett fält som ska undantas och dess nollvärde.
type Widget struct {
Name *string `json:",omitempty"`
Count *int `json:",omitempty"`
}
I föregående exempel Name
definieras och Count
som pekare-till-typ för att skilja mellan ett saknat värde (nil
) och ett nollvärde (0), vilket kan ha semantiska skillnader.
I en HTTP PATCH-åtgärd påverkar inte fält vars värde är nil
värdet i serverns resurs. När du uppdaterar en widgets Count
fält anger du det nya värdet för Count
och lämnar Name
som nil
.
För att uppfylla kravet på att skicka en JSON null
NullValue
används funktionen:
w := Widget{
Count: azcore.NullValue(0).(*int),
}
Den här koden anger Count
till en explicit JSON null
. När begäran skickas till servern tas resursens Count
fält bort.
Se även
Feedback
https://aka.ms/ContentUserFeedback.
Kommer snart: Under hela 2024 kommer vi att fasa ut GitHub-problem som feedbackmekanism för innehåll och ersätta det med ett nytt feedbacksystem. Mer information finns i:Skicka och visa feedback för