การติดตามบริการ OpenTracing และ Jaeger

การติดตามบริการ OpenTracing และ Jaeger

เราใช้สถาปัตยกรรมไมโครเซอร์วิสในโครงการของเรา เมื่อเกิดปัญหาคอขวดด้านประสิทธิภาพ จะต้องใช้เวลามากในการตรวจสอบและแยกวิเคราะห์บันทึก เมื่อบันทึกการกำหนดเวลาของการดำเนินการแต่ละรายการลงในไฟล์บันทึก มักจะยากที่จะเข้าใจว่าอะไรนำไปสู่การเรียกใช้การดำเนินการเหล่านี้ เพื่อติดตามลำดับของการดำเนินการหรือการเปลี่ยนแปลงเวลาของการดำเนินการหนึ่งที่เกี่ยวข้องกับอีกบริการหนึ่ง

เพื่อลดการใช้แรงงานคน เราตัดสินใจใช้เครื่องมือติดตามตัวใดตัวหนึ่ง เกี่ยวกับวิธีการและเหตุผลที่คุณสามารถใช้การติดตามและวิธีที่เราใช้ ซึ่งจะมีการกล่าวถึงในบทความนี้

ปัญหาใดที่สามารถแก้ไขได้ด้วยการติดตาม

  1. ค้นหาคอขวดของประสิทธิภาพทั้งภายในบริการเดียวและในแผนผังการดำเนินการทั้งหมดระหว่างบริการที่เข้าร่วมทั้งหมด ตัวอย่างเช่น:
    • การเรียกสั้นๆ ติดต่อกันหลายๆ ครั้งระหว่างบริการต่างๆ เช่น เพื่อ geocoding หรือไปยังฐานข้อมูล
    • การรอ I/O ที่ยาวนาน เช่น การโอนย้ายเครือข่ายหรือการอ่านดิสก์
    • การแยกวิเคราะห์ข้อมูลแบบยาว
    • การทำงานที่ยาวนานต้องใช้ซีพียู
    • ส่วนของโค้ดที่ไม่จำเป็นเพื่อให้ได้ผลลัพธ์สุดท้าย และสามารถลบออกหรือเลื่อนออกไปได้
  2. เข้าใจอย่างชัดเจนว่าลำดับใดที่เรียกว่าอะไรและจะเกิดอะไรขึ้นเมื่อดำเนินการ
    การติดตามบริการ OpenTracing และ Jaeger
    จะเห็นได้ว่า ตัวอย่างเช่น คำขอมาที่บริการ WS -> บริการ WS เพิ่มข้อมูลผ่านบริการ R -> จากนั้นส่งคำขอไปยังบริการ V -> บริการ V โหลดข้อมูลจำนวนมากจากบริการ R -> ไปที่บริการ P -> บริการ P ไปที่บริการ R อีกครั้ง -> บริการ V เพิกเฉยต่อผลลัพธ์และไปที่บริการ J -> จากนั้นจึงส่งคืนการตอบกลับไปยังบริการ WS เท่านั้น ในขณะที่ดำเนินการคำนวณอย่างอื่นอยู่เบื้องหลัง
    หากไม่มีการติดตามหรือเอกสารโดยละเอียดสำหรับกระบวนการทั้งหมด ก็เป็นเรื่องยากมากที่จะเข้าใจว่าเกิดอะไรขึ้นเมื่อดูโค้ดเป็นครั้งแรก และโค้ดจะกระจัดกระจายไปตามบริการต่างๆ และซ่อนอยู่หลังถังขยะและอินเทอร์เฟซจำนวนมาก
  3. การรวบรวมข้อมูลเกี่ยวกับแผนผังการดำเนินการสำหรับการวิเคราะห์ที่เลื่อนออกไปในภายหลัง ในแต่ละขั้นตอนของการดำเนินการ คุณสามารถเพิ่มข้อมูลไปยังการติดตามที่พร้อมใช้งานในขั้นตอนนี้ จากนั้นค้นหาว่าข้อมูลอินพุตใดที่นำไปสู่สถานการณ์ที่คล้ายกัน ตัวอย่างเช่น:
    • รหัสผู้ใช้
    • สิทธิมนุษยชน
    • ประเภทของวิธีที่เลือก
    • บันทึกหรือดำเนินการผิดพลาด
  4. เปลี่ยนการติดตามเป็นส่วนย่อยของเมตริกและการวิเคราะห์เพิ่มเติมในรูปแบบของเมตริก

ร่องรอยใดที่สามารถบันทึกได้ ช่วง

ในการติดตามมีแนวคิดของช่วง ซึ่งเป็นอะนาล็อกของบันทึกหนึ่งไปยังคอนโซล สปามี:

  • ชื่อ โดยปกติจะเป็นชื่อของเมธอดที่ถูกเรียกใช้งาน
  • ชื่อของบริการที่สร้างช่วง
  • ID เฉพาะของตัวเอง
  • ข้อมูลเมตาบางประเภทในรูปแบบของคีย์/ค่าที่เข้าสู่ระบบ ตัวอย่างเช่น พารามิเตอร์เมธอดหรือเมธอดจบลงด้วยข้อผิดพลาดหรือไม่
  • เวลาเริ่มต้นและสิ้นสุดสำหรับช่วงเวลานี้
  • รหัสช่วงผู้ปกครอง

แต่ละช่วงจะถูกส่งไปยังตัวรวบรวมช่วงเพื่อเก็บไว้ในฐานข้อมูลเพื่อตรวจสอบในภายหลังทันทีที่ดำเนินการเสร็จสิ้น ในอนาคต คุณสามารถสร้างแผนผังของช่วงทั้งหมดได้โดยเชื่อมต่อด้วยรหัสพาเรนต์ เมื่อทำการวิเคราะห์ คุณจะพบ เช่น ระยะเวลาทั้งหมดในบริการบางอย่างที่ใช้เวลานานกว่าระยะหนึ่ง นอกจากนี้ เมื่อไปที่ช่วงใดช่วงหนึ่ง ให้ดูทั้งต้นไม้ด้านบนและด้านล่างของช่วงนี้

การติดตามบริการ OpenTracing และ Jaeger

Opentrace, Jagger และวิธีที่เราใช้ในโครงการของเรา

มีมาตรฐานร่วมกัน เปิดการติดตามซึ่งอธิบายถึงวิธีการและสิ่งที่ควรรวบรวม โดยไม่ผูกติดกับการนำไปใช้เฉพาะในภาษาใดๆ ตัวอย่างเช่น ใน Java การทำงานทั้งหมดที่มีการติดตามจะดำเนินการผ่าน Opentrace API ทั่วไป และภายใต้นั้น เช่น Jaeger หรือการใช้งานเริ่มต้นที่ว่างเปล่าซึ่งไม่สามารถซ่อนสิ่งใดไว้ได้
เรากำลังใช้ Jaeger เป็นการใช้งาน Opentrace ประกอบด้วยองค์ประกอบหลายอย่าง:

การติดตามบริการ OpenTracing และ Jaeger

  • Jaeger-agent เป็น local agent ที่โดยปกติจะติดตั้งในแต่ละเครื่องและบริการต่างๆ จะถูกล็อกอินบนพอร์ตเริ่มต้นในเครื่อง หากไม่มีตัวแทน การติดตามบริการทั้งหมดบนเครื่องนี้มักจะถูกปิดใช้งาน
  • Jaeger-collector - ตัวแทนทั้งหมดส่งการติดตามที่รวบรวมได้และวางไว้ในฐานข้อมูลที่เลือก
  • ฐานข้อมูลเป็นคาสซานดราที่พวกเขาต้องการ แต่เราใช้ elasticsearch มีการใช้งานสำหรับฐานข้อมูลอื่นสองสามฐานข้อมูลและการใช้งานในหน่วยความจำที่ไม่ได้บันทึกอะไรลงในดิสก์
  • Jaeger-query เป็นบริการที่ไปยังฐานข้อมูลและส่งคืนร่องรอยที่รวบรวมไว้แล้วสำหรับการวิเคราะห์
  • Jaeger-ui เป็นเว็บอินเตอร์เฟสสำหรับค้นหาและดูร่องรอย โดยจะไปที่ jaeger-query

การติดตามบริการ OpenTracing และ Jaeger

คอมโพเนนต์ที่แยกจากกันสามารถเรียกว่าการดำเนินการของ opentrace jaeger สำหรับภาษาเฉพาะ ซึ่งส่งผ่านช่วงไปยัง jaeger-agent
การเชื่อมต่อ Jagger ใน Java ลงมาเพื่อใช้อินเทอร์เฟซ io.opentracing.Tracer หลังจากนั้นการติดตามทั้งหมดจะบินไปยังตัวแทนจริง

การติดตามบริการ OpenTracing และ Jaeger

คุณสามารถเชื่อมต่อสำหรับส่วนประกอบสปริงได้ opentracing-สปริงคลาวด์สตาร์ทเตอร์ และการใช้งานจาก Jaeger opentracing-สปริงแจเกอร์-คลาวด์สตาร์ทเตอร์ ซึ่งจะกำหนดค่าการติดตามโดยอัตโนมัติสำหรับทุกสิ่งที่ผ่านส่วนประกอบเหล่านี้ เช่น คำขอ HTTP ไปยังคอนโทรลเลอร์ คำขอไปยังฐานข้อมูลผ่าน jdbc เป็นต้น

บันทึกการติดตามใน Java

ที่ระดับบนสุด ต้องสร้าง Span แรก ซึ่งสามารถทำได้โดยอัตโนมัติ เช่น โดยสปริงคอนโทรลเลอร์เมื่อได้รับการร้องขอ หรือด้วยตนเองหากไม่มี จากนั้นจะถูกส่งผ่านขอบเขตด้านล่าง หากเมธอดใดๆ ด้านล่างต้องการเพิ่ม Span ระบบจะใช้ ActiveSpan ปัจจุบันจากขอบเขต สร้าง Span ใหม่และบอกว่าพาเรนต์คือ ActiveSpan ที่เป็นผลลัพธ์ และทำให้ Span ใหม่ใช้งานได้ เมื่อเรียกใช้บริการจากภายนอก สแปนที่ใช้งานอยู่ในปัจจุบันจะถูกส่งต่อไปยังบริการเหล่านั้น และบริการเหล่านั้นจะสร้างสแปนใหม่โดยอ้างอิงจากสแปนนี้
งานทั้งหมดต้องผ่านอินสแตนซ์ Tracer คุณสามารถรับได้ผ่านกลไก DI หรือ GlobalTracer.get () เป็นตัวแปรส่วนกลางหากกลไก DI ไม่ทำงาน ตามค่าเริ่มต้น ถ้าตัวติดตามไม่ได้ถูกเตรียมใช้งาน NoopTracer จะกลับมาโดยไม่ทำอะไรเลย
นอกจากนี้ ขอบเขตปัจจุบันได้รับจากตัวติดตามผ่าน ScopeManager ขอบเขตใหม่จะถูกสร้างขึ้นจากขอบเขตปัจจุบันโดยผูกกับช่วงใหม่ จากนั้นขอบเขตที่สร้างขึ้นจะปิด ซึ่งจะปิดช่วงที่สร้างขึ้นและส่งกลับขอบเขตก่อนหน้าไปยังสถานะใช้งาน ขอบเขตเชื่อมโยงกับเธรด ดังนั้นเมื่อเขียนโปรแกรมแบบมัลติเธรด คุณต้องไม่ลืมโอนช่วงที่ใช้งานไปยังเธรดอื่น เพื่อเปิดใช้งานขอบเขตของเธรดอื่นเพิ่มเติมโดยอ้างอิงถึงสแปนนี้

io.opentracing.Tracer tracer = ...; // GlobalTracer.get()

void DoSmth () {
   try (Scope scope = tracer.buildSpan("DoSmth").startActive(true)) {
      ...
   }
}
void DoOther () {
    Span span = tracer.buildSpan("someWork").start();
    try (Scope scope = tracer.scopeManager().activate(span, false)) {
        // Do things.
    } catch(Exception ex) {
        Tags.ERROR.set(span, true);
        span.log(Map.of(Fields.EVENT, "error", Fields.ERROR_OBJECT, ex, Fields.MESSAGE, ex.getMessage()));
    } finally {
        span.finish();
    }
}

void DoAsync () {
    try (Scope scope = tracer.buildSpan("ServiceHandlerSpan").startActive(false)) {
        ...
        final Span span = scope.span();
        doAsyncWork(() -> {
            // STEP 2 ABOVE: reactivate the Span in the callback, passing true to
            // startActive() if/when the Span must be finished.
            try (Scope scope = tracer.scopeManager().activate(span, false)) {
                ...
            }
        });
    }
}

สำหรับการเขียนโปรแกรมแบบมัลติเธรด ยังมี TracedExecutorService และ wrapper ที่คล้ายกันซึ่งจะส่งต่อช่วงปัจจุบันไปยังเธรดโดยอัตโนมัติเมื่อเปิดใช้งานงานแบบอะซิงโครนัส:

private ExecutorService executor = new TracedExecutorService(
    Executors.newFixedThreadPool(10), GlobalTracer.get()
);

สำหรับคำขอ HTTP ภายนอกมี การติดตาม HTTPClient

HttpClient httpClient = new TracingHttpClientBuilder().build();

ปัญหาที่เราประสบ

  • ดังนั้น Beans และ DI จะไม่ทำงานเสมอไปหากไม่ได้ใช้ตัวติดตามในบริการหรือส่วนประกอบ อัตโนมัติ Tracer อาจใช้งานไม่ได้ และคุณจะต้องใช้ GlobalTracer.get()
  • คำอธิบายประกอบจะไม่ทำงานหากไม่ใช่คอมโพเนนต์หรือบริการ หรือหากเมธอดถูกเรียกจากเมธอดข้างเคียงของคลาสเดียวกัน คุณต้องระมัดระวังในการตรวจสอบว่าอะไรใช้งานได้และใช้การสร้างการติดตามด้วยตนเองหาก @Traced ไม่ทำงาน คุณยังสามารถแนบคอมไพเลอร์เพิ่มเติมสำหรับคำอธิบายประกอบของจาวา ซึ่งควรจะทำงานได้ทุกที่
  • ในสปริงและสปริงบูตแบบเก่า การกำหนดค่าอัตโนมัติของ opentraing spring cloud ไม่ทำงานเนื่องจากข้อบกพร่องใน DI ดังนั้นหากคุณต้องการให้ร่องรอยในส่วนประกอบสปริงทำงานโดยอัตโนมัติ คุณสามารถทำได้โดยเปรียบเทียบกับ github.com/opentracing-contrib/java-spring-jaeger/blob/master/opentracing-spring-jaeger-starter/src/main/java/io/opentracing/contrib/java/spring/jaeger/starter/JaegerAutoConfiguration.java
  • การลองด้วยทรัพยากรใช้งานไม่ได้ใน Groovy คุณต้องใช้การลองในที่สุด
  • แต่ละบริการต้องมี spring.application.name ของตัวเอง ซึ่งการติดตามจะถูกบันทึก ชื่อแยกต่างหากสำหรับการขายและการทดสอบคืออะไร เพื่อไม่ให้รบกวนพวกเขาด้วยกัน
  • หากคุณใช้ GlobalTracer และ Tomcat บริการทั้งหมดที่ทำงานใน Tomcat นี้จะมี GlobalTracer เดียว ดังนั้นบริการทั้งหมดจะมีชื่อบริการเหมือนกัน
  • เมื่อเพิ่มการติดตามให้กับเมธอด คุณต้องแน่ใจว่าไม่ได้เรียกซ้ำหลายครั้ง จำเป็นต้องเพิ่มหนึ่งการติดตามทั่วไปสำหรับการโทรทั้งหมด ซึ่งรับประกันเวลาทำงานทั้งหมด มิฉะนั้นจะมีการสร้างภาระส่วนเกิน
  • ครั้งหนึ่งใน jaeger-ui มีการร้องขอจำนวนมากเกินไปสำหรับการติดตามจำนวนมาก และเนื่องจากพวกเขาไม่รอการตอบกลับ พวกเขาจึงทำอีกครั้ง ผลที่ตามมาคือ jaeger-query เริ่มกินหน่วยความจำจำนวนมากและทำให้ความยืดหยุ่นช้าลง ช่วยโดยการรีสตาร์ท jaeger-query

การสุ่มตัวอย่าง การจัดเก็บ และการดูร่องรอย

มีสามประเภท ร่องรอยการสุ่มตัวอย่าง:

  1. Const ซึ่งส่งและบันทึกร่องรอยทั้งหมด
  2. ความน่าจะเป็นที่กรองร่องรอยด้วยความน่าจะเป็นที่กำหนด
  3. Ratelimiting ซึ่งจำกัดจำนวนการติดตามต่อวินาที คุณสามารถกำหนดการตั้งค่าเหล่านี้บนไคลเอ็นต์ บน jaeger-agent หรือบนตัวรวบรวม ตอนนี้เราใช้ const 1 ใน valuator stack เนื่องจากมีคำขอไม่มากนัก แต่ใช้เวลานาน ในอนาคต ถ้าสิ่งนี้จะทำให้ระบบโหลดมากเกินไป คุณสามารถจำกัดได้

หากคุณใช้คาสซานดรา ตามค่าเริ่มต้นจะเก็บร่องรอยไว้เพียงสองวันเท่านั้น เรากำลังใช้ ElasticSearch และการติดตามจะถูกเก็บไว้ตลอดเวลาและไม่ถูกลบ แต่ละวันจะมีการสร้างดัชนีแยกต่างหาก ตัวอย่างเช่น jaeger-service-2019-03-04 ในอนาคต คุณต้องกำหนดค่าการล้างร่องรอยเก่าโดยอัตโนมัติ

ในการดูร่องรอยที่คุณต้องการ:

  • เลือกบริการที่คุณต้องการกรองการติดตาม ตัวอย่างเช่น tomcat7-default สำหรับบริการที่ทำงานใน Tomcat และไม่สามารถมีชื่อของตัวเองได้
  • จากนั้นเลือกการดำเนินการ ช่วงเวลา และเวลาการดำเนินการขั้นต่ำ เช่น จาก 10 วินาที เพื่อใช้เวลาการดำเนินการที่ยาวนานเท่านั้น
    การติดตามบริการ OpenTracing และ Jaeger
  • ไปที่หนึ่งในร่องรอยและดูว่ามีอะไรช้าลงที่นั่น
    การติดตามบริการ OpenTracing และ Jaeger

นอกจากนี้ หากทราบรหัสคำขอบางรายการ คุณสามารถค้นหาการติดตามด้วยรหัสนี้ผ่านการค้นหาแท็ก หากรหัสนี้ถูกบันทึกไว้ในช่วงการติดตาม

เอกสาร

บทความ

วีดีโอ

  • www.youtube.com/watch?v=qg0ENOdP1Lo วิธีที่เราใช้ Jaeger และ Prometheus เพื่อส่งข้อความค้นหาของผู้ใช้ที่รวดเร็วปานสายฟ้า — Bryan Boreham
  • www.youtube.com/watch?v=WRntQsUajow บทนำ: Jaeger - Yuri Shkuro, Uber & Pavol Loffay, Red Hat
  • www.youtube.com/watch?v=fsHb0qK37bc Serghei Iakovlev, “เรื่องเล็กๆ ของชัยชนะที่ยิ่งใหญ่: OpenTracing, AWS และ Jaeger”

ที่มา: will.com

เพิ่มความคิดเห็น