Editor PHP Strawberry mengalami ralat biasa apabila meneroka penggunaan golang untuk membangunkan pengendali kubernetes: "Objek telah diubah suai". Ralat ini biasanya berlaku apabila berbilang goroutin mengubah suai objek yang sama pada masa yang sama, mengakibatkan ketidakkonsistenan data atau keadaan perlumbaan. Dalam artikel ini, kami akan meneroka punca dan penyelesaian ralat ini untuk membantu pembangun lebih memahami dan menangani masalah yang serupa.
"Objek telah diubah suai" ralat muncul pada pengendali k8s
import "sigs.k8s.io/controller-runtime"
Terdapat banyak perbincangan tentang kesilapan ini. Jawapan utama ialah "Masalah ini berlaku kerana saya mempunyai versi lama objek apabila saya cuba mengemas kini." Tetapi saya juga mempunyai beberapa soalan. Dalam operator saya, untuk beberapa senario, saya perlu mengemas kini anotasi pod 2 kali semasa satu panggilan "koordinat". Sudah tentu, saya sering mendapat ralat "objek telah diubah suai".
Soalan: Saya ingin tahu di mana 'r.Get()' dan 'r.Update()' mendapatkan/kemas kini objek? Daripada cache tempatan, atau pelayan API?
1: Saya rasa 'r.Get()' sedang mendapatkan objek daripada 'cache' dan 'r.Update()' sedang mengemas kini objek kepada cache, bukan? Jika ya, mengapa saya mendapat ralat ini? Jika objek pod berubah atas sebab selain daripada operator, adakah saya tidak akan dapat mengemas kini objek pod saya semasa "rekonsiliasi" semasa? (Memandangkan objek cache adalah setempat, ia sudah tidak segerak dengan pelayan API.) Mengapa kadang-kadang "cuba semula" untuk mendapatkan objek terkini?
import "sigs.k8s.io/controller-runtime" var pod corev1.Pod if err := r.Get(ctx, req.NamespacedName, &pod); err != nil { if !apierrors.IsNotFound(err) { log.Error(err, "unable to get pod") return ctrl.Result{}, err } } if err := r.Update(ctx, &pod); err != nil { log.Error(err, "unable to update chaosctl status") return ctrl.Result{}, err }
2: Jika 'r.Get()' adalah untuk mendapatkan objek daripada pelayan API dan 'r.Update()' turut mengemas kini pelayan API. Mengapa saya perlu mencuba semula mengemas kini objek?
Apabila anda menggunakan r.Get() dan r.Update() dalam pengawal Kubernetes, interaksi dengan pelayan API melibatkan kedua-dua cache setempat dan pelayan API itu sendiri.
r.Get()
:
r.Get() mendapatkan semula objek daripada cache setempat jika ia wujud jika tidak, ia mendapatkannya daripada pelayan API. Jika objek wujud dalam cache tempatan, ia dikembalikan serta-merta. Jika tidak, minta pelayan API untuk mendapatkan objek, dan simpan objek yang diperoleh dalam cache tempatan untuk kegunaan seterusnya. r.Kemas kini():
r.Update()
Fungsi mengemas kini objek dalam cache tempatan dan pelayan API.
Operasi kemas kini ke pelayan API mungkin gagal dengan ralat "konflik" jika objek telah diubah suai dalam cache setempat sejak ia diambil semula. Ini berlaku apabila versi objek dalam cache tidak sepadan dengan versi pada pelayan API, menunjukkan bahawa orang lain mengubah suai objek itu dalam masa yang sama.
Ada strategi untuk menanganinya -
乐观并发控制(OCC):
- Dikemas kini agar sepadan dengan versi sebelumnya. retry
-retryErr := retry.RetryOnConflict(retry.DefaultRetry, func() error { return r.Update(ctx, pod) }) if retryErr != nil { return retryErr }
Atas ialah kandungan terperinci ralat golang 'objek telah diubah suai' pada operator k8s. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!