Bagikan melalui


Pola penggunaan umum di SDK Azure untuk Go

Paket Inti Azure (azcore) di SDK Azure untuk Go mengimplementasikan beberapa pola yang diterapkan di seluruh SDK:

Paginasi (metode yang menampilkan koleksi)

Banyak layanan Azure menampilkan koleksi item. Karena jumlah item bisa saja besar, metode klien ini menampilkan Penyeranta, yang memungkinkan aplikasi Anda memproses satu halaman hasil dalam satu waktu. Jenis-jenis ini didefinisikan secara individual untuk berbagai konteks tetapi memiliki karakteristik yang sama, seperti metode NextPage.

Misalnya, ada metode ListWidgets yang menampilkan WidgetPager. Maka Anda akan menggunakan WidgetPager seperti yang ditunjukkan di sini:

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

Operasi jangka panjang

Beberapa operasi di Azure dapat memakan waktu yang lama untuk diselesaikan, dari beberapa detik hingga beberapa hari. Contoh operasi tersebut termasuk menyalin data dari URL sumber ke blob penyimpanan atau melatih model AI untuk mengenali formulir. Operasi jangka panjang (LMO) ini sangat cocok untuk alur HTTP standar dari permintaan dan respons yang relatif cepat.

Dengan konvensi, metode yang memulai LRO diawali dengan "Mulai" dan menampilkan Poller. Poller digunakan untuk secara berkala melakukan polling layanan sampai operasi selesai.

Contoh-contoh berikut menggambarkan berbagai pola dalam menangani LRO. Anda juga dapat mempelajari lebih lanjut dari kode sumber poller.go di SDK.

Memblokir panggilan ke PollUntilDone

PollUntilDone menangani seluruh rentang operasi polling sampai status terminal tercapai. Kemudian mengembalikan respons HTTP akhir untuk operasi polling dengan konten payload di respType antarmuka.

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)

Perulangan polling yang disesuaikan

Poll mengirimkan permintaan polling ke titik akhir polling dan menampilkan respons atau kesalahan.

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)

Melanjutkan dari operasi sebelumnya

Ekstrak dan simpan token lanjutkan dari Poller yang sudah ada.

Untuk melanjutkan polling, mungkin dalam proses yang lain atau di komputer lain, buat instans PollerResponse baru, kemudian inisialisasi dengan memanggil metode Resume terkait, yang akan meneruskan token resume yang disimpan sebelumnya.

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)

Aliran alur HTTP

Berbagai klien SDK menyediakan abstraksi atas REST API Azure untuk mengaktifkan penyelesaian kode dan keamanan jenis kompilasi-waktu sehingga Anda tidak perlu berurusan dengan mekanika transportasi tingkat bawah melalui HTTP. Namun, Anda dapat menyesuaikan mekanika transportasi (seperti percobaan ulang dan pengelogan).

SDK membuat permintaan melalui alur HTTP. Alur menjelaskan urutan langkah-langkah yang dilakukan untuk setiap perjalanan bolak-balik permintaan-respons.

Alur terdiri dari transportasi bersama dengan sejumlah kebijakan:

  • Transportasi mengirimkan permintaan ke layanan dan menerima tanggapan.
  • Setiap kebijakan menyelesaikan tindakan tertentu dalam alur.

Diagram berikut mengilustrasikan alur:

Diagram yang memperlihatkan alur.

Semua paket klien berbagi paket Inti bernama azcore. Paket ini membangun alur HTTP dengan serangkaian kebijakan terkait yang disusun, memastikan bahwa semua paket klien berperilaku konsisten.

Ketika permintaan HTTP dikirim, semua kebijakan berjalan sesuai urutan di mana mereka ditambahkan ke alur sebelum permintaan dikirim ke titik akhir HTTP. Kebijakan ini biasanya menambahkan header permintaan atau mencatat permintaan keluar.

Setelah layanan Azure merespons, semua kebijakan berjalan dalam urutan terbalik sebelum respons kembali ke kode Anda. Sebagian besar kebijakan mengabaikan respons, tetapi kebijakan pengelogan mencatat respons. Kebijakan coba lagi mungkin menghasilkan kembali permintaan, membuat aplikasi Anda lebih tahan terhadap kegagalan jaringan.

Setiap kebijakan dilengkapi dengan data respons atau permintaan yang diperlukan, bersama dengan konteks apa pun yang diperlukan untuk menjalankan kebijakan. Kebijakan ini menyelesaikan operasinya dengan data yang diberikan, kemudian meneruskan kontrol ke kebijakan berikutnya dalam alur.

