מה זה?

Analyzer עלול לזהות את אותה אנומליה כמה פעמים ברציפות (אם הערך החריג נשאר חריג לאורך כמה אירועים רצופים) — בלי הגנה, Alert Service היה שולח 10 התראות זהות למישהו, מטריד ומיותר. Redis (מיחידת NoSQL) פותר את זה: שומר “כבר התרענו על זה” עם TTL — אם אותה אנומליה מתגלה שוב תוך זמן קצר, לא שולחים התראה כפולה.

מילות מפתח שחשוב לזכור

• Deduplication (מניעת כפילות) — זיהוי שהתראה “כבר נשלחה” ומניעת שליחה חוזרת מיותרת

• Threshold Alert — התראה שנשלחת רק כשערך חוצה סף מוגדר מראש, לא על כל חריגה קטנה

• Alert Fatigue — תופעה אמיתית שבה יותר מדי התראות (כולל כפולות) גורמות למי שמקבל אותן להתעלם מכולן, כולל האמיתיות

// AlertService — consumes from Kafka, Deduplication with Redis
public class AlertConsumerService : BackgroundService
{
    private readonly IDatabase _redis;   // from the NoSQL unit

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        using var consumer = new ConsumerBuilder<Null, string>(config).Build();
        consumer.Subscribe("anomaly-detected");   // matches the Contract from Analyzer

        while (!stoppingToken.IsCancellationRequested)
        {
            var result = consumer.Consume(stoppingToken);
            var finding = JsonSerializer.Deserialize<AnomalyFinding>(result.Message.Value);

            string dedupeKey = $"alert:{finding.EventId}";
            bool alreadyAlerted = await _redis.KeyExistsAsync(dedupeKey);   // cache check, like Cache-Aside

            if (!alreadyAlerted)
            {
                await SendAlert(finding);
                await _redis.StringSetAsync(dedupeKey, "sent", TimeSpan.FromMinutes(10));   // TTL — don't send again for 10 minutes
            }
        }
    }

    private Task SendAlert(AnomalyFinding finding)
    {
        Console.WriteLine($"🚨 Alert: event {finding.EventId} exceeded the expected range!");
        return Task.CompletedTask;
    }
}

הסבר עיקרי

BackgroundService — Consumer שרץ ברציפות, לא endpoint — בניגוד ל-Collector (שיש לו endpoint שמישהו קורא אליו), Alert Service מאזין ברציפות ברקע לכל אורך חיי האפליקציה — BackgroundService הוא הדפוס הסטנדרטי ב-ASP.NET Core לקוד שרץ ברקע (לא תגובה לבקשת HTTP ספציפית).

Deduplication עם Redis הוא Cache-Aside בהיפוך תפקידים — בשיעור Redis (מיחידת NoSQL) בדקנו “האם יש במטמון?” כדי לקצר תהליך; כאן בודקים “האם כבר שלחתי?” כדי למנוע פעולה כפולה. אותו כלי בדיוק (KeyExistsAsync+TTL), שימוש הפוך: לא חוסכים חישוב, מונעים חזרתיות מיותרת.

Threshold, לא כל חריגה — Analyzer כבר “סינן” חריגות (2 סטיות תקן), אבל Alert Service יכול להוסיף שכבת סף נוספת משלו — למשל, להתריע רק אם חריגה חוזרת 3 פעמים תוך דקה, לא על חריגה בודדת. זה מונע Alert Fatigue — יותר מדי התראות “אמיתיות אך לא-קריטיות” שגורמות למי שמקבל אותן להתעלם מהכל, כולל האמיתי-חשוב.

יתרונות

Redis Deduplication מונע הצפת התראות זהות; BackgroundService נותן דפוס נקי לצריכה רציפה ברקע; שכבת Threshold נוספת מפחיתה Alert Fatigue.

חסרונות

TTL קבוע מדי (10 דקות בדוגמה) עלול להחמיץ הידרדרות אמיתית שממשיכה מעבר לחלון הזה; אם Redis לא זמין, Deduplication נכשל בשקט (או חוסם התראות לגמרי, תלוי במימוש) — נדרש טיפול שגיאות מפורש.

נקודות חשובות

• Deduplication מונע התראות כפולות על אותו אירוע תוך זמן קצר, עם Redis+TTL

• BackgroundService הוא הדפוס הסטנדרטי לצריכת Kafka רציפה ב-ASP.NET Core

• Alert Fatigue הוא סיכון אמיתי — יותר מדי התראות (גם אמיתיות) פוגעות באפקטיביות שלהן

• זהו אותו מנגנון Cache-Aside מיחידת Redis, בשימוש הפוך (מניעת חזרה, לא חיסכון חישוב)

טעויות נפוצות

• לשלוח התראה על כל הודעת אנומליה בלי Deduplication — הצפה מהירה של אותה בעיה שוב ושוב

• לבחור TTL קצר/ארוך מדי בלי לחשוב על טבע הבעיה שמנטרים

• לא לטפל בכישלון Redis (חיבור נכשל) — עלול לחסום כל התראה עתידית או להציף בלי הגנה, תלוי בכיוון הכישלון

סיכום

Alert Service צורך ממצאי אנומליה מ-anomaly-detected (תואם ל-Contract מ-Analyzer) דרך BackgroundService, ומשתמש ב-Redis Deduplication (KeyExistsAsync+TTL) כדי למנוע התראות כפולות על אותה בעיה תוך זמן קצר — אותו מנגנון Cache-Aside מיחידת Redis, בכיוון הפוך. שכבת Threshold נוספת יכולה למנוע Alert Fatigue — יותר מדי התראות שגורמות להתעלמות מהאמיתיות.

דוקומנטציה רשמית

Microsoft Learn — BackgroundService


תרגילים

תרגיל 1 — Deduplication בסיסי

המשימה: כתבו פונקציה bool ShouldAlert(string key) שבודקת Redis, ומחזירה true פעם ראשונה בלבד לכל key תוך TTL של דקה.

בדיקה: קריאה ראשונה מחזירה true; קריאה שנייה תוך פחות מדקה על אותו key מחזירה false; אחרי דקה, true שוב.

תרגיל 2 — BackgroundService מינימלי

המשימה: כתבו BackgroundService שמדפיס “בדיקה…” כל 5 שניות (בלי Kafka עדיין), והריצו אותו כחלק מ-ASP.NET Core app.

בדיקה: ההודעה מודפסת ברציפות ברקע, גם בלי בקשת HTTP נכנסת כלשהי.


פרויקט מסכם

המשימה: ממשו את Alert Service המלא לפי ה-Contract שהצוות כתב.

דרישות:

  1. BackgroundService שצורך מ-anomaly-detected
  2. Deduplication עם Redis, TTL סביר (5-10 דקות)
  3. הדפסת/רישום התראה ברורה עם פרטי האירוע (לא רק “יש בעיה”)

בדיקה: שליחת אותה אנומליה כמה פעמים ברצף (דרך Collector+Analyzer) מייצרת התראה אחת בלבד; אחרי TTL, אותה אנומליה בדיוק כן מייצרת התראה נוספת.

מה בפרק הבא

בפרק הבא — Dashboard Service: השירות הרביעי והאחרון — מציג תמונת מצב מצטברת מכל שאר השירותים, בפייתון.