Spring Cloud Sleuth ביישום מונולית

1. סקירה כללית

במאמר זה אנו מציגים אביב ענן סלאוט - כלי רב עוצמה לשיפור יומני הרישום בכל יישום, אך במיוחד במערכת הבנויה ממספר שירותים.

ובשביל כתיבה זו אנו מתמקדים בשימוש ב- Sleuth ביישום מונוליט, לא במיקרו-שירותים.

לכולנו הייתה חוויה אומללה בניסיון לאבחן בעיה במשימה מתוזמנת, פעולה מרובת שרשורים או בקשת רשת מורכבת. לעתים קרובות, גם כשיש רישום, קשה לדעת אילו פעולות יש לתאם יחד כדי ליצור בקשה אחת.

זה יכול לעשות אבחון פעולה מורכבת קשה מאוד או אפילו בלתי אפשרי. לעיתים קרובות נוצר פתרונות כמו העברת מזהה ייחודי לכל שיטה בבקשה לזהות את היומנים.

נכנס נכנס בַּלָשׁ. ספרייה זו מאפשרת לזהות יומנים הנוגעים לעבודה, שרשור או בקשה ספציפיים. Sleuth משתלב ללא מאמץ עם מסגרות כניסה כמו לוגבק ו SLF4J כדי להוסיף מזהים ייחודיים המסייעים במעקב ובאבחון בעיות באמצעות יומנים.

בואו נסתכל על איך זה עובד.

2. התקנה

נתחיל ביצירת מגף אביב פרויקט אינטרנט ב- IDE המועדף עלינו והוספת תלות זו ל pom.xml קוֹבֶץ:

 org.springframework.cloud spring-cloud-starter-sleuth 

היישום שלנו פועל עם מגף אביב ו- pom parent מספק גרסאות לכל ערך. הגרסה האחרונה של תלות זו נמצאת כאן: אביב-ענן-מתנע-סליוט. כדי לראות את כל ה- POM, בדוק את הפרויקט ב- Github.

בנוסף, בואו להוסיף שם יישום להוראות בַּלָשׁ כדי לזהות את יומני היישום הזה.

בשלנו application.properties קובץ הוסף שורה זו:

spring.application.name = הדרכה של Baeldung Sleuth

3. תצורות Sleuth

בַּלָשׁ מסוגל לשפר יומנים במצבים רבים. החל מגרסת 2.0.0, Spring Cloud Sleuth משתמש ב- Brave כספריית המעקב שמוסיפה מזהים ייחודיים לכל בקשת אינטרנט שנכנסת ליישום שלנו. יתר על כן, צוות האביב הוסיף תמיכה בשיתוף מזהים אלה על פני גבולות השרשור.

ניתן לחשוב על עקבות כמו בקשה אחת או עבודה שמופעלת ביישום. לכל השלבים השונים בבקשה זו, אפילו מעבר לגבולות היישומים וההשחלה, יהיה אותו traceId.

לעומת זאת, ניתן לחשוב על טווחים כמקטעים בעבודה או בבקשה. עקבות בודדים יכולים להיות מורכבים ממספר תוחלות המתאימות לשלב או לקטע ספציפי של הבקשה. באמצעות מזהי מעקב וטווח נוכל לאתר בדיוק מתי והיכן היישום שלנו תוך שהוא מעבד בקשה. להקל על קריאת יומנינו.

בדוגמאות שלנו נחקור יכולות אלה ביישום יחיד.

3.1. בקשת אינטרנט פשוטה

ראשית, בואו ניצור מחלקת בקר שתהיה נקודת כניסה לעבודה:

@RestController מחלקה ציבורית SleuthController {@GetMapping ("/") פומבי מחרוזת helloSleuth () {logger.info ("Hello Sleuth"); להחזיר "הצלחה"; }}

בוא נפעיל את היישום שלנו ונעבור אל “// localhost: 8080”. צפה ביומני הפלט שנראים כמו:

2017-01-10 22: 36: 38.254 INFO [הדרכה של Baeldung Sleuth, 4e30f7340b3fb631,4e30f7340b3fb631, false] 12516 --- [nio-8080-exec-1] c.b.spring.session.SleuthController: Hello Sleuth

זה נראה כמו יומן רגיל, למעט החלק בהתחלה בין הסוגריים. זה המידע המרכזי ש אביב סלאוט הוסיף. נתונים אלה עוקבים אחר הפורמט של:

[שם היישום, traceId, spanId, export]

  • שם אפליקציה - זה השם שקבענו בקובץ המאפיינים וניתן להשתמש בו כדי לצבור יומנים ממספר מופעים של אותה יישום.
  • TraceId - זהו מזהה המוקצה לבקשה, עבודה או פעולה אחת. משהו כמו כל בקשת אינטרנט ייחודית שיזם משתמש ייחודי לו traceId.
  • SpanId - עוקב אחר יחידת עבודה. חשוב על בקשה המורכבת ממספר שלבים. לכל שלב יכול להיות משלו spanId ולהיות במעקב בנפרד. כברירת מחדל, כל זרימת יישום תתחיל באותה TraceId ו- SpanId.
  • יְצוּא - מאפיין זה הוא בוליאני המציין אם יומן זה יוצא לאגרגטור כמו או לא זיפקין. זיפקין הוא מעבר לתחום של מאמר זה אך ממלא תפקיד חשוב בניתוח יומנים שנוצרו על ידי בַּלָשׁ.

נכון לעכשיו, יהיה לך מושג כלשהו על כוחה של ספרייה זו. בואו נסתכל על דוגמה אחרת כדי להדגים עוד יותר עד כמה ספרייה זו היא חלק מהרישומים.

3.2. בקשת אינטרנט פשוטה עם גישה לשירות

נתחיל ביצירת שירות בשיטה אחת:

@Service מחלקה ציבורית SleuthService {public void doSomeWorkSameSpan () {Thread.sleep (1000L); logger.info ("עושה קצת עבודה"); }}

עכשיו בואו נזריק את השירות שלנו לבקר שלנו ונוסיף שיטת מיפוי בקשות שניגשת אליו:

@ SleuthService פרטית אוטומטית sleuthService; @GetMapping ("/ same-span") ציבורי מחרוזת helloSleuthSameSpan () זורק את InterruptedException {logger.info ("אותו טווח"); sleuthService.doSomeWorkSameSpan (); להחזיר "הצלחה"; }

לבסוף, הפעל מחדש את היישום ונווט אל "// localhost: 8080 / אותו טווח". צפה לפלט יומן שנראה כמו:

2017-01-10 22: 51: 47.664 מידע [הדרכה של Baeldung Sleuth, b77a5ea79036d5b9, b77a5ea79036d5b9, false] 12516 --- [nio-8080-exec-3] cbspring.session.SleuthController: אותו טווח 22/01/2017 : 51: 48.664 מידע [הדרכה של Baeldung Sleuth, b77a5ea79036d5b9, b77a5ea79036d5b9, false] 12516 --- [nio-8080-exec-3] c.baeldung.spring.session.SleuthService: עושה קצת עבודה

שים לב שמזהי המעקב והטווח זהים בין שני היומנים למרות שההודעות מקורן בשתי מחלקות שונות. זה עושה את זה טריוויאלי לזהות כל יומן במהלך בקשה על ידי חיפוש ה- traceId של בקשה זו.

זו התנהגות ברירת המחדל, בקשה אחת מקבלת יחיד traceId ו spanId. אך אנו יכולים להוסיף טווחים באופן ידני כראות עינינו. בואו נסתכל על דוגמה המשתמשת בתכונה זו.

3.3. הוספת טווח ידני

כדי להתחיל, בואו נוסיף בקר חדש:

@GetMapping ("/ new-span") ציבורי מחרוזת helloSleuthNewSpan () {logger.info ("טווח חדש"); sleuthService.doSomeWorkNewSpan (); להחזיר "הצלחה"; }

ועכשיו בואו נוסיף את השיטה החדשה בשירות שלנו:

@ Tracer פרטי פרטי מאושר; // ... חלל ציבורי doSomeWorkNewSpan () זורק את InterruptedException {logger.info ("אני נמצא בטווח המקורי"); טווח newSpan = tracer.nextSpan (). שם ("newSpan"). התחל (); נסה (SpanInScope ws = tracer.withSpanInScope (newSpan.start ())) {Thread.sleep (1000L); logger.info ("אני בטווח החדש עושה עבודה מגניבה שצריכה טווח משלה"); } סוף סוף {newSpan.finish (); } logger.info ("אני נמצא בטווח המקורי"); }

שימו לב שהוספנו גם אובייקט חדש, נוֹתֵב. ה נוֹתֵב מופע נוצר על ידי אביב סלאוט במהלך ההפעלה והוא זמין לכיתה שלנו באמצעות הזרקת תלות.

יש להתחיל ולעצור עקבות באופן ידני. כדי להשיג זאת, קוד שרץ בתוכנה שנוצרה באופן ידני לְהַקִיף ממוקם בתוך א נסה סוף סוף לחסום כדי להבטיח את לְהַקִיף סגור ללא קשר להצלחת המבצע. כמו כן, שים לב שיש להניח טווח חדש בהיקף.

הפעל מחדש את היישום ונווט אל "// localhost: 8080 / new-span". צפה לפלט היומן שנראה כמו:

2017-01-11 21: 07: 54.924 מידע [הדרכה של Baeldung Sleuth, 9cdebbffe8bbade, 9cdebbffe8bbade, false] 12516 --- [nio-8080-exec-6] cbspring.session.SleuthController: Span חדש 21/01/2017 : 07: 54.924 מידע [הדרכה של Baeldung Sleuth, 9cdebbffe8bbbade, 9cdebbffe8bbade, false] 12516 --- [nio-8080-exec-6] c.baeldung.spring.session.SleuthService: אני נמצא בטווח המקורי 2017-01- 11 21: 07: 55.924 מידע [הדרכה של Baeldung Sleuth, 9cdebbffe8bbbade, 1e706f252a0ee9c2, false] 12516 --- [nio-8080-exec-6] c.baeldung.spring.session. SleuthService: אני במתחם החדש עושה קצת עבודה מגניבה הזקוקה לטווח משלה 2017-01-11 21: 07: 55.924 מידע [הדרכה של Baeldung Sleuth, 9cdebbffe8bbbade, 9cdebbffe8bbade, false] 12516 --- [nio-8080-exec-6] c.baeldung.spring.session. SleuthService: אני נמצא בטווח המקורי

אנו יכולים לראות כי היומן השלישי חולק את ה- traceId עם האחרים, אבל יש לו ייחודי spanId. בעזרת זה ניתן לאתר חלקים שונים בבקשה אחת למעקב אחר גרגירים עדינים יותר.

עכשיו בואו נסתכל על של סלאוט תמיכה בחוטים.

3.4. Runnables פורש

כדי להדגים את יכולות ההשחלה של בַּלָשׁ בואו נוסיף תחילה מחלקת תצורה להגדרת מאגר חוטים:

@Configuration בכיתה ציבורית ThreadConfig {@ BeanFactory פרטית אוטומטית פרטית; @Bean Executor Executor () {ThreadPoolTaskExecutor threadPoolTaskExecutor = ThreadPoolTaskExecutor חדש (); threadPoolTaskExecutor.setCorePoolSize (1); threadPoolTaskExecutor.setMaxPoolSize (1); threadPoolTaskExecutor.initialize (); להחזיר LazyTraceExecutor חדש (beanFactory, threadPoolTaskExecutor); }}

חשוב לציין כאן את השימוש ב- LazyTraceExecutor. שיעור זה בא מה בַּלָשׁ הספרייה והיא סוג מיוחד של מוציא להורג שתפיץ את שלנו traceIds לשרשורים חדשים וליצור חדשים spanIds בתהליך.

עכשיו בואו נחבר את המנהל הזה לבקר שלנו ונשתמש בו בשיטת מיפוי בקשות חדשות:

@ מוציא להורג פרטי פרטי; @GetMapping ("/ thread-new") מחרוזת helloSleuthNewThread () {logger.info ("אשכול חדש"); Runnable runnable = () -> {נסה {Thread.sleep (1000L); } לתפוס (InterruptedException e) {e.printStackTrace (); } logger.info ("אני בתוך השרשור החדש - עם טווח חדש"); }; executor.execute (ניתן להפעיל); logger.info ("סיימתי - עם טווח המקור"); להחזיר "הצלחה"; }

עם הפעלתנו במקום, בוא נתחיל מחדש את היישום שלנו ונעבור אל "// localhost: 8080 / thread-new". צפה לפלט יומן שנראה כמו:

2017-01-11 21: 18: 15.949 מידע [הדרכה של Baeldung Sleuth, 96076a78343c364d, 96076a78343c364d, false] 12516 --- [nio-8080-exec-9] cbspring.session.SleuthController: חוט חדש 21/01/2017 : 18: 15.950 מידע [הדרכה של Baeldung Sleuth, 96076a78343c364d, 96076a78343c364d, false] 12516 --- [nio-8080-exec-9] cbspring.session.SleuthController: סיימתי - עם הטווח המקורי 11/01/2017 21: 18: 16.953 מידע [הדרכה של Baeldung Sleuth, 96076a78343c364d, e3b6a68013ddfeea, false] 12516 --- [lTaskExecutor-1] cbspring.session.SleuthController: אני בתוך החוט החדש - עם טווח חדש

בדומה לדוגמא הקודמת אנו יכולים לראות כי כל היומנים חולקים אותו דבר traceId. אך היומן שמקורו ב- Runnable כולל טווח ייחודי שיעקוב אחר העבודה שנעשתה בשרשור זה. זכרו שזה קורה בגלל LazyTraceExecutor, אם היינו משתמשים במבצע רגיל היינו ממשיכים לראות אותו דבר spanId משמש בשרשור החדש.

עכשיו בואו נסתכל של סלאוט תמיכה ל @ Async שיטות.

3.5. @ Async תמיכה

כדי להוסיף תמיכה ב- async בואו קודם לשנות את ThreadConfig בכיתה כדי לאפשר תכונה זו:

@Configuration @EnableAsync המחלקה הציבורית ThreadConfig מרחיב את AsyncConfigurerSupport {// ... @Override Public Executor getAsyncExecutor () {ThreadPoolTaskExecutor threadPoolTaskExecutor = ThreadPoolTaskExecutor (); threadPoolTaskExecutor.setCorePoolSize (1); threadPoolTaskExecutor.setMaxPoolSize (1); threadPoolTaskExecutor.initialize (); להחזיר LazyTraceExecutor חדש (beanFactory, threadPoolTaskExecutor); }}

שימו לב שאנחנו מרחיבים AsyncConfigurerSupport כדי לציין את מבצע ה- async והשימוש בו LazyTraceExecutor כדי להבטיח כי עקבות ותפריטים מופצים כהלכה. הוספנו גם @EnableAsync לראש הכיתה שלנו.

בואו כעת הוסיפו שיטת async לשירות שלנו:

@Async פומבית בטל asyncMethod () {logger.info ("התחל שיטת Async"); Thread.sleep (1000L); logger.info ("סוף שיטת הסינכרון"); }

עכשיו בואו נקרא לשיטה זו מהבקר שלנו:

@GetMapping ("/ async") ציבורי מחרוזת helloSleuthAsync () {logger.info ("לפני קריאת שיטת Async"); sleuthService.asyncMethod (); logger.info ("אחרי שיחת שיטת Async"); להחזיר "הצלחה"; }

לסיום, בואו נתחיל מחדש את השירות שלנו ונעבור אל "// localhost: 8080 / async". צפה לפלט היומן שנראה כמו:

2017-01-11 21: 30: 40.621 מידע [הדרכה של Baeldung Sleuth, c187f81915377fff, c187f81915377fff, false] 10072 --- [nio-8080-exec-2] cbspring.session.SleuthController: לפני שיטת Async התקשר 2017-01- 11 21: 30: 40.622 מידע [הדרכה של Baeldung Sleuth, c187f81915377fff, c187f81915377fff, false] 10072 --- [nio-8080-exec-2] cbspring.session.SleuthController: אחרי שיטת Async התקשר לשנת 01-01-2017 21:30 : 40.622 מידע [הדרכה של Baeldung Sleuth, c187f81915377fff, 8a9f3f097dca6a9e, false] 10072 --- [lTaskExecutor-1] c.baeldung.spring.session.SleuthService: התחל שיטת Async 2017-01-11 21: 30: 41.622 INFO [Baeldung Sleuth הדרכה, c187f81915377fff, 8a9f3f097dca6a9e, false] 10072 --- [lTaskExecutor-1] c.baeldung.spring.session.SleuthService: שיטת Async סוף

אנחנו יכולים לראות כאן הרבה כמו הדוגמה שלנו, בַּלָשׁ מפיץ את traceId לשיטת async ומוסיף spanId ייחודי.

בואו נעבור באמצעות דוגמא באמצעות תמיכה באביב למשימות מתוזמנות.

3.6. מתוזמן תמיכה

לבסוף, בואו נסתכל איך בַּלָשׁ עובד עם מתוזמן שיטות. לשם כך בואו לעדכן את שלנו ThreadConfig בכיתה כדי לאפשר תזמון:

@Configuration @EnableAsync @EnableScheduling בכיתה ציבורית ThreadConfig מרחיב את AsyncConfigurerSupport מיישם SchedulingConfigurer {// ... @Override public void configureTasks (ScheduledTaskRegistrar schedulTaskRegistrar) {schedulTaskRegistrar.setScheduler; setScheduler; set; } @Bean (destroyMethod = "כיבוי") התכנון הציבורי של התביעה הציבורית () {return Executors.newScheduledThreadPool (1); }}

שים לב שהטמענו את ה- מתזמן קביעת תצורה ממשק ועקף את שיטת configureTasks שלו. הוספנו גם @EnableScheduling לראש הכיתה שלנו.

לאחר מכן, בואו להוסיף שירות למשימות המתוזמנות שלנו:

מחלקה ציבורית @Service SchedulingService {לוגר לוגר פרטי = LoggerFactory.getLogger (this.getClass ()); @ SleuthService פרטית אוטומטית sleuthService; @Scheduled (fixedDelay = 30000) חלל פומבי schedWork () זורק את InterruptedException {logger.info ("התחל לעבוד מהמטלה המתוזמנת"); sleuthService.asyncMethod (); logger.info ("סיום העבודה ממשימה מתוזמנת"); }}

בשיעור זה יצרנו משימה מתוזמנת אחת עם עיכוב קבוע של 30 שניות.

בוא נתחיל כעת להפעיל מחדש את היישום שלנו ונחכה לביצוע המשימה שלנו. צפה בקונסולה לקבלת פלט כזה:

2017-01-11 21: 30: 58.866 מידע [הדרכה של Baeldung Sleuth, 3605f5deaea28df2,3605f5deaea28df2, false] 10072 --- [pool-1-thread-1] cbspring.session.SchedulingService: התחל בעבודה מהמטלה המתוזמנת 2017 -01-11 21: 30: 58.866 מידע [הדרכה של Baeldung Sleuth, 3605f5deaea28df2,3605f5deaea28df2, false] 10072 --- [pool-1-thread-1] cbspring.session.SchedulingService: סיום העבודה ממשימה מתוזמנת

אנו יכולים לראות כאן את זה בַּלָשׁ יצר מזהי מעקב וטווח חדשים למשימה שלנו. כל מופע של משימה יקבל עקבות וטווח משלה כברירת מחדל.

4. מסקנה

לסיכום, ראינו כיצד אביב סלאוט יכול לשמש במגוון מצבים בתוך יישום אינטרנט יחיד. אנו יכולים להשתמש בטכנולוגיה זו כדי לתאם בקלות יומנים מבקשה אחת, גם כאשר בקשה זו מתפרשת על מספר שרשורים.

עד עכשיו אנו יכולים לראות כיצד אביב ענן סלאוט יכול לעזור לנו לשמור על שפיותנו בעת ניפוי באגים בסביבה מרובת-הברגה. על ידי זיהוי כל פעולה ב traceId וכל שלב ב spanId אנחנו באמת יכולים להתחיל לפרק את הניתוח שלנו על עבודות מורכבות ביומנינו.

גם אם אנחנו לא הולכים לענן, אביב סלאוט הוא ככל הנראה תלות קריטית כמעט בכל פרויקט; זה חלק לשילוב ו הוא תוספת מסיבית של ערך.

מכאן כדאי לחקור תכונות אחרות של בַּלָשׁ. זה יכול לתמוך במעקב במערכות מבוזרות באמצעות RestTemplate, על פני פרוטוקולי העברת הודעות המשמשים את RabbitMQ ו רדיס, ודרך שער כמו זול.

כמו תמיד תוכל למצוא את קוד המקור ב- Github.


$config[zx-auto] not found$config[zx-overlay] not found