Secara default, setiap paket klien membuat alur yang dikonfigurasi untuk bekerja dengan layanan Azure tertentu. Anda juga dapat menentukan kebijakan kustom Anda sendiri dan memasukkannya ke dalam alur HTTP saat membuat klien.

Kebijakan alur HTTP Inti

Paket Inti menyediakan tiga kebijakan HTTP yang merupakan bagian dari setiap alur:

Kebijakan alur HTTP kustom

Anda dapat menentukan kebijakan kustom Anda sendiri untuk menambahkan kemampuan di luar konten paket Core. Misalnya, untuk melihat cara aplikasi Anda menangani kegagalan jaringan atau layanan, Anda dapat membuat kebijakan yang menyuntikkan kesalahan saat permintaan dibuat selama pengujian. Atau Anda dapat membuat kebijakan yang meniru perilaku layanan untuk pengujian.

Untuk membuat kebijakan HTTP kustom, tentukan struktur Anda sendiri dengan metode Do yang mengimplementasikan antarmuka Policy:

  1. Metode Do kebijakan Anda harus melakukan operasi sesuai kebutuhan pada policy.Request yang masuk. Contoh operasi termasuk pengelogan, menyuntikkan kegagalan, atau memodifikasi URL permintaan, parameter kueri, atau header permintaan.
  2. Metode Do meneruskan permintaan (yang dimodifikasi) ke kebijakan berikutnya dalam alur dengan memanggil metode Next permintaan.
  3. Next menampilkan http.Response dan kesalahan. Kebijakan Anda dapat melakukan operasi apa pun yang diperlukan, seperti mencatat respons/kesalahan.
  4. Kebijakan Anda harus mengembalikan respons dan kesalahan kembali ke kebijakan sebelumnya dalam alur.

Catatan

Kebijakan harus goroutine-aman. Keamanan goroutine memungkinkan beberapa goroutine untuk mengakses satu objek klien secara bersamaan. Tidak dapat diubahnya kebijakan setelah dibuat merupakan hal yang umum. Keabadian ini memastikan goroutine aman.

Templat kebijakan kustom

Kode berikut dapat digunakan sebagai titik awal untuk menentukan kebijakan kustom.

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
}

Transportasi HTTP kustom

Transportasi mengirimkan permintaan dan menampilkan respons/kesalahannya. Kebijakan pertama untuk menangani permintaan juga merupakan kebijakan terakhir yang menangani respons sebelum mengembalikan respons/kesalahan kembali ke kebijakan alur (dalam urutan terbalik). Kebijakan terakhir dalam alur memanggil transportasi.

Secara default, klien menggunakan berbagi http.Client dari pustaka standar Go.

Anda membuat transportasi berstatus atau tanpa status kustom dengan cara yang sama seperti Anda membuat kebijakan kustom. Dalam kasus berstatus, Anda menerapkan metode Do yang diwarisi dari antarmuka Transporter. Dalam kedua kasus, fungsi atau metode Do Anda kembali menerima azcore.Request, mengembalikan azCore.Response, dan melakukan tindakan dalam urutan yang sama dengan kebijakan.

Cara menghapus bidang JSON saat Anda memanggil operasi Azure

Operasi seperti JSON-MERGE-PATCH mengirim null JSON untuk menunjukkan bidang harus dihapus (bersama dengan nilainya):

{
    "delete-me": null
}

Perilaku ini bertentangan dengan penyusunan default SDK yang menentukan omitempty sebagai cara untuk menyelesaikan ambiguitas antara bidang yang akan dikecualikan dan nilai nolnya.

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

Dalam contoh sebelumnya, Name dan Count didefinisikan sebagai pointer-ke-jenis untuk membedakan antara nilai yang hilang (nil) dan nilai nol (0), yang mungkin memiliki perbedaan semantik.

Dalam operasi PATCH HTTP, bidang apa pun dengan nilai nil tidak memengaruhi nilai dalam sumber daya server. Saat memperbarui bidang Count Widget, tentukan nilai baru untuk Count, membiarkan Name sebagai nil.

Untuk memenuhi persyaratan pengiriman null JSON, fungsi NullValue digunakan:

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

Kode ini mengatur Count ke null JSON eksplisit. Saat permintaan dikirim ke server, bidang sumber daya Count dihapus.

Lihat juga