ฟากาปอฟ ฟ้ายอดนิยม

ฟากาปอฟ ฟ้ายอดนิยม

ทั้งหมดดี! 

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

คำนำ

นานมาแล้ว เมื่อ Cian ประกอบด้วยหินใหญ่ก้อนเดียว และยังไม่มีคำแนะนำเกี่ยวกับไมโครเซอร์วิส เราวัดความพร้อมใช้งานของทรัพยากรโดยการตรวจสอบ 3-5 หน้า 

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

หน้าหลักของเว็บไซต์หรือวิธีที่เราเข้าใจว่าเราถึงจุดต่ำสุดแล้ว

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

สมมติว่าเราพบว่ามีส่วนสำคัญอย่างยิ่งหลายส่วนในไซต์ที่รับผิดชอบบริการหลัก นั่นคือ การค้นหาและส่งโฆษณา หากจำนวนคำขอที่ล้มเหลวเกิน 1% นี่เป็นเหตุการณ์ร้ายแรง หากภายใน 15 นาทีในช่วงเวลาไพรม์ไทม์ อัตราข้อผิดพลาดเกิน 0,1% ก็ถือเป็นเหตุการณ์วิกฤติเช่นกัน เกณฑ์เหล่านี้ครอบคลุมเหตุการณ์ส่วนใหญ่ ส่วนที่เหลืออยู่นอกเหนือขอบเขตของบทความนี้

ฟากาปอฟ ฟ้ายอดนิยม

เหตุการณ์ที่ดีที่สุดยอดนิยม Cian

ดังนั้นเราจึงได้เรียนรู้ที่จะระบุข้อเท็จจริงของเหตุการณ์ที่เกิดขึ้นอย่างแน่นอน 

ตอนนี้ทุกเหตุการณ์ได้รับการอธิบายอย่างละเอียดและสะท้อนให้เห็นในมหากาพย์จิระ อย่างไรก็ตาม: สำหรับสิ่งนี้เราได้เริ่มโปรเจ็กต์แยกต่างหากเรียกว่า FAIL - มีเพียงมหากาพย์เท่านั้นที่สามารถสร้างได้ 

หากคุณรวบรวมความล้มเหลวทั้งหมดในช่วงไม่กี่ปีที่ผ่านมา ผู้นำได้แก่: 

  • เหตุการณ์ที่เกี่ยวข้องกับ mssql;
  • เหตุการณ์ที่เกิดจากปัจจัยภายนอก
  • ข้อผิดพลาดของผู้ดูแลระบบ

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

อันดับที่ห้า - “วางสิ่งต่าง ๆ ตามลำดับใน DNS”

มันเป็นวันอังคารที่มีพายุ เราตัดสินใจกู้คืนคำสั่งซื้อในคลัสเตอร์ DNS 

ฉันต้องการถ่ายโอนเซิร์ฟเวอร์ DNS ภายในจากการเชื่อมโยงไปยัง powerdns โดยจัดสรรเซิร์ฟเวอร์ที่แยกจากกันโดยสิ้นเชิงสำหรับสิ่งนี้ โดยที่ไม่มีอะไรนอกจาก DNS 

เราวางเซิร์ฟเวอร์ DNS หนึ่งเครื่องไว้ในแต่ละตำแหน่งของ DC ของเรา และถึงเวลาแล้วที่ต้องย้ายโซนจากการเชื่อมโยงไปยัง powerdns และเปลี่ยนโครงสร้างพื้นฐานไปยังเซิร์ฟเวอร์ใหม่ 

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

สรุป:

หากก่อนหน้านี้เราละเลยปัจจัยภายนอกในการเตรียมตัวทำงาน ตอนนี้ก็รวมอยู่ในรายการสิ่งที่เรากำลังเตรียมการด้วย และตอนนี้เรามุ่งมั่นที่จะตรวจสอบให้แน่ใจว่าส่วนประกอบทั้งหมดถูกสงวนไว้ n-2 และในระหว่างทำงานเราสามารถลดระดับนี้เป็น n-1 ได้

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

อันดับที่สี่ - “วางสิ่งต่าง ๆ ตามลำดับใน Nginx”

วันหนึ่ง ทีมของเราตัดสินใจว่า "เราพอแล้ว" และกระบวนการปรับเปลี่ยนการกำหนดค่า nginx ก็เริ่มต้นขึ้น เป้าหมายหลักคือการนำการกำหนดค่ามาสู่โครงสร้างที่ใช้งานง่าย ก่อนหน้านี้ ทุกอย่าง "ได้รับการสถาปนาตามประวัติศาสตร์" และไม่มีตรรกะใดๆ ตอนนี้แต่ละ server_name ได้ถูกย้ายไปยังไฟล์ชื่อเดียวกันและการกำหนดค่าทั้งหมดได้ถูกกระจายไปยังโฟลเดอร์แล้ว อย่างไรก็ตาม การกำหนดค่าประกอบด้วย 253949 บรรทัดหรือ 7836520 อักขระ และใช้พื้นที่เกือบ 7 เมกะไบต์ โครงสร้างระดับบนสุด: 

โครงสร้าง Nginx

├── access
│   ├── allow.list
...
│   └── whitelist.conf
├── geobase
│   ├── exclude.conf
...
│   └── geo_ip_to_region_id.conf
├── geodb
│   ├── GeoIP.dat
│   ├── GeoIP2-Country.mmdb
│   └── GeoLiteCity.dat
├── inc
│   ├── error.inc
...
│   └── proxy.inc
├── lists.d
│   ├── bot.conf
...
│   ├── dynamic
│   └── geo.conf
├── lua
│   ├── cookie.lua
│   ├── log
│   │   └── log.lua
│   ├── logics
│   │   ├── include.lua
│   │   ├── ...
│   │   └── utils.lua
│   └── prom
│       ├── stats.lua
│       └── stats_prometheus.lua
├── map.d
│   ├── access.conf
│   ├── .. 
│   └── zones.conf
├── nginx.conf
├── robots.txt
├── server.d
│   ├── cian.ru
│   │   ├── cian.ru.conf
│   │   ├── ...
│   │   └── my.cian.ru.conf
├── service.d
│   ├── ...
│   └── status.conf
└── upstream.d
    ├── cian-mcs.conf
    ├── ...
    └── wafserver.conf

มันดีขึ้นมาก แต่ในกระบวนการเปลี่ยนชื่อและกระจายการกำหนดค่า บางส่วนมีส่วนขยายที่ไม่ถูกต้องและไม่รวมอยู่ในคำสั่ง include *.conf เป็นผลให้บางโฮสต์ไม่สามารถใช้งานได้และส่งคืน 301 ไปที่หน้าหลัก เนื่องจากรหัสตอบกลับไม่ใช่ 5xx/4xx จึงไม่ได้สังเกตเห็นทันที แต่เฉพาะในตอนเช้าเท่านั้น หลังจากนั้น เราเริ่มเขียนการทดสอบเพื่อตรวจสอบส่วนประกอบโครงสร้างพื้นฐาน

สรุป: 

  • วางโครงสร้างการกำหนดค่าของคุณอย่างถูกต้อง (ไม่ใช่แค่ nginx) และคิดทบทวนโครงสร้างตั้งแต่ระยะเริ่มต้นของโปรเจ็กต์ วิธีนี้จะทำให้ทีมเข้าใจได้มากขึ้น ซึ่งจะลด TTM ไปด้วย
  • เขียนการทดสอบสำหรับส่วนประกอบโครงสร้างพื้นฐานบางอย่าง ตัวอย่างเช่น: การตรวจสอบว่าคีย์ server_names ทั้งหมดให้สถานะที่ถูกต้อง + เนื้อความการตอบสนอง แค่มีสคริปต์ไม่กี่ตัวที่จะตรวจสอบฟังก์ชั่นพื้นฐานของส่วนประกอบก็เพียงพอแล้วเพื่อไม่ให้จำอย่างเมามันตอนตี 3 จะต้องตรวจสอบอะไรอีกบ้าง 

อันดับที่สาม - “พื้นที่ในคาสซานดราหมดทันใด”

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

วันหนึ่งพายุกระหน่ำ คลัสเตอร์เกือบจะกลายเป็นฟักทอง กล่าวคือ:

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

ฟากาปอฟ ฟ้ายอดนิยม

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

สรุป:

  • บนเซิร์ฟเวอร์ Cassandra ทั้งหมด ไม่ควรเกิน 60% ของพื้นที่ในแต่ละพาร์ติชัน 
  • ควรโหลดด้วย CPU ไม่เกิน 50%
  • คุณไม่ควรลืมเกี่ยวกับการวางแผนกำลังการผลิตและต้องคิดทบทวนสำหรับแต่ละส่วนประกอบโดยพิจารณาจากข้อมูลเฉพาะของมัน
  • ยิ่งมีโหนดในคลัสเตอร์มากเท่าไรก็ยิ่งดีเท่านั้น เซิร์ฟเวอร์ที่มีข้อมูลจำนวนเล็กน้อยจะถูกโอเวอร์โหลดเร็วขึ้น และคลัสเตอร์ดังกล่าวจะฟื้นคืนชีพได้ง่ายกว่า 

อันดับที่สอง - “ข้อมูลหายไปจากการจัดเก็บคีย์-ค่ากงสุล”

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

สรุป:

  • บริการที่ไม่ได้รับอนุญาตไม่ควรมีข้อมูลที่สำคัญต่อการดำเนินงานของไซต์ ตัวอย่างเช่น หากคุณไม่ได้รับอนุญาตใน ES จะเป็นการดีกว่าถ้าปฏิเสธการเข้าถึงในระดับเครือข่ายจากทุกที่ที่ไม่จำเป็น เหลือเฉพาะที่จำเป็นเท่านั้น และตั้งค่า action.destructive_requires_name: true ด้วย
  • ฝึกฝนกลไกการสำรองและกู้คืนของคุณล่วงหน้า ตัวอย่างเช่น สร้างสคริปต์ล่วงหน้า (เช่น ใน Python) ที่สามารถสำรองและกู้คืนได้

ที่หนึ่ง - “กัปตันไม่ชัดเจน” 

ในบางจุด เราสังเกตเห็นการกระจายโหลดที่ไม่สม่ำเสมอบนอัปสตรีม nginx ในกรณีที่มีเซิร์ฟเวอร์มากกว่า 10 เซิร์ฟเวอร์ในระบบแบ็กเอนด์ เนื่องจากข้อเท็จจริงที่ว่า Round-robin ส่งคำขอตั้งแต่วันที่ 1 ถึงอัปสตรีมสุดท้ายตามลำดับและการโหลด nginx แต่ละครั้งเริ่มต้นใหม่ อัปสตรีมแรกจะได้รับคำขอมากกว่าที่เหลือเสมอ ผลก็คือ พวกเขาทำงานช้าลงและทั้งไซต์ก็ประสบปัญหา สิ่งนี้เริ่มสังเกตเห็นได้ชัดเจนยิ่งขึ้นเมื่อปริมาณการรับส่งข้อมูลเพิ่มขึ้น การอัปเดต nginx เพื่อเปิดใช้งานการสุ่มไม่ทำงาน - เราจำเป็นต้องทำซ้ำรหัส lua จำนวนมากที่ไม่ได้นำไปใช้กับเวอร์ชัน 1.15 (ในขณะนั้น) เราต้องแพตช์ nginx 1.14.2 ของเรา โดยแนะนำการรองรับแบบสุ่ม วิธีนี้ช่วยแก้ปัญหาได้ จุดบกพร่องนี้ชนะหมวดหมู่ "กัปตันไม่ชัดเจน"

สรุป:

การสำรวจข้อบกพร่องนี้น่าสนใจและน่าตื่นเต้นมาก) 

  • จัดระเบียบการติดตามของคุณเพื่อช่วยให้คุณค้นหาความผันผวนดังกล่าวได้อย่างรวดเร็ว ตัวอย่างเช่น คุณสามารถใช้ ELK เพื่อตรวจสอบ rps ในแต่ละแบ็กเอนด์ของแต่ละอัปสตรีม ตรวจสอบเวลาตอบสนองจากมุมมองของ nginx ในกรณีนี้ สิ่งนี้ช่วยให้เราระบุปัญหาได้ 

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

ที่มา: will.com

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