ฉันต้องเซิร์ฟเวอร์โปรแกรมที่ใช้เพิ่ม ASIO ต้องติดต่อกับหลายรายชื่อรั่วไหลออก เซิร์ฟเวอร์โปรแกรมวิ่งอยู่บนระบบลินุกซ์เซิร์ฟเวอร์และพวกลูกค้าประมวลผลเมื่อหน้าต่างบนพื้นที่ทำงาน.
ปัจจุบันออกแบบเป็นหลาย threaded ถึงแม้ว่ามันมีแค่คนเดียวที่เพิ่ม ASIO thead(ซึ่งวิ่ง boost::asio::io_context
). ที่เพิ่ม ASIO เธรดเป็นเพียงรับผิดชอบอ่านหนังสือเขียนและบาง infrequent กรุณาฝากข้อความ อ่านเสร็จแล้วใช้ boost::asio::async_read
แต่สำเนานผลลัพธ์จากข้อความนั่นอีกด้าสามารถทำงานการประมวณผลนี้ เขียนเสร็จแล้วใช้ boost::asio::write
แต่ข้อความที่ได้คัดลอกและส่งออกไปที่เพิ่ม ASIO เธรด
ภายใต้สถานการณ์ส่วนใหญ่เมื่อเป็นลูกค้าของ disconnects เพิ่ม ASIO ให้เกิดข้อผิดพลาดเกิดขึ้นระหว่างฉันปิดที่เกี่ยวข้องซ็อกเก็ตและคนอื่นซ็อกเกตอทำงานต่อไป แต่ถ้าเป็นลูกค้าของหน้าต่างบนพื้นที่ทำงานมีพลังงานล้มเหลวขณะ boost::asio::write
คือการเขียนกับพวกเขางั้นเพิ่มไม่ได้ตรวจจับเป็นปัญหาและนั้นแขวนอยู่บ boost::asio::write
. มันแกร่วอยู่มาเกือบ 20 นาทีบางครั้งแล้วโดยเซิร์ฟเวอร์ไม่สามารถสื่อสารกับลูกค้าระหว่างเวลานี้
จากสิ่งที่ฉันต้องอ่านออนไลน์นผู้เขียนเพิ่ม ASIO ไม่มีความตั้งใจขอแนะนำผู้หมดเวลาพารามิเตอร์. ฉันพยายามการตั้งค่า SO_SNDTIMEO ต้อง 5 วินาทีแต่นั่นมันไม่มีผลกระทบต่อที่เขียนเที่ยวด้วยกัน ตอนนี้ดีที่สุดของฉันเดาว่าต้องแก้ปัญหาคือต้องให้ทุกซ็อกเกตได้อีกด้าดังนั้นลูกค้าคนหนึ่งไม่สามารถไปลงที่ลูกค้าอีกคน มีอะไรดีขึ้นตัวเลือกมากกว่านี้? ถ้าฉันทำให้ทุกซ็อกเก็ตของเธรดมันหมายความว่าฉันจะต้องการ boost::asio::io_context
ต่อเธรดที่จะหลีกเลี่ยงการเขียนแขวนคอ?
แก้ไข:หลังจากเห็นคอมเมนท์ฉันพยายามเรียนซ้ำฟังก์ชันที่โทรมา boost::asio::write
กับ boost::asio::async_write
. ด้านล่างนี้ฉันต้องมีรหัสนั่นเป็นประยุกต์@item text character set สำหรับดังนั้นแต่ยังคงแสดงอะไรทั้งหมดนี้เปลี่ยนเป็น:
ในตอนแรงกับ boost::asio::write
:
inline void MessagingServer::writeMessage(
GuiSession* const a_guiSession,
const PB::Message& a_msg
) {
boost::asio::dispatch(m_guiIoIoContext, [this, a_guiSession, a_msg]() {
// I removed code that writes a_msg's bytes into m_guiIoWriteBuf
// and sets totalSize to simplify for SO
boost::system::error_code error;
boost::asio::write(a_guiSession->m_guiIoGsSocket, boost::asio::buffer(m_guiIoWriteBuf, totalSize), error);
if (UNLIKELY(error))
ERRLOG << a_guiSession->m_gsSessionId << " write failed: " << error.message();
});
}
Redone กับ boost::asio::async_write
:
inline void MessagingServer::writeMessage(
GuiSession* const a_guiSession,
const PB::Message& a_msg
) {
a_guiSession->m_tempMutex.lock();
boost::asio::dispatch(m_guiIoIoContext, [this, a_guiSession, a_msg]() {
// I removed code that writes a_msg's bytes into m_guiIoWriteBuf
// and sets totalSize to simplify for SO
boost::asio::async_write(
a_guiSession->m_guiIoGsSocket,
boost::asio::buffer(m_guiIoWriteBuf, totalSize),
[this, a_guiSession](const boost::system::error_code& a_error, std::size_t) {
if (UNLIKELY(a_error))
ERRLOG << a_guiSession->m_gsSessionId << " write failed: " << a_error.message();
a_guiSession->m_tempMutex.unlock();
}
);
});
}
ที่ล็อคนแนะนำในครั้งที่สอรหัสรับประกันเดียวที่โทรไป boost::asio::async_write
กำลังใช้งานอยู่ช่วงเวลา(ฉันรู้ว่าพวกมันมีมากกว่า performant วิธีที่จะทำแบบนี้แต่นี่มันง่ายกว่าสำหรับการทดสอบ). ทั้งสองของพวกนี้มีรหัสคนเดียวกับปัญหาของแขวนเพิ่ม ASIO ตอนที่ลูกค้าของมีพลังความล้มเหลว แต่พวกเขาแขวนคออยู่ในวิธีที่แตกต่างกันที่ asynchronous รหัสมันออนุญาตให้สำหรับเพิ่ม ASIO ต้องแสดงการกระทำอื่นๆก็ไม่ได้ต่อเขียนจนถึงแขวนหนึ่งได้เกิดข้อผิดพลาด
ระหว่างการทดลองแยกกันฉันพยายามการตั้งค่า SO_KEEPALIVE
แต่นั่นก็ไม่ได้แก้ปัญหาแขวนปัญหา