สถาปัตยกรรมของตัวโหลดบาลานเซอร์เครือข่ายใน Yandex.Cloud

สถาปัตยกรรมของตัวโหลดบาลานเซอร์เครือข่ายใน Yandex.Cloud
สวัสดี ฉันชื่อ Sergey Elantsev ฉันพัฒนา ตัวโหลดบาลานซ์เครือข่าย ใน Yandex.Cloud ก่อนหน้านี้ฉันเป็นผู้นำการพัฒนาบาลานเซอร์ L7 สำหรับพอร์ทัลยานเดกซ์ - เพื่อนร่วมงานพูดติดตลกว่าไม่ว่าฉันจะทำอะไรมันก็กลายเป็นบาลานเซอร์ ฉันจะบอกผู้อ่าน Habr ถึงวิธีจัดการโหลดในแพลตฟอร์มคลาวด์ สิ่งที่เราเห็นว่าเป็นเครื่องมือในอุดมคติสำหรับการบรรลุเป้าหมายนี้ และวิธีที่เราจะก้าวไปสู่การสร้างเครื่องมือนี้

ก่อนอื่น เรามาแนะนำคำศัพท์กันก่อน:

  • วีไอพี (IP เสมือน) - ที่อยู่ IP ของบาลานเซอร์
  • เซิร์ฟเวอร์ แบ็กเอนด์ อินสแตนซ์ - เครื่องเสมือนที่รันแอปพลิเคชัน
  • RIP (IP จริง) - ที่อยู่ IP ของเซิร์ฟเวอร์
  • Healthcheck - ตรวจสอบความพร้อมของเซิร์ฟเวอร์
  • Availability Zone, AZ - โครงสร้างพื้นฐานแบบแยกส่วนในศูนย์ข้อมูล
  • ภูมิภาค - การรวมกันของ AZ ที่แตกต่างกัน

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

โหลดบาลานเซอร์มักถูกจัดประเภทตามเลเยอร์โปรโตคอลจากโมเดล OSI ที่โหลดบาลานเซอร์ทำงาน Cloud Balancer ทำงานที่ระดับ TCP ซึ่งสอดคล้องกับเลเยอร์ที่สี่ L4

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

เครื่องบินข้อมูล

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

สถาปัตยกรรมของตัวโหลดบาลานเซอร์เครือข่ายใน Yandex.Cloud

การรับส่งข้อมูลถูกส่งผ่าน ECMP - นี่คือกลยุทธ์การกำหนดเส้นทางซึ่งสามารถมีหลายเส้นทางที่ดีพอ ๆ กันไปยังเป้าหมาย (ในกรณีของเราเป้าหมายจะเป็นที่อยู่ IP ปลายทาง) และสามารถส่งแพ็กเก็ตไปตามเส้นทางใดก็ได้ นอกจากนี้เรายังสนับสนุนการทำงานในโซนความพร้อมใช้งานหลายแห่งตามรูปแบบต่อไปนี้: เราโฆษณาที่อยู่ในแต่ละโซน การรับส่งข้อมูลไปยังโซนที่ใกล้ที่สุดและไม่เกินขีดจำกัด ภายหลังในโพสต์ เราจะดูรายละเอียดเพิ่มเติมเกี่ยวกับสิ่งที่เกิดขึ้นกับการจราจร

กำหนดค่าระนาบ

 
องค์ประกอบหลักของระนาบการกำหนดค่าคือ API ซึ่งใช้ดำเนินการพื้นฐานกับบาลานเซอร์: การสร้าง การลบ การเปลี่ยนองค์ประกอบของอินสแตนซ์ การได้รับผลลัพธ์การตรวจสุขภาพ ฯลฯ ในด้านหนึ่ง นี่คือ REST API และบน อื่นๆ เราในระบบคลาวด์มักใช้เฟรมเวิร์ก gRPC ดังนั้นเราจึง "แปล" REST เป็น gRPC แล้วใช้เฉพาะ gRPC เท่านั้น คำขอใดๆ จะนำไปสู่การสร้างชุดงาน idempotent แบบอะซิงโครนัสที่ดำเนินการในกลุ่มผู้ปฏิบัติงาน Yandex.Cloud ทั่วไป งานถูกเขียนในลักษณะที่สามารถระงับได้ตลอดเวลาแล้วเริ่มใหม่อีกครั้ง สิ่งนี้ทำให้มั่นใจถึงความสามารถในการปรับขนาด การทำซ้ำ และการบันทึกการดำเนินการ

สถาปัตยกรรมของตัวโหลดบาลานเซอร์เครือข่ายใน Yandex.Cloud

ด้วยเหตุนี้ งานจาก API จะส่งคำขอไปยังตัวควบคุมบริการบาลานเซอร์ ซึ่งเขียนด้วยภาษา Go สามารถเพิ่มและลบบาลานเซอร์ เปลี่ยนองค์ประกอบของแบ็กเอนด์และการตั้งค่าได้ 

สถาปัตยกรรมของตัวโหลดบาลานเซอร์เครือข่ายใน Yandex.Cloud

บริการจัดเก็บสถานะไว้ในฐานข้อมูล Yandex ซึ่งเป็นฐานข้อมูลที่มีการจัดการแบบกระจายที่คุณจะสามารถใช้ได้ในไม่ช้า ใน Yandex.Cloud เหมือนที่เราอยู่แล้ว บอกแนวคิดเรื่องอาหารสุนัขถูกนำมาใช้: หากเราใช้บริการของเราเอง ลูกค้าของเราก็จะยินดีใช้บริการเช่นกัน ฐานข้อมูล Yandex เป็นตัวอย่างของการนำแนวคิดดังกล่าวไปใช้ เราจัดเก็บข้อมูลทั้งหมดของเราไว้ใน YDB และเราไม่จำเป็นต้องคำนึงถึงการบำรุงรักษาและปรับขนาดฐานข้อมูล ปัญหาเหล่านี้แก้ไขให้เราแล้ว เราใช้ฐานข้อมูลเป็นบริการ

กลับไปที่ตัวควบคุมบาลานเซอร์กันเถอะ หน้าที่คือบันทึกข้อมูลเกี่ยวกับบาลานเซอร์และส่งงานเพื่อตรวจสอบความพร้อมของเครื่องเสมือนไปยังตัวควบคุมการตรวจสุขภาพ

ตัวควบคุมการตรวจสุขภาพ

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

สถาปัตยกรรมของตัวโหลดบาลานเซอร์เครือข่ายใน Yandex.Cloud

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

นอกจากนี้ การตรวจสอบยังแตกต่างกันในระดับการดำเนินการ - เป็นแบบแอคทีฟและไม่โต้ตอบ การตรวจสอบแบบพาสซีฟเพียงตรวจสอบสิ่งที่เกิดขึ้นกับการรับส่งข้อมูลโดยไม่ต้องดำเนินการใดๆ เป็นพิเศษ สิ่งนี้ทำงานได้ไม่ดีนักบน L4 เนื่องจากขึ้นอยู่กับตรรกะของโปรโตคอลระดับสูงกว่า: บน L4 ไม่มีข้อมูลเกี่ยวกับระยะเวลาการดำเนินการที่ใช้เวลานานหรือการเชื่อมต่อเสร็จสมบูรณ์ดีหรือไม่ดี การตรวจสอบที่ใช้งานอยู่ต้องการให้บาลานเซอร์ส่งคำขอไปยังแต่ละอินสแตนซ์ของเซิร์ฟเวอร์

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

สถาปัตยกรรมของตัวโหลดบาลานเซอร์เครือข่ายใน Yandex.Cloud

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

ข้อแตกต่างคือลูกค้าส่งคำขอไปยัง VIP ในขณะที่การตรวจสุขภาพจะส่งคำขอไปยัง RIP แต่ละรายการ ปัญหาที่น่าสนใจเกิดขึ้นที่นี่: เราให้โอกาสผู้ใช้ของเราในการสร้างทรัพยากรในเครือข่าย IP สีเทา ลองจินตนาการว่ามีเจ้าของคลาวด์สองคนที่แตกต่างกันซึ่งซ่อนบริการของตนไว้เบื้องหลังบาลานเซอร์ แต่ละรายการมีทรัพยากรในซับเน็ต 10.0.0.1/24 โดยมีที่อยู่เดียวกัน คุณต้องสามารถแยกแยะความแตกต่างได้และที่นี่คุณต้องเจาะลึกโครงสร้างของเครือข่ายเสมือน Yandex.Cloud เข้าไปดูรายละเอียดเพิ่มเติมใน วิดีโอจากงาน about:cloudสิ่งสำคัญสำหรับเราในตอนนี้คือเครือข่ายมีหลายชั้นและมีช่องสัญญาณที่สามารถแยกแยะได้ด้วยรหัสเครือข่ายย่อย

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

การรับส่งข้อมูลแบบย้อนกลับดำเนินไปในลักษณะเดียวกัน: ตัวปรับสมดุลจะเห็นว่าปลายทางเป็นเครือข่ายสีเทาจากตัวตรวจสอบสุขภาพ และแปลง IPv4 เป็น IPv6

VPP - หัวใจของระนาบข้อมูล

บาลานเซอร์ถูกใช้งานโดยใช้เทคโนโลยี Vector Packet Processing (VPP) ซึ่งเป็นเฟรมเวิร์กจาก Cisco สำหรับการประมวลผลการรับส่งข้อมูลเครือข่ายเป็นชุด ในกรณีของเรา เฟรมเวิร์กทำงานบนไลบรารีการจัดการอุปกรณ์เครือข่ายพื้นที่ผู้ใช้ - Data Plane Development Kit (DPDK) สิ่งนี้ทำให้มั่นใจได้ถึงประสิทธิภาพการประมวลผลแพ็กเก็ตที่สูง: มีการขัดจังหวะเกิดขึ้นในเคอร์เนลน้อยลงมาก และไม่มีการสลับบริบทระหว่างพื้นที่เคอร์เนลและพื้นที่ผู้ใช้ 

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

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

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

n_left_from = frame->n_vectors;
while (n_left_from > 0)
{
    vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
    // ...
    while (n_left_from >= 4 && n_left_to_next >= 2)
    {
        // processing multiple packets at once
        u32 next0 = SAMPLE_NEXT_INTERFACE_OUTPUT;
        u32 next1 = SAMPLE_NEXT_INTERFACE_OUTPUT;
        // ...
        /* Prefetch next iteration. */
        {
            vlib_buffer_t *p2, *p3;

            p2 = vlib_get_buffer (vm, from[2]);
            p3 = vlib_get_buffer (vm, from[3]);

            vlib_prefetch_buffer_header (p2, LOAD);
            vlib_prefetch_buffer_header (p3, LOAD);

            CLIB_PREFETCH (p2->data, CLIB_CACHE_LINE_BYTES, STORE);
            CLIB_PREFETCH (p3->data, CLIB_CACHE_LINE_BYTES, STORE);
        }
        // actually process data
        /* verify speculative enqueues, maybe switch current next frame */
        vlib_validate_buffer_enqueue_x2 (vm, node, next_index,
                to_next, n_left_to_next,
                bi0, bi1, next0, next1);
    }

    while (n_left_from > 0 && n_left_to_next > 0)
    {
        // processing packets by one
    }

    // processed batch
    vlib_put_next_frame (vm, node, next_index, n_left_to_next);
}

ดังนั้น Healthchecks จะพูดคุยผ่าน IPv6 กับ VPP ซึ่งเปลี่ยนให้เป็น IPv4 สิ่งนี้ทำโดยโหนดในกราฟ ซึ่งเราเรียกว่า NAT แบบอัลกอริทึม สำหรับการรับส่งข้อมูลย้อนกลับ (และการแปลงจาก IPv6 เป็น IPv4) จะมีโหนด NAT แบบอัลกอริทึมเดียวกัน

สถาปัตยกรรมของตัวโหลดบาลานเซอร์เครือข่ายใน Yandex.Cloud

การรับส่งข้อมูลโดยตรงจากไคลเอนต์บาลานเซอร์จะผ่านโหนดกราฟ ซึ่งดำเนินการปรับสมดุลเอง 

สถาปัตยกรรมของตัวโหลดบาลานเซอร์เครือข่ายใน Yandex.Cloud

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

แฮช 5 ทูเพิลช่วยให้เราคำนวณน้อยลงในโหนดแฮชที่สอดคล้องกันในภายหลัง รวมถึงจัดการการเปลี่ยนแปลงรายการทรัพยากรด้านหลังบาลานเซอร์ได้ดีขึ้น เมื่อแพ็กเก็ตที่ไม่มีเซสชันมาถึงบาลานเซอร์ แพ็กเก็ตจะถูกส่งไปยังโหนดแฮชที่สอดคล้องกัน นี่คือจุดที่ความสมดุลเกิดขึ้นโดยใช้การแฮชที่สอดคล้องกัน: เราเลือกทรัพยากรจากรายการทรัพยากร "สด" ที่พร้อมใช้งาน ถัดไป แพ็กเก็ตจะถูกส่งไปยังโหนด NAT ซึ่งจะแทนที่ที่อยู่ปลายทางจริงและคำนวณเช็คซัมใหม่ อย่างที่คุณเห็นเราปฏิบัติตามกฎของ VPP - like to like โดยจัดกลุ่มการคำนวณที่คล้ายกันเพื่อเพิ่มประสิทธิภาพของแคชตัวประมวลผล

การแฮชที่สม่ำเสมอ

ทำไมเราถึงเลือกมันและมันคืออะไร? ขั้นแรก พิจารณางานก่อนหน้า - การเลือกทรัพยากรจากรายการ 

สถาปัตยกรรมของตัวโหลดบาลานเซอร์เครือข่ายใน Yandex.Cloud

ด้วยการแฮชที่ไม่สอดคล้องกัน ระบบจะคำนวณแฮชของแพ็กเก็ตขาเข้า และเลือกทรัพยากรจากรายการด้วยส่วนที่เหลือของการหารแฮชนี้ด้วยจำนวนทรัพยากร ตราบใดที่รายการยังคงไม่เปลี่ยนแปลง รูปแบบนี้จะทำงานได้ดี: เราจะส่งแพ็กเก็ตที่มี 5 tuple เดียวกันไปยังอินสแตนซ์เดียวกันเสมอ ตัวอย่างเช่น หากทรัพยากรบางส่วนหยุดตอบสนองต่อการตรวจสอบประสิทธิภาพ ตัวเลือกจะเปลี่ยนไปสำหรับแฮชส่วนสำคัญ การเชื่อมต่อ TCP ของไคลเอ็นต์จะใช้งานไม่ได้: แพ็กเก็ตที่เข้าถึงอินสแตนซ์ A ก่อนหน้านี้อาจเริ่มเข้าถึงอินสแตนซ์ B ซึ่งไม่คุ้นเคยกับเซสชันสำหรับแพ็กเก็ตนี้

การแฮชที่สอดคล้องกันช่วยแก้ปัญหาที่อธิบายไว้ วิธีที่ง่ายที่สุดในการอธิบายแนวคิดนี้คือ: ลองจินตนาการว่าคุณมีวงแหวนที่คุณแจกจ่ายทรัพยากรด้วยแฮช (เช่น โดย IP:พอร์ต) การเลือกทรัพยากรกำลังหมุนวงล้อตามมุม ซึ่งกำหนดโดยแฮชของแพ็กเก็ต

สถาปัตยกรรมของตัวโหลดบาลานเซอร์เครือข่ายใน Yandex.Cloud

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

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

Loadbalancer-node และส่วนประกอบที่ประกอบแล้ว

องค์ประกอบของบาลานเซอร์และทรัพยากรใน VPP ได้รับการรายงานโดยบริการในพื้นที่ - loadbalancer-node โดยจะสมัครรับสตรีมของเหตุการณ์จาก loadbalancer-controller และสามารถพล็อตความแตกต่างระหว่างสถานะ VPP ปัจจุบันและสถานะเป้าหมายที่ได้รับจากคอนโทรลเลอร์ได้ เราได้รับระบบปิด: เหตุการณ์จาก API มาที่ตัวควบคุมบาลานเซอร์ ซึ่งมอบหมายงานให้กับตัวควบคุมการตรวจสุขภาพเพื่อตรวจสอบ "ความมีชีวิตชีวา" ของทรัพยากร ในทางกลับกัน จะมอบหมายงานให้กับโหนดตรวจสุขภาพและรวบรวมผลลัพธ์ หลังจากนั้นจะส่งงานกลับไปยังตัวควบคุมบาลานเซอร์ Loadbalancer-node สมัครรับเหตุการณ์จากคอนโทรลเลอร์และเปลี่ยนสถานะของ VPP ในระบบดังกล่าว แต่ละบริการจะรู้เฉพาะสิ่งที่จำเป็นสำหรับบริการใกล้เคียงเท่านั้น จำนวนการเชื่อมต่อมีจำกัด และเรามีความสามารถในการดำเนินการและปรับขนาดส่วนต่างๆ ได้อย่างอิสระ

สถาปัตยกรรมของตัวโหลดบาลานเซอร์เครือข่ายใน Yandex.Cloud

หลีกเลี่ยงปัญหาอะไรบ้าง?

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

ปัญหาและแนวทางแก้ไข

อะไรทำงานได้ไม่ดีนัก? Go มีการจัดการหน่วยความจำอัตโนมัติ แต่หน่วยความจำรั่วยังคงเกิดขึ้น วิธีที่ง่ายที่สุดในการจัดการกับพวกมันคือเรียกใช้ goroutines และอย่าลืมยุติพวกมัน Takeaway: ดูการใช้หน่วยความจำของโปรแกรม Go ของคุณ ตัวบ่งชี้ที่ดีมักเป็นจำนวนโกรูทีน มีข้อดีในเรื่องนี้: ใน Go การรับข้อมูลรันไทม์เป็นเรื่องง่าย เช่น การใช้หน่วยความจำ จำนวนกอร์รูทีนที่ทำงานอยู่ และพารามิเตอร์อื่นๆ อีกมากมาย

นอกจากนี้ Go อาจไม่ใช่ตัวเลือกที่ดีที่สุดสำหรับการทดสอบการทำงาน สิ่งเหล่านี้ค่อนข้างละเอียด และวิธีการมาตรฐานในการ "เรียกใช้ทุกอย่างใน CI เป็นกลุ่ม" นั้นไม่เหมาะกับพวกเขามากนัก ความจริงก็คือการทดสอบการทำงานต้องใช้ทรัพยากรมากกว่าและทำให้เกิดการหมดเวลาจริง ด้วยเหตุนี้ การทดสอบอาจล้มเหลวเนื่องจาก CPU ไม่ว่างกับการทดสอบหน่วย สรุป: หากเป็นไปได้ ให้ทำการทดสอบ "หนัก" แยกจากการทดสอบหน่วย 

สถาปัตยกรรมเหตุการณ์ไมโครเซอร์วิสมีความซับซ้อนมากกว่าเสาหิน: การรวบรวมบันทึกบนเครื่องที่แตกต่างกันหลายสิบเครื่องนั้นไม่สะดวกนัก สรุป: หากคุณสร้างไมโครเซอร์วิส ให้คิดถึงการติดตามทันที

แผนของเรา

เราจะเปิดตัวบาลานเซอร์ภายใน, บาลานเซอร์ IPv6, เพิ่มการรองรับสคริปต์ Kubernetes, แบ่งส่วนบริการของเราต่อไป (ขณะนี้มีเพียงโหนด healthcheck-node และ healthcheck-ctrl เท่านั้นที่ถูกแบ่งส่วน), เพิ่มการตรวจสุขภาพใหม่ และใช้การรวมการตรวจสอบอย่างชาญฉลาดด้วย เรากำลังพิจารณาถึงความเป็นไปได้ในการทำให้บริการของเรามีความเป็นอิสระมากยิ่งขึ้น เพื่อไม่ให้บริการสื่อสารถึงกันโดยตรง แต่ใช้คิวข้อความ บริการที่เข้ากันได้กับ SQS ได้ปรากฏบนคลาวด์เมื่อเร็ว ๆ นี้ คิวข้อความยานเดกซ์.

เมื่อเร็ว ๆ นี้ Yandex Load Balancer ได้เปิดตัวสู่สาธารณะแล้ว สำรวจ เอกสาร ในการบริการ จัดการบาลานเซอร์ในวิธีที่สะดวกสำหรับคุณ และเพิ่มความทนทานต่อความเสียหายของโครงการของคุณ!

ที่มา: will.com

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