مراقبة الخدمات المصغرة باستخدام Prometheus و Grafana

Navendu Pottekkat

Navendu Pottekkat

June 8, 2023

Ecosystem

المراقبة المستمرة أمر بالغ الأهمية لجعل أنظمة الخدمات المصغرة قوية. بدون مراقبة مناسبة، يمكن أن تتعرض الخدمات المصغرة للإرهاق بسرعة، مما يؤدي إلى حدوث أخطاء وفقدان في الأداء.

من خلال المراقبة المستمرة، يمكن للمطورين اكتشاف المشكلات في خدماتهم بمجرد ظهورها واتخاذ إجراءات لمنع حدوث أضرار كبيرة. كما توفر رؤى حول كيفية أداء خدماتك، مما يسمح لك باتخاذ قرارات مستنيرة.

ستقدم هذه المقالة كيفية إعداد المراقبة على تطبيق الخدمات المصغرة الخاص بك باستخدام أداتين شائعتين في هذا المجال، وهما Prometheus وGrafana.

يتوفر الكود المصدري وملف Docker Compose لهذا البرنامج التعليمي في pottekkat/monitoring-101.

أساسيات Prometheus

Prometheus هو أداة مراقبة وإنذار مفتوحة المصدر. يقوم "بسحب" المقاييس (القياسات) من الخدمات المصغرة عن طريق إرسال طلبات HTTP ويخزن النتائج في قاعدة بيانات تسلسل زمني.

يمكنك توجيه خدماتك باستخدام مكتبات العميل التي توفرها Prometheus. سيسمح لك ذلك بإنشاء وجمع مقاييس مخصصة من خدماتك.

كما أن Prometheus يحتوي على مصدّرات تتيح لك سحب المقاييس التي ليست بتنسيق Prometheus. يعمل المصدّر كوسيط ويحول البيانات المصدرة إلى تنسيق يمكن لـ Prometheus قراءته.

1-prometheus-architecture.png

توفر Prometheus لغة استعلام قوية، PromQL، للعمل مع هذه البيانات المجمعة. يمكنك استخدام PromQL لإنشاء استعلامات معقدة لتصفية البيانات وتجميعها وتحويلها إلى التنسيق المطلوب.

بالإضافة إلى سحب المقاييس، يمكن لـ Prometheus أيضًا تشغيل إنذارات عند تجاوز الحدود المحددة. آلية الإنذار قابلة للتخصيص بشكل كبير ويمكنها إرسال إشعارات إلى أماكن مثل Slack أو البريد الإلكتروني.

يحتوي Prometheus على واجهة مستخدم رسومية تتيح لك تصور المقاييس المجمعة بسهولة. كما يتكامل مع أدوات التصور المتقدمة الأخرى مثل Grafana.

prometheus-dashboard.png

أنواع المقاييس

توفر Prometheus أربعة أنواع أساسية من المقاييس:

  1. العداد (Counter): يمثل عدادًا واحدًا يتزايد بشكل رتيب. يمكن أن تزيد قيمته أو تعود إلى الصفر عند إعادة التشغيل. يمكنك استخدامه لتمثيل مقاييس مثل عدد الطلبات التي تمت خدمتها.
  2. المقياس (Gauge): يمثل قيمة رقمية يمكن أن تزيد أو تنخفض. يمكنك استخدامه لتمثيل قيم مثل استخدام الذاكرة أو عدد الطلبات في الثانية.
  3. الهيستوجرام (Histogram): يقوم بأخذ عينات من البيانات وتوزيعها في سلال قابلة للتكوين. استخدمه لتمثيل قيم مثل مدة الطلبات أو أحجام الاستجابات.
  4. الملخص (Summary): يشبه الهيستوجرام، حيث يقوم أيضًا بحساب قيم قابلة للتكوين على نافذة زمنية منزلقة.

يمكنك معرفة المزيد عن هذه الأنواع من المقاييس وكيفية استخدامها من الوثائق الرسمية.

تطبيق العينة

يتكون تطبيق العينة الخاص بنا من بوابة API، تطبيق Go، وتطبيق Python.

2-sample-app-flowchart.png

سيقوم التطبيق بإرجاع "مرحبًا <اسم>!" باللغة التي تختارها مع الاسم الذي تقدمه. سيكون Apache APISIX هو بوابة API التي توجه حركة المرور إلى خدماتك.

يظهر الرسم البياني التالي كيفية عمل النظام.

3-sample-app-sequence.png

  1. يرسل المستخدم طلب GET إلى APISIX، وهي نقطة الدخول للتطبيق.
  2. يقوم APISIX بتوجيه الطلب إلى خدمة Go.
  3. تقوم خدمة Go بإرسال طلب GET إلى خدمة Python للحصول على "مرحبًا" باللغة المحددة.
  4. تقوم خدمة Python بالرد بالترجمة المطلوبة لـ "مرحبًا".
  5. تقوم خدمة Go بإنشاء الاستجابة المطلوبة باستخدام الاسم المقدم في الاستعلام وترسلها إلى APISIX.
  6. يقوم APISIX بتوجيه الاستجابة مرة أخرى إلى المستخدم.

تكوين Prometheus لجمع المقاييس

سنقوم بتوجيه وتصدير المقاييس من جميع الخدمات في تطبيقنا وجمعها في Prometheus. سنبدأ ببوابة API الخاصة بنا، Apache APISIX.

تصدير المقاييس من APISIX

Apache APISIX هو بوابة API مفتوحة المصدر ومصممة للعمل في البيئات السحابية.

لا تحتاج إلى معرفة APISIX لمتابعة هذا البرنامج التعليمي، ويمكنك استخدام ملف Docker Compose المقدم لإعداد كل شيء. لمعرفة المزيد عن APISIX، قم بزيارة api7.ai/apisix.

يوفر APISIX إضافة prometheus التي تصدر المقاييس بسهولة بتنسيق Prometheus. يمكنك تكوين الإضافة في ملف تكوين APISIX الخاص بك:

apisix:
  enable_admin: false # تشغيل APISIX في الوضع المستقل
  config_center: yaml # استخدام ملف YAML للتكوين بدلاً من تخزينه في etcd
plugin_attr:
  prometheus:
    export_uri: /prometheus/metrics # تمكين إضافة prometheus وتصدير المقاييس إلى هذا الرابط
    enable_export_server: false # تصدير المقاييس في منفذ data-plane الافتراضي

يمكننا الآن تمكين الإضافة على كل Route عن طريق جعلها قاعدة عامة:

routes:
  # توجيه الطلبات إلى /hello/* إلى go-app
  - uri: /hello/*
    upstream:
      type: roundrobin
      nodes:
        "go-app:8080": 1
    plugins:
      # إزالة البادئة "/hello" قبل توجيه الطلب إلى go-app
      proxy-rewrite:
        regex_uri:
          - "/hello/(.*)"
          - "/$1"
  # تصدير مقاييس Prometheus إلى الرابط المحدد
  - uri: /prometheus/metrics
    plugins:
      public-api:
# تمكين إضافة Prometheus بشكل عام على جميع Routes
global_rules:
  - id: 1
    plugins:
      prometheus:
        prefer_name: true
#END

سيؤدي هذا إلى تصدير المقاييس إلى نقطة النهاية /prometheus/metrics في Apache APISIX.

يمكنك معرفة المزيد عن المقاييس المتاحة من الوثائق.

توجيه وتصدير المقاييس من خدمة Go

يحتوي Prometheus على مكتبة عميل رسمية لـ Go لتوجيه تطبيقات Go.

بشكل افتراضي، سيقوم Prometheus بعرض المقاييس الافتراضية لـ Go. يمكنك أيضًا إنشاء مقاييس خاصة بتطبيقك.

في خدمتنا، سنعرض المقاييس الافتراضية وننشئ مقياس عداد خاص بنا لتتبع عدد الطلبات:

package main

import (
  "encoding/json"
  "fmt"
  "io/ioutil"
  "log"
  "net/http"
  "os"

  // حزم Prometheus
  "github.com/prometheus/client_golang/prometheus"
  "github.com/prometheus/client_golang/prometheus/promauto"
  "github.com/prometheus/client_golang/prometheus/promhttp"
)

// Response يخزن الرسالة التي تم الحصول عليها من python-app
type Response struct {
  Message string `json:"message"`
}

// اللغة والاسم الافتراضيين
var (
  lang = "en"
  name = "John"
)

// إنشاء مقياس عداد مخصص جديد لـ Prometheus
var pingCounter = promauto.NewCounter(
  prometheus.CounterOpts{
    Name: "go_app_request_count",
    Help: "عدد الطلبات التي تمت معالجتها بواسطة go-app",
  },
)

// HelloHandler يعالج الطلبات إلى go-app
func HelloHandler(w http.ResponseWriter, r *http.Request) {
  lang = r.URL.String()
  name = r.URL.Query()["name"][0]
  
  fmt.Println("طلب لـ", lang, "مع الاسم", name)
  pingCounter.Inc()
  
  pUrl := os.Getenv("PYTHON_APP_URL")
  if len(pUrl) == 0 {
    pUrl = "localhost"
  }

  // استدعاء python-app للحصول على الترجمة
  resp, err := http.Get("http://" + pUrl + ":8000" + lang)
  if err != nil {
    log.Fatalln(err)
  }

  body, err := ioutil.ReadAll(resp.Body)
  if err != nil {
    log.Fatalln(err)
  }

  resp.Body.Close()

  var m Response
  json.Unmarshal(body, &m)

  // إرسال الرد مع "مرحبًا اسم!" باللغة المحددة
  fmt.Fprintf(w, "%s %s!", m.Message, name)
}

func main() {
  // عرض مقاييس Prometheus
  http.Handle("/metrics", promhttp.Handler())
  http.HandleFunc("/", HelloHandler)
  
  http.ListenAndServe(":8080", nil)
}

سيؤدي هذا إلى عرض المقاييس إلى نقطة النهاية /metrics. يمكنك معرفة المزيد عن مكتبة عميل Go من مستودع GitHub الخاص بها.

توجيه وتصدير المقاييس من خدمة Python

يحتوي Prometheus أيضًا على مكتبة عميل رسمية لـ Python. هناك أيضًا مكتبات تابعة لجهات خارجية مصممة لتلائم حالات استخدام محددة.

تستخدم خدمتنا FastAPI، وسنستخدم مكتبة prometheus_fastapi_instrumentator لتوجيهها:

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

from prometheus_fastapi_instrumentator import Instrumentator

app = FastAPI()

hello = {"en": "Hello", "fr": "Bonjour", "es": "Hola", "ml": "ഹലോ"}

# عرض المقاييس الافتراضية لـ Python إلى نقطة النهاية /metrics
Instrumentator().instrument(app).expose(app)

@app.get("/{lang}")
async def get_hello(lang):
    return {"message": hello[lang]}

يمكنك معرفة المزيد عن إنشاء مقاييس مخصصة من الوثائق.

تكوين Prometheus

يمكننا الآن سحب وجمع هذه المقاييس في Prometheus.

يمكنك تكوين Prometheus لجمع المقاييس من كل خدمة. بشكل افتراضي، يتحقق Prometheus من المقاييس في المسار /metrics:

global:
  scrape_interval: 15s
  evaluation_interval: 15s

scrape_configs:
  - job_name: "prometheus"
    static_configs:
      - targets: ["localhost:9090"]
  
  - job_name: "go-app"
    static_configs:
      - targets: ["go-app:8080"]

  - job_name: "python-app"
    static_configs:
      - targets: ["python-app:8000"]

  - job_name: "apisix"
    static_configs:
      - targets: ["apisix:9080"]
    metrics_path: "/prometheus/metrics"

هذا كل شيء! الآن، إذا قمت بفتح لوحة تحكم Prometheus (الافتراضي على المنفذ 9090) والنقر على "Status" من شريط التنقل و"Targets"، ستتمكن من رؤية حالة المقاييس التي يتم سحبها من خدماتك.

prometheus-target-status.png

استعلام وتصور المقاييس في Prometheus

الآن، يمكنك استخدام لوحة تحكم Prometheus لتشغيل الاستعلامات والتعابير المعقدة.

prometheus-query.png

يمكنك معرفة المزيد عن استعلام Prometheus في الوثائق الرسمية.

استخدام Grafana لاستعلام Prometheus

Grafana هي منصة تصور بيانات مفتوحة المصدر تعمل مع Prometheus لتوفير أداة شاملة لجمع المقاييس واستعلامها وتصورها.

Prometheus جيد في جمع المقاييس والاستعلام ولكن يفتقر إلى توفير أدوات لإنشاء تصورات ذات معنى. يتغلب Grafana على هذا القصور عن طريق تحويل المقاييس المجمعة إلى تصورات.

Grafana متوافق أيضًا مع العديد من مصادر البيانات الأخرى غير Prometheus.

بمجرد نشر Grafana، يمكنك فتح واجهة المستخدم عبر الويب (الافتراضي على المنفذ 3000).

أولاً، يجب عليك إضافة Prometheus كمصدر بيانات. للقيام بذلك، انتقل إلى `/datasources أو "Configuration" و"Data sources." انقر على "Add data source" واختر Prometheus. حدد مكان نشر Prometheus، واحفظ واختبر الاتصال.

grafana-add-prometheus.png

استخدام لوحات تحكم Grafana المبنية مسبقًا

يستضيف Grafana مستودع لوحات تحكم عامة يحتوي على لوحات تحكم Grafana مبنية مسبقًا. يمكنك استخدامها في نسختك من Grafana لتصور المقاييس ذات الصلة بسرعة.

سنستخدم لوحة تحكم Go Processes التي ستقوم بمعالجة وتصور حالة العملية التي تنشرها مكتبة عميل Prometheus لـ Go.

لاستيراد هذا القالب، أولاً، انسخ معرفه (6671) من مستودع لوحات التحكم. في واجهة مستخدم Grafana الخاصة بك، انتقل إلى "Dashboards" واختر "Import." الصق المعرف الذي نسخته وانقر على "Load."

grafana-dashboard.png

يمكنك أيضًا استكشاف لوحات تحكم أخرى مبنية مسبقًا أو إنشاء لوحات تحكم خاصة بك. راجع الوثائق لمعرفة المزيد عن هذا.

ما التالي؟

هذا كل شيء لهذا البرنامج التعليمي!

كانت هذه المقالة مجرد مقدمة عن كيفية إعداد المراقبة على خدماتك، وأشجعك على معرفة المزيد عن Prometheus وGrafana من المصادر المذكورة أدناه:

يتوفر الكود الكامل وملف Docker Compose لهذا البرنامج التعليمي في pottekkat/monitoring-101.

Tags: