Score:0

การถ่ายโอนไฟล์ tmp ขนาดใหญ่ค้างในพร็อกซี nginx php-fpm

ธง cn

เรามีเซิร์ฟเวอร์ที่ทำงานบนไซต์ WordPress ที่มี nginx stack ที่ติดตั้งบน Ubuntu 20 LTS

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

สำหรับกรณีการใช้งานของเรา เราจำเป็นต้องอนุญาตให้อัปโหลดได้สูงสุด 50GB ซึ่งเราทำงานได้อย่างไม่มีปัญหาในสภาพแวดล้อมการจัดเตรียมที่รัน LAMP stack มาตรฐาน เราไม่มีปัญหากับไฟล์ที่มีขนาดต่ำกว่า ~2GB แต่สิ่งใดก็ตามที่อาจล้มเหลวหรือล้มเหลวตามเกณฑ์บางอย่างที่ฉันไม่สามารถติดตามได้ ในขณะที่แก้ไขปัญหาก่อนหน้านี้ เวลาที่การคัดลอกไฟล์หยุดดูเหมือนไม่มีกฎเกณฑ์ (โดยสำเร็จสูงสุด 10GB) แต่ด้วยการกำหนดค่าปัจจุบัน (ดูด้านล่าง) เวลาจะหยุดอย่างต่อเนื่องเมื่อ PHP ทีเอ็มพี ไฟล์ถึง 2GB

เมื่อเราอัปโหลดไฟล์ขนาดใหญ่มาก เราสามารถดูไฟล์ temp ที่เข้ามาใช้พื้นที่ดิสก์จนกว่าไฟล์ทั้งหมดจะอยู่ /mnt/tmp/[nginx_tmp_path] (ใช่ มีพื้นที่ว่างในดิสก์เหลือเฟือ) หลังจากนั้นเราจะเห็นไฟล์ถูกคัดลอกไปยัง php.ini ทีเอ็มพี เส้นทาง แต่หลังจากนั้นไม่กี่วินาที php.ini ทีเอ็มพี ไฟล์มีขนาดไม่ใหญ่ขึ้นและกระบวนการคัดลอกหยุดทำงาน ในที่สุด การหมดเวลาหนึ่งใน 600 วินาทีก็มาถึง และมีข้อผิดพลาดที่บันทึกไว้ (ดูด้านล่าง) ในภาพหน้าจอนี้ เราได้อัปโหลดเสร็จสมบูรณ์ (จากมุมมองของเบราว์เซอร์/ผู้ใช้ปลายทาง) ขนาด 14.8GB ที่ค้างอยู่บนการถ่ายโอนไฟล์ tmp ที่ขนาดประมาณ 2GB ไฟล์ PHP tmp หยุดเติบโต

เมื่อสิ้นสุดช่วงเวลา 600 วินาที จะอยู่ในบันทึกข้อผิดพลาดของ Apache:

(70008) ผลลัพธ์บางส่วนถูกต้อง แต่การประมวลผลไม่สมบูรณ์: [ไคลเอนต์ <MY_IP>] AH01075: เกิดข้อผิดพลาดในการส่งคำขอไปที่: (กำลังอ่านอินพุตกลุ่ม), ผู้อ้างอิง: https://<THE_URL>/wp-admin/media-new.php

และบันทึกข้อผิดพลาด nginx กล่าวว่า:

2512066#0: *9 อัปสตรีมหมดเวลา (110: การเชื่อมต่อหมดเวลา) ขณะส่งคำขอไปยังอัปสตรีม ไคลเอ็นต์: <MY_IP> เซิร์ฟเวอร์: <INTERNAL_IP> คำขอ: "POST /wp-admin/async-upload.php HTTP/ 2.0", อัปสตรีม: "http://127.0.0.1:81/wp-admin/async-upload.php", โฮสต์: "<THE_URL>", ผู้อ้างอิง: "https://<THE_URL>/wp-admin/ สื่อใหม่.php"

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

ด้วยการกำหนดค่าปัจจุบัน PHP ทีเอ็มพี ไฟล์จะเติบโตเป็น 2097152 KB เสมอ (อ้างอิงจาก ดู่ -a) ซึ่งทำให้ฉันเชื่อว่าฉันถึงขีดจำกัดขนาดไฟล์ในตัวที่ฉันยังไม่ได้เปิดเผยในตอนนี้

ตัวเลือกการกำหนดค่าเซิร์ฟเวอร์ nginx ที่เกี่ยวข้องคือ: ใน เซิร์ฟเวอร์ บริบท:

    proxy_connect_timeout 600;
    proxy_read_timeout 600;
    proxy_send_timeout 600;
    proxy_max_temp_file_size 51200m;

    fastcgi_connect_timeout 600;
    fastcgi_read_timeout 600;
    fastcgi_send_timeout 600;
    ปิด fastcgi_request_buffering;

    keepalive_timeout 600;
    send_timeout 600;

    client_max_body_size 0;
    client_body_temp_path /mnt/tmp;
    client_body_in_file_only สะอาด;

การกำหนดค่า VirtualHost ของ Apache:

    ส่วนหัว RequestReadTimeout=0 เนื้อหา=0
    หมดเวลา 3600
    ProxyTimeout 3600

และสุดท้าย config PHP:

memory_limit = -1
max_execution_time = 0
max_input_time = -1
post_max_size = 50G
upload_max_filesize = 50G
default_socket_timeout = -1

ฉันไม่รู้ว่าอะไรเป็นสาเหตุของอาการที่ฉันเห็นพอยน์เตอร์ใด ๆ ที่ชื่นชม!

หมายเหตุเพิ่มเติม: อาการดังกล่าวทำให้รู้สึกว่าไม่เกี่ยวข้อง แต่ในกรณีที่เป็น... ไซต์ทำงานผ่าน WP Rocket แต่ไม่มีบริการพร็อกซีภายนอกเช่น CloudFlare

อัปเดต: ฉันเพิ่มบรรทัดเหล่านี้ในการกำหนดค่า nginx:

    proxy_http_version 1.1;
    การเชื่อมต่อ proxy_set_header "";

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

อัพเดท 2: ฉันสามารถระบุได้อย่างชัดเจนว่าสิ่งนี้เป็นปัญหาในการส่งต่อของ ทีเอ็มพี ไฟล์ระหว่าง nginx และ php แต่ฉันไม่สามารถระบุสิ่งเฉพาะที่ทำให้กระบวนการหยุดทำงาน

เราสามารถข้าม nginx proxy และใช้เฉพาะ PHP เท่านั้น ทีเอ็มพี โดยเพิ่มบรรทัดเหล่านี้ในการกำหนดค่า nginx:

    ปิด proxy_buffering;
    ปิด proxy_request_buffering;

ด้วยการกำหนดค่านี้ ไฟล์จะเข้าไปโดยตรง /mnt/tmp/php<RND_STR> และเมื่อการอัปโหลดเสร็จสิ้น แอปพลิเคชันของเราจะเลือกไฟล์อย่างถูกต้อง ทีเอ็มพี และเสร็จสิ้นภารกิจ

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

นี่คือสิ่งที่เกิดขึ้น:

  1. ผู้ใช้อัปโหลดไฟล์ขนาดใหญ่ (50GB เป็นกรณีการใช้งานสูงสุดของเรา)
  2. ไฟล์มาถึงใน nginx ทีเอ็มพี ที่ตั้งไว้อย่างครบถ้วน
  3. มีความพยายามที่จะคัดลอกไฟล์จาก nginx ทีเอ็มพี เป็น PHP ทีเอ็มพี - กระบวนการคัดลอกจะหยุดทำงานภายในไม่กี่วินาทีโดยที่ไม่สามารถคาดเดาได้ แต่ระหว่าง 3GB และ 10GB [3b] ณ เวลานี้ เราสามารถเห็นทั้งสองอย่าง ทีเอ็มพี ไฟล์และ PHP ทีเอ็มพี ไฟล์มีจำนวนไบต์ที่ควรจะเติบโตจนกว่าจะเท่ากับขนาดของ nginx ทีเอ็มพี ไฟล์ แต่พวกเขาไม่ได้ทั้งสองไฟล์จะอยู่ตามเดิมจนกว่าจะครบเวลาหนึ่งใน 600 วินาที (ดูด้านบน) จากนั้นข้อผิดพลาดจะปรากฏขึ้นในไฟล์บันทึกและทั้งสองไฟล์ ทีเอ็มพี ไฟล์หายไป [3c] หากไฟล์มีขนาดต่ำกว่า 3GB ไฟล์จะทำงานทุกครั้ง หากไฟล์มีขนาดใหญ่กว่า 3GB บางครั้งไฟล์จะทำงานได้ แต่ไฟล์อื่นไม่สามารถใช้งานได้ ยิ่งไฟล์มีขนาดเล็กเท่าใด โอกาสในการทำงานก็จะยิ่งมากขึ้นเท่านั้น
  4. ข้าม nginx's ทีเอ็มพี ทำงานได้อย่างสมบูรณ์ตามที่คาดไว้ ยกเว้นว่าการอัปโหลดจะช้า

มีบางอย่างกำลังวางสายอย่างแน่นอนในระหว่าง ทีเอ็มพี การส่งต่อไฟล์ระหว่าง nginx และ PHP เมื่อไฟล์มีขนาดใหญ่อย่างน่าขยะแขยง และฉันก็อยากรู้ว่ามันคืออะไร

Michael Hampton avatar
cz flag
เป็นเรื่องที่น่าถามว่าทำไมแอปพลิเคชัน PHP จึงใช้เวลามากกว่า 600 วินาทีในการประมวลผลไฟล์
Chris Ostmo avatar
cn flag
ฉันเพิ่มการหมดเวลาทั้งหมดเนื่องจากคาดว่าการส่งต่อไฟล์ขนาด 50GB จะใช้เวลามากกว่าค่าเริ่มต้น 60 วินาที ไม่ใช่การประมวลผลของ PHP ที่จะหมดเวลา - การส่งไฟล์ temp จะทำให้พร็อกซีหมดเวลา ฉันยอมรับว่าเปิดกว้างเกินไปในการแสวงหาวิธีแก้ปัญหา
Chris Ostmo avatar
cn flag
... อย่างไรก็ตาม PHP ไม่ได้ใช้เวลา 600 วินาทีในการประมวลผลไฟล์ - มีบางอย่างที่ขัดขวางการคัดลอกไฟล์ในไม่กี่วินาที และ 600 วินาทีนั้นเป็นเพียงเวลาที่หยุดรอและแสดงข้อผิดพลาด แอปพลิเคชัน PHP ของเราไม่สามารถเริ่มทำงานกับไฟล์ได้จนกว่าจะย้ายออกจาก `tmp` ซึ่งไม่ใช่สถานะที่เรากำลังเข้าถึง (ขออภัย พยายามแก้ไขความคิดเห็นเดิมของฉัน แต่สายเกินไป)
Michael Hampton avatar
cz flag
อืม. ทั้งหมดที่ฉันสามารถบอกได้จากข้อผิดพลาดที่โพสต์คือ nginx ดูเหมือนจะส่งผ่านไปยัง Apache สำเร็จและ Apache ไม่สามารถส่งต่อไปยัง PHP สำหรับฉันสิ่งนี้ทำให้ผู้ต้องสงสัยหลักคือโค้ด PHP ที่จัดการการอัปโหลด คุณควรให้นักพัฒนาแอปมีส่วนร่วม แต่สิ่งอื่น ๆ ดูแปลก ๆ เล็กน้อย คุณได้ติดตั้งระบบไฟล์แยกต่างหากสำหรับไฟล์ชั่วคราวหรือไม่ พวกเขาเป็นระบบไฟล์ประเภทใด
Chris Ostmo avatar
cn flag
ฉันเป็นนักพัฒนาซอฟต์แวร์ และข้อผิดพลาดนี้เกิดขึ้นจากไดอะล็อกการอัปโหลดสื่อ WordPress ของวานิลลา ดังนั้นจึงไม่มีโค้ดใดๆ ที่เล่นที่นี่ซึ่งไม่ได้ใช้งานโดยผู้คนจำนวนมาก ไฟล์ไม่เคยเสร็จสิ้นการส่งต่อจาก tmp ของ nginx ไปยัง tmp ของ PHP ดังนั้นฉันจึงไม่เชื่อว่าแอปพลิเคชันอาจรบกวนได้ ใช่ โฟลเดอร์ `tmp` ติดตั้งอยู่บนพาร์ติชั่น ext4 ของมันเอง นอกจากนี้ พฤติกรรมที่เปลี่ยนไปเมื่อฉันเปลี่ยนการกำหนดค่าเซิร์ฟเวอร์ไม่สอดคล้องกับข้อผิดพลาดของแอปพลิเคชัน

โพสต์คำตอบ

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