GoDasturchi
Production Graceful Shutdown

Production Graceful Shutdown

Production darajasidagi muloyim to'xtash

Oldingi darsda bitta worker uchun graceful shutdown ko'rgan edik. Haqiqiy serverda esa bu jarayon biroz kengroq: server "to'xtash signali"ni kutadi, signal kelganda yangi so'rovlarni qabul qilishni to'xtatadi, so'ng hozirgi faol so'rovlar tugashini kutadi, va faqat shundan keyin dastur butunlay yopiladi.

example.go
package main

import (
	"context"
	"fmt"
	"time"
)

type Server struct{}

func (s *Server) Shutdown(ctx context.Context) error {
	done := make(chan struct{})
	go func() {
		// haqiqiy loyihada: faol so'rovlar tugashini kutish
		time.Sleep(5 * time.Millisecond)
		close(done)
	}()

	select {
	case <-done:
		return nil
	case <-ctx.Done():
		return ctx.Err()
	}
}

func main() {
	srv := &Server{}

	stop := make(chan struct{})
	go func() {
		time.Sleep(1 * time.Millisecond)
		close(stop) // haqiqiy loyihada: bu OS signalidan (Ctrl+C) kelardi
	}()

	<-stop
	fmt.Println("to'xtatish signali keldi")

	ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond)
	defer cancel()

	if err := srv.Shutdown(ctx); err != nil {
		fmt.Println("xato:", err)
		return
	}
	fmt.Println("server to'xtatildi")
}

Haqiqiy loyihada stop kanali odatda os/signal paketi orqali operatsion tizimning "Ctrl+C" (SIGINT) yoki "deploy tizimidan to'xtatish" (SIGTERM) signalidan keladi — biz buni bu yerda oddiy time.Sleep bilan simulyatsiya qildik, chunki bizning muhitimizda haqiqiy OS signali yubora olmaymiz. Server.Shutdown(ctx) — bu naqsh aynan Go'ning standart kutubxonasidagi http.Server.Shutdown metodining o'zi ishlatadigan imzo: u ham contextni oladi, chunki "qancha vaqt kutish mumkinligi" chegarasi bo'lishi kerak.

Bu yerdagi select — "Graceful Shutdown Basics" darsidagi bilan bir xil g'oya, lekin teskari nuqtai nazardan: endi biz "barcha ish tugashini" (done) kutayapmiz, agar bu juda uzoq davom etsa (ctx muddati tugasa), majburan to'xtatib, xato qaytaramiz — "cheksiz kutib qolmang" degan xavfsizlik chegarasi.

>_ Exercise

Shutdown vaqti chegaradan oshib ketgan holatni sinab ko'ring.

  • Server.Shutdown ichidagi time.Sleep'ni 200 millisekundga o'zgartiring (juda uzoq)
  • context timeout'ni 50 millisekundga o'zgartiring
  • natijada Shutdown xato (context deadline exceeded) qaytarishi kerak

Stuck? Reveal a hint to help you.

Hints (0/3)

Key Takeaway

Key Takeaway:

Production graceful shutdown har doim vaqt chegarasiga (context timeout) ega bo'lishi kerak — aks holda "muloyim kutish" abadiy davom etib, dasturni umuman to'xtatib bo'lmay qolishi mumkin.

NEXT UP

Factory Pattern

OUTPUT

$ go run main.go
Kodingizni ishga tushiring

Production Graceful Shutdown

Production darajasidagi muloyim to'xtash

Oldingi darsda bitta worker uchun graceful shutdown ko'rgan edik. Haqiqiy serverda esa bu jarayon biroz kengroq: server "to'xtash signali"ni kutadi, signal kelganda yangi so'rovlarni qabul qilishni to'xtatadi, so'ng hozirgi faol so'rovlar tugashini kutadi, va faqat shundan keyin dastur butunlay yopiladi.

example.go
package main

import (
	"context"
	"fmt"
	"time"
)

type Server struct{}

func (s *Server) Shutdown(ctx context.Context) error {
	done := make(chan struct{})
	go func() {
		// haqiqiy loyihada: faol so'rovlar tugashini kutish
		time.Sleep(5 * time.Millisecond)
		close(done)
	}()

	select {
	case <-done:
		return nil
	case <-ctx.Done():
		return ctx.Err()
	}
}

func main() {
	srv := &Server{}

	stop := make(chan struct{})
	go func() {
		time.Sleep(1 * time.Millisecond)
		close(stop) // haqiqiy loyihada: bu OS signalidan (Ctrl+C) kelardi
	}()

	<-stop
	fmt.Println("to'xtatish signali keldi")

	ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond)
	defer cancel()

	if err := srv.Shutdown(ctx); err != nil {
		fmt.Println("xato:", err)
		return
	}
	fmt.Println("server to'xtatildi")
}

Haqiqiy loyihada stop kanali odatda os/signal paketi orqali operatsion tizimning "Ctrl+C" (SIGINT) yoki "deploy tizimidan to'xtatish" (SIGTERM) signalidan keladi — biz buni bu yerda oddiy time.Sleep bilan simulyatsiya qildik, chunki bizning muhitimizda haqiqiy OS signali yubora olmaymiz. Server.Shutdown(ctx) — bu naqsh aynan Go'ning standart kutubxonasidagi http.Server.Shutdown metodining o'zi ishlatadigan imzo: u ham contextni oladi, chunki "qancha vaqt kutish mumkinligi" chegarasi bo'lishi kerak.

Bu yerdagi select — "Graceful Shutdown Basics" darsidagi bilan bir xil g'oya, lekin teskari nuqtai nazardan: endi biz "barcha ish tugashini" (done) kutayapmiz, agar bu juda uzoq davom etsa (ctx muddati tugasa), majburan to'xtatib, xato qaytaramiz — "cheksiz kutib qolmang" degan xavfsizlik chegarasi.

>_ Exercise

Shutdown vaqti chegaradan oshib ketgan holatni sinab ko'ring.

  • Server.Shutdown ichidagi time.Sleep'ni 200 millisekundga o'zgartiring (juda uzoq)
  • context timeout'ni 50 millisekundga o'zgartiring
  • natijada Shutdown xato (context deadline exceeded) qaytarishi kerak

Stuck? Reveal a hint to help you.

Hints (0/3)

Key Takeaway

Key Takeaway:

Production graceful shutdown har doim vaqt chegarasiga (context timeout) ega bo'lishi kerak — aks holda "muloyim kutish" abadiy davom etib, dasturni umuman to'xtatib bo'lmay qolishi mumkin.

NEXT UP

Factory Pattern