Get a quote

تشخيص خدمات Go في بيئة الإنتاج على AWS ECS: بدون SSH وبدون ذعر

عندما تُخفق خدمة Go على ECS Fargate في الساعة 3 فجرًا، لا يمكنك الاتصال بـ SSH. الفرق التي تشخص الإنتاج بسرعة هي تلك التي بنت طبقة المراقبة الصحيحة قبل أن تحتاجها.

عندما تُخفق خدمة Go على ECS Fargate في الساعة 3 فجرًا، لا يمكنك الاتصال بـ SSH. الحاوية مؤقتة، والمهمة ربما أُعيد تشغيلها بالفعل، والجهاز التحتي تديره AWS. الفرق التي تشخص الإنتاج بسرعة هي تلك التي بنت طبقة المراقبة الصحيحة قبل أن تحتاجها. هذا ما يبدو عليه ذلك الإعداد فعليًا لمنتجات SaaS التي ندير بنيتها في لبنان ومنطقة MENA.

لماذا يجعل ECS Fargate التشخيص التقليدي مستحيلًا

مع EC2، يمكن للمهندس القلق الاتصال بـ SSH، وتشغيل strace، وتتبع السجلات مباشرة. مع Fargate، لا يوجد جهاز تحتي تتحكم فيه. الحاوية تعمل وتختفي. هذا هو المقايضة الصحيحة للإنتاج: استرداد تلقائي، لا عبء تحديثات، لا خوادم وسيطة. لكنه يتطلب أن يكون النظام مجهزًا بالمراقبة الصحيحة قبل حدوث أي خطأ.

الطبقة الأولى: السجلات المهيكلة مع معرفات الارتباط

أول ما تحتاجه كل خدمة Go على ECS هو تسجيل مهيكل يُرسل إلى CloudWatch Logs. الـ fmt.Println لا تفيد في الإنتاج.

نستخدم zap للتسجيل المهيكل في Go:

func NewLogger(env string) (*zap.Logger, error) {
  if env == "production" {
    return zap.NewProduction()
  }
  return zap.NewDevelopment()
}

zap.NewProduction() يُخرج JSON يمكن لـ CloudWatch تحليله وفلترته.

mعرفات الارتباط هي القطعة الحاسمة. كل طلب يدخل النظام يجب أن يحصل على معرف تتبع فريد يتدفق عبر كل سطر سجل لذلك الطلب:

func TraceMiddleware(next http.Handler) http.Handler {
  return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    traceID := r.Header.Get("X-Trace-Id")
    if traceID == "" {
      traceID = uuid.New().String()
    }
    w.Header().Set("X-Trace-Id", traceID)
    ctx := context.WithValue(r.Context(), contextKeyTraceID, traceID)
    next.ServeHTTP(w, r.WithContext(ctx))
  })
}

عندما يفشل طلب، تبحث في CloudWatch Logs عن معرف التتبع وترى كل سطر سجل من كل خدمة لمست ذلك الطلب.

الطبقة الثانية: استعلامات CloudWatch Logs Insights

بمجرد وجود سجلات JSON مهيكلة في CloudWatch، تتيح لك Logs Insights الاستعلام عنها كقاعدة بيانات:

# البحث عن جميع أخطاء آخر 30 دقيقة
fields @timestamp, @message, trace_id, workspace_id
| filter level = "error"
| sort @timestamp desc
| limit 50

# ربط تتبع محدد عبر الخدمات
fields @timestamp, @logStream, @message
| filter trace_id = "5d3f2a1b-..."
| sort @timestamp asc

الطبقة الثالثة: ECS Exec للوصول المباشر للحاوية

للحالات التي لا تكفي فيها السجلات وتحتاج لفحص حالة الحاوية الحية، أضافت AWS ميزة ECS Exec. إنها بمثابة SSH داخل حاوية Fargate قيد التشغيل:

aws ecs execute-command \
  --cluster production \
  --task arn:aws:ecs:eu-west-1:123456789:task/... \
  --container api \
  --interactive \
  --command "/bin/sh"

داخل الحاوية يمكنك فحص متغيرات البيئة، التحقق من حالة نظام الملفات، تشغيل curl ضد نقاط النهاية الداخلية. هذا أداة طوارئ، ليس عكازًا لغياب المراقبة.

الطبقة الرابعة: استرداد الـ Panic مع التسجيل المهيكل

خدمات Go على ECS تحتاج استرداد صريح للـ panic:

func RecoverMiddleware(logger *zap.Logger) func(http.Handler) http.Handler {
  return func(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
      defer func() {
        if rec := recover(); rec != nil {
          buf := make([]byte, 4096)
          n := runtime.Stack(buf, false)
          log := LoggerFromContext(r.Context(), logger)
          log.Error("panic recovered",
            zap.Any("panic", rec),
            zap.String("stack", string(buf[:n])),
          )
          http.Error(w, "internal server error", http.StatusInternalServerError)
        }
      }()
      next.ServeHTTP(w, r)
    })
  }
}

هذا يضمن أنه حتى عند حدوث panic، تحصل على سطر سجل مهيكل مع تتبع المكدس ومعرف التتبع.

الطبقة الخامسة: فحوصات صحة الحاوية

فحص الصحة المفيد في Go يتحقق من الحالة الداخلية:

func (s *Server) HealthHandler(w http.ResponseWriter, r *http.Request) {
  if err := s.db.PingContext(r.Context()); err != nil {
    s.logger.Warn("health check: db ping failed", zap.Error(err))
    w.WriteHeader(http.StatusServiceUnavailable)
    return
  }
  json.NewEncoder(w).Encode(map[string]string{"status": "healthy"})
}

سير عمل التشخيص في الممارسة

عندما يحدث خطأ في الإنتاج:

  1. تحقق من Container Insights للحصول على حالات إعادة التشغيل والموارد
  2. ابحث في CloudWatch Logs عن level = "error" في النافذة الزمنية المعنية
  3. اختر معرف تتبع فاشل من تلك الأخطاء
  4. ابحث في جميع مجموعات السجلات عن ذلك المعرف لإعادة بناء تدفق الطلب الكامل
  5. إذا احتجت حالة الحاوية الحية، استخدم ECS Exec

الدروس الرئيسية

ابنِ المراقبة قبل أن تحتاجها. السجلات المهيكلة ومعرفات الارتباط واسترداد الـ panic ليست اختيارية في أي خدمة Go للإنتاج على ECS. Container Insights رخيص ويستحق التفعيل على كل cluster.

هل تحتاج مساعدة في إعداد مراقبة إنتاج حقيقية لخدمات Go الخاصة بك؟

Voxire تبني وتصون البنية التحتية السحابية لمنتجات SaaS في لبنان ومنطقة MENA. إذا كان فريقك يعمل في الإنتاج بدون رؤية كافية، يمكننا مساعدتك في بناء طبقة الرؤية التي تحتاجها فعلًا.

https://voxire.com/get-a-quote/

العودة إلى المدونة
Chat on WhatsApp