Khoảng một lần một tuần, nhưng đôi khi thậm chí một vài lần một ngày sau khi chạy tốt trong nhiều ngày, các trường hợp EC2 của tôi trở nên không phản hồi. Biểu đồ bộ nhớ của Munin kể một câu chuyện khá đơn giản: bộ nhớ được phân bổ cho "ứng dụng" bắt đầu phát triển và không dừng lại cho đến khi trao đổi được sử dụng đầy đủ và ví dụ được đưa xuống đầu gối một cách hiệu quả. Một biểu đồ tùy chỉnh khác cho thấy quá trình phát triển không ngừng là apache2.
Tôi chạy một thiết lập prefork Apache tiêu chuẩn với mod_php và một vài tập lệnh PHP. Như bạn có thể thấy trong biểu đồ bên dưới, một cái gì đó xảy ra sẽ kích hoạt các quá trình apache2 để bắt đầu tiêu thụ nhiều bộ nhớ hơn. Cành xanh đầu tiên tôi bắt kịp và khởi động lại Apache trước khi mọi thứ vượt quá tầm tay. Spike thứ hai đã xa hơn một chút và trường hợp phải được khởi động lại hoàn toàn.
Điều tôi đang tự hỏi là làm thế nào để gỡ lỗi này tốt nhất. Thiếu thiết lập PHP với FastCGI và để nó chạy trong các quy trình riêng của mình, cách tốt nhất để tìm hiểu xem đó là Apache hay sự kết hợp giữa PHP và mã của tôi gây ra việc sử dụng bộ nhớ quá mức? Các bạn sẽ làm những bước nào để theo dõi vấn đề này?
CẬP NHẬT: Tôi đã có thể theo dõi rò rỉ sau khi tham gia bước đi, như Matt đề xuất dưới đây.
Sau khi tìm thấy một quá trình apache2 đang tăng dần và liên tục trong bộ nhớ, tôi đã thêm một vài lệnh gọi error_log () vào tập lệnh PHP của mình, in ra tổng số RSS được sử dụng tại các điểm khác nhau trong quá trình thực thi (sử dụng đầu ra của ps). Tuy nhiên, điều đó hóa ra là sai lệch - trong khi có vẻ như RSS chỉ nhảy sau khi tập lệnh của tôi được thực thi, việc gỡ lỗi sau đó cho thấy đó không phải là trường hợp thực sự. Hãy cẩn thận!
May mắn thay, cuối cùng tất cả các cuộc gọi error_log () hóa ra đều hữu ích. Khi tôi kích hoạt strace ( strace -p <pid> -tt -o trace.log -s 256
), tôi thấy rằng với mỗi yêu cầu, quy trình đã phân bổ khoảng 400k bộ nhớ (tìm cuộc gọi hệ thống 'brk' và trừ tham số của cuộc gọi đầu tiên từ cuộc gọi cuối cùng - một số thường đến trong một cuộc gọi sau cái khác). Sau đó, tôi đã tìm kiếm cuộc gọi hệ thống 'ghi' gần đây nhất có chứa thông báo error_log () của tôi, thông báo cho tôi biết tại thời điểm nào trong tập lệnh mà bộ nhớ được phân bổ. Với một vài lệnh gọi error_log () được đặt một cách chiến lược hơn để xác định vị trí chính xác hơn, cuối cùng tôi đã tìm ra thủ phạm.
Bộ nhớ đã bị rò rỉ khi chúng tôi gọi curl_exec () từ tập lệnh PHP của chúng tôi. Một số mã curl liên quan đến việc xử lý kết nối SSL đang làm sai điều gì đó - sự rò rỉ đã biến mất khi tôi chuyển sang HTTP. Thay đổi của Curl tham chiếu một vài rò rỉ bộ nhớ SSL đã được sửa trong 7.19.5 (chúng tôi đã ở 7.18.2) vì vậy tôi sẽ thử tiếp theo.
Trong khi đó, tôi đang chạy với MaxRequestsPerChild rất thấp, điều đó giữ cho Apache nằm trong giới hạn hợp lý. Cảm ơn mọi người!