در برنامهنویسی شبکهای و وب سرورها یه مبحثی هست با نام "graceful shutdown" یعنی kill کردن یا بستن بهینه سرویس ها با حداق تلفات در درخواست ها، میتونه در شرکت های بزرگ انقدر بهینه پیاده سازی بشه تا به هیچ عنوان درخواست یا دیتایی از دست نره.
خب حالا بیاین یه مثال ساده ازش بزنیم، برای مثال ما یه سرویسی داریم که کلی ریکوست از سمت کلاینت داره و میخوایم بنا به دلایلی چند لحظه down کنیمش اینجاس که پای "graceful shutdown" به ماجرا باز میشه، ما باید یه سیستمی پیاده کنیم تا دو مورد زیر رو تکمیل کنه و سپس process رو kill کنه.
تکمیل درخواستهای جاری: زمانی که سرور خاموش میشه، درخواستهایی که در حال پردازش هستن باید به درستی تکمیل بشن.
آزادسازی منابع: منابعی مثل پایگاه دادهها و فایلها باید به درستی بسته بشن تا از نشت یا ذخیره ناقص منابع جلوگیری بشه.
یه مثال با golang اینجا میارم، به علت اینکه کد طولانی شد میزارمش تو یه فایل تکست پایین
break;
حالا اجازه بدین به زبون خودمونی توضیح بدم که چرا استفاده از Graceful Shutdown (خاموشی تمیز) مهمه و چطوری توی این کد \پایین اجرا شده.
فرض کن یه مغازهداری. وقتی میخوای مغازهات رو ببندی، قبلش مطمئن میشی که همه مشتریها کارشون تموم شده، حساب کتاباشون رو کردن و دارن میرن بیرون. نمیای وسط کار مشتریها، کرکره رو بکشی پایین و در رو قفل کنی. اینجوری هم خودت ضرر میکنی، هم مشتریها ناراضی میشن.
حالا همینو بیاریم توی برنامهنویسی سرور:
تموم کردن کارهای در حال اجرا: وقتی سرور رو یهویی خاموش نکنی، به درخواستهایی که در حال پردازش هستن فرصت میدی کارشون رو تموم کنن. مثلا وقتی کسی داره اطلاعاتی رو از سرور میگیره، اگه وسطش سرور خاموش بشه، اون شخص به اطلاعاتش نمیرسه. با Graceful Shutdown، سرور منتظر میمونه تا این درخواستها تموم بشن.
جلوگیری از از دست رفتن دادهها: اگه سرور وسط نوشتن اطلاعات به پایگاه داده خاموش بشه، ممکنه دادهها خراب بشن یا ناقص ذخیره بشن. خاموشی تمیز باعث میشه همه کارها به درستی و تا آخر انجام بشن و بعد سرور خاموش بشه.
مدیریت بهتر منابع: وقتی سرور رو تمیز خاموش میکنی، منابعی مثل حافظه و اتصالات شبکه به درستی آزاد میشن. اینجوری وقتی دوباره سرور رو روشن میکنی، با مشکلات کمتری مواجه میشی.
حالا توی کد پایین، اینطوری این کار انجام شده:
تعریف یک کانال برای دریافت سیگنالها:
go
Copy code
stop := make(chan os.Signal, 1)
signal.Notify(stop, os.Interrupt, syscall.SIGTERM, syscall.SIGINT)
این قسمت میگه که وقتی سیگنالهای مشخصی (مثل Ctrl+C زدن توی ترمینال) دریافت شد، بره سراغ خاموشی تمیز.
گوش دادن به سیگنالها و شروع فرآیند خاموشی:
go
Copy code
<-stop
log.Println("Server is shutting down...")
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
if err := srv.Shutdown(ctx); err != nil {
log.Fatalf("Server Shutdown Failed:%+v", err)
}
اینجا وقتی سیگنال رو دریافت کرد، پیام "سرور داره خاموش میشه" رو لاگ میکنه. بعد با استفاده از یه کانتکست 30 ثانیهای سرور رو خاموش میکنه. یعنی سرور تا 30 ثانیه فرصت داره کارهای در حال اجرا رو تموم کنه و بعدش خاموش بشه.
صبر کردن تا تموم شدن همه کارها:
go
Copy code
wg.Wait()
log.Println("Server exited properly")
اینجا منتظر میمونه تا همه کارها (که با استفاده از wg.Add(1) و wg.Done() کنترل میشه) تموم بشن. وقتی همه کارها تموم شد، پیام "سرور به درستی خاموش شد" رو لاگ میکنه.
به طور خلاصه، استفاده از Graceful Shutdown کمک میکنه سرور به درستی و بدون ایجاد مشکل خاموش بشه، کارهای در حال اجرا تموم بشن و دادهها به درستی ذخیره بشن. این باعث میشه که سرور همیشه به صورت مطمئن و پایدار کار کنه و تجربه بهتری برای کاربرها فراهم کنه، و از خیلی چیزای دیگه مثل ذخیره شدن ناقص اطلاعت یا بسته نشدن procss ها که باعث میشن منابع الکی هدر بره جلوگیره کنه.
#Graceful_Shutdown
@CleverDevs - @CleverDevsGp