Công việc cron thu gom rác của Ubuntu cho các phiên PHP mất 25 phút để chạy, tại sao?


13

Ubuntu có một công việc định kỳ được thiết lập để tìm và xóa các phiên PHP cũ:

# Look for and purge old sessions every 30 minutes
09,39 *     * * *     root   [ -x /usr/lib/php5/maxlifetime ] \
   && [ -d /var/lib/php5 ] && find /var/lib/php5/ -depth -mindepth 1 \
   -maxdepth 1 -type f -cmin +$(/usr/lib/php5/maxlifetime) ! -execdir \
   fuser -s {} 2> /dev/null \; -delete

Vấn đề của tôi là quá trình này mất rất nhiều thời gian để chạy, với rất nhiều đĩa IO. Đây là biểu đồ sử dụng CPU của tôi:

Biểu đồ sử dụng CPU

Việc dọn dẹp đang chạy được thể hiện bằng các gai nhọn. Vào đầu giai đoạn này, các công việc dọn dẹp của PHP đã được lên lịch vào mặc định 09 và 39 phút. Vào lúc 15:00, tôi đã loại bỏ thời gian 39 phút khỏi cron, vì vậy công việc dọn dẹp gấp đôi kích thước thường gấp rưỡi (bạn có thể thấy các đỉnh được tăng gấp đôi và gấp rưỡi thường xuyên).

Dưới đây là các biểu đồ tương ứng cho thời gian IO:

Thời gian IO

Và hoạt động của đĩa:

Hoạt động của đĩa

Vào lúc cao điểm có khoảng 14.000 phiên hoạt động, việc dọn dẹp có thể được xem là chạy đủ 25 phút, rõ ràng là sử dụng 100% một lõi của CPU và dường như là 100% IO của đĩa trong toàn bộ thời gian. Tại sao nó rất tốn tài nguyên? Một lsthư mục phiên /var/lib/php5chỉ mất một phần của giây. Vậy tại sao phải mất 25 phút để cắt các phiên cũ? Có bất cứ điều gì tôi có thể làm để tăng tốc độ này?

Hệ thống tập tin cho thiết bị này hiện đang là ext4, chạy trên Ubuntu Precise 12.04 64-bit.

EDIT: Tôi nghi ngờ rằng tải là do quá trình "fuser" bất thường (vì tôi mong đợi một đơn giản rmlà một cảnh tượng chết tiệt nhanh hơn hiệu suất tôi đang thấy). Tôi sẽ loại bỏ việc sử dụng bộ nhiệt áp và xem điều gì sẽ xảy ra.


Trang web của bạn có bao nhiêu lưu lượng truy cập để tạo ra nhiều phiên như vậy?
Michael Hampton

Câu trả lời:


9

Loại bỏ fusernên giúp đỡ. Công việc này chạy một fuserlệnh (kiểm tra xem một tệp hiện đang được mở) cho mỗi tệp phiên được tìm thấy , có thể dễ dàng mất vài phút trên một hệ thống bận rộn với 14k phiên. Đây là một lỗi Debian (Ubuntu dựa trên Debian).

Thay vì memcached, bạn cũng có thể thử sử dụng tmpfs (một hệ thống tệp trong bộ nhớ) cho các tệp phiên. Giống như memcached, điều này sẽ làm mất hiệu lực các phiên khi khởi động lại (điều này có thể được giải quyết bằng cách sao lưu thư mục này ở đâu đó trong tập lệnh tắt và khôi phục tập lệnh khởi động), nhưng sẽ dễ cài đặt hơn nhiều. Nhưng nó sẽ không giúp đỡ với fuservấn đề.


Nghe có vẻ như lỗi trong fuser là một phiên bản trước đó đã rẽ nhánh nhưng sau đó không bao giờ được gặt hái khi hoàn thành, khiến hàng ngàn fusertiến trình trong trạng thái tiêu thụ zombie, dẫn đến sự cố máy chủ. Tôi nghĩ rằng nó đã được sửa trong phiên bản psmisc mà tôi đang sử dụng.
thenickdude

Đó là một lỗi khác. Bạn có một vấn đề đơn giản là bắt đầu hàng ngàn fuserquy trình, tất cả đều phải tìm kiếm toàn bộ /proc/các tệp đang mở.
Tometzky

9

Chúc mừng bạn đã có một trang web phổ biến và quản lý để giữ cho nó chạy trên máy ảo trong tất cả thời gian này.

Nếu bạn đang thực sự kéo trong hai triệu lượt xem mỗi ngày, sau đó bạn sẽ chồng lên một LOT phiên PHP trong hệ thống tập tin, và họ sẽ phải mất một thời gian dài để xóa dù bạn sử dụng fuserhoặc rmhoặc một máy hút bụi.

Tại thời điểm này, tôi khuyên bạn nên tìm hiểu các cách khác để lưu trữ các phiên của mình:

  • Một lựa chọn là lưu trữ phiên trongmemcached . Điều này nhanh như chớp, nhưng nếu máy chủ gặp sự cố hoặc khởi động lại, tất cả các phiên của bạn sẽ bị mất và mọi người đều đăng xuất.
  • Bạn cũng có thể lưu trữ các phiên trong cơ sở dữ liệu. Điều này sẽ chậm hơn một chút so với memcached, nhưng cơ sở dữ liệu sẽ liên tục và bạn có thể xóa các phiên cũ bằng một truy vấn SQL đơn giản. Để thực hiện điều này, mặc dù, bạn phải viết một trình xử lý phiên tùy chỉnh .

Memcached chắc chắn là một tùy chọn, mặc dù nó sẽ phải là một nhóm riêng biệt với thể hiện memcached chính của chúng tôi, nếu không các phiên sẽ bị loại bỏ ngẫu nhiên khỏi áp lực bộ đệm của chúng tôi. Tuy nhiên, tôi không tin rằng việc xóa 14.000 tệp sẽ mất 25 phút. Điều đó nghe có vẻ quá chậm đối với tôi. Tôi sẽ đợi một vài giờ và xem hiệu suất của một đơn giản rmlà như thế nào.
thenickdude

Không biết nhiều hơn về kiến ​​trúc tổng thể của bạn, tôi ngần ngại giới thiệu cái này hơn cái kia.
Michael Hampton

Bạn có thể gộp các máy chủ Memcached để dự phòng bằng cách đặt memcache.session_redundancy = 2. Xem serverfault.com/questions/164350/ Lần . Redis là một lựa chọn tốt nếu bạn quan tâm đến sự kiên trì và nhanh hơn nhiều so với các cửa hàng cơ sở dữ liệu SQL.
jfenez

4

Vì vậy, các tùy chọn lưu trữ phiên Memcached và cơ sở dữ liệu được đề xuất bởi người dùng ở đây đều là những lựa chọn tốt để tăng hiệu suất, mỗi tùy chọn đều có những lợi ích và nhược điểm riêng.

Nhưng bằng cách thử nghiệm hiệu năng, tôi thấy rằng chi phí hiệu năng khổng lồ của việc bảo trì phiên này gần như hoàn toàn phụ fuserthuộc vào công việc định kỳ. Đây là biểu đồ hiệu suất sau khi hoàn nguyên công việc định kỳ Natty / Oneiric sử dụng rmthay vì fusercắt các phiên cũ, việc chuyển đổi xảy ra lúc 2:30.

Sử dụng CPU

Thời gian IO đã trôi qua

Hoạt động của đĩa

Bạn có thể thấy rằng sự suy giảm hiệu suất định kỳ do việc dọn dẹp phiên PHP của Ubuntu gần như bị xóa hoàn toàn. Các đột biến được hiển thị trong biểu đồ Hoạt động của đĩa bây giờ có độ lớn nhỏ hơn nhiều và có thể đo được bằng biểu đồ này, cho thấy sự gián đoạn nhỏ, ngắn trong đó hiệu suất máy chủ trước đó bị suy giảm đáng kể trong 25 phút. Việc sử dụng CPU bổ sung đã được loại bỏ hoàn toàn, đây hiện là một công việc ràng buộc IO.

(một công việc IO không liên quan chạy vào 05:00 và công việc CPU chạy lúc 7:40, cả hai đều gây ra đột biến của riêng chúng trên các biểu đồ này)

Công việc định kỳ đã sửa đổi mà tôi hiện đang chạy là:

09 *     * * *     root   [ -x /usr/lib/php5/maxlifetime ] && \
   [ -d /var/lib/php5 ] && find /var/lib/php5/ -depth -mindepth 1 \
   -maxdepth 1 -type f -cmin +$(/usr/lib/php5/maxlifetime) -print0 \
   | xargs -n 200 -r -0 rm

-print0 | xargs ...không cần thiết - bạn có thể chỉ cần rời khỏi -deleteđó. Nhưng nó sẽ hoạt động cả hai cách với tốc độ tương đương.
Tometzky

1

Tôi đã xem qua bài đăng này khi thực hiện một số nghiên cứu về các phiên. Mặc dù câu trả lời được chấp nhận là rất tốt (và cuộc gọi fuser đã bị xóa khỏi tập lệnh gc một thời gian) Tôi nghĩ rằng đáng chú ý một vài điều cần cân nhắc khác nếu bất kỳ ai khác gặp phải vấn đề tương tự.

Trong kịch bản được mô tả, OP đã sử dụng ext4. Các thư mục trong ext4 lưu trữ dữ liệu tệp theo định dạng cơ sở dữ liệu htree - có nghĩa là có tác động không đáng kể trong việc giữ nhiều tệp trong một thư mục so với phân phối chúng trên các thư mục mutlipl. Điều này không đúng với tất cả các hệ thống tập tin. Trình xử lý mặc định trong PHP cho phép bạn sử dụng nhiều thư mục con cho các tệp phiên (nhưng lưu ý rằng bạn nên kiểm tra xem quy trình kiểm soát có được đệ quy vào các thư mục đó không - công việc cron ở trên không).

Rất nhiều chi phí của hoạt động (sau khi loại bỏ cuộc gọi đến bộ nhiệt áp) phát sinh từ việc xem các tệp chưa cũ. Sử dụng (ví dụ) một cấp thư mục con duy nhất và 16 công việc định kỳ tìm kiếm trong mỗi thư mục con (0 /, 1 /, ... d /, e /, f /) sẽ giúp loại bỏ các va chạm tải phát sinh.

Sử dụng trình xử lý phiên tùy chỉnh với chất nền nhanh hơn sẽ giúp ích - nhưng có rất nhiều lựa chọn (memcache, redis, ổ cắm xử lý mysql ...) bỏ qua phạm vi chất lượng của những thứ được công bố trên internet, mà bạn chọn phụ thuộc vào chính xác các yêu cầu liên quan đến ứng dụng, cơ sở hạ tầng và kỹ năng của bạn, đừng quên rằng thường xuyên có sự khác biệt trong việc xử lý ngữ nghĩa (đáng chú ý là khóa) so với trình xử lý mặc định.


0

Với loại lưu lượng truy cập đó, bạn không nên đặt phiên trên một dis. Bạn nên sử dụng một cái gì đó như memcache. Tất cả bạn phải làm là thiết lập php và sẽ không cần thay đổi mã. Xem ví dụ

http://www.dotdeb.org/2008/08/08/storing-your-php-simes-USE-memcached/

Lý do nó mất quá nhiều thời gian là do số lượng tệp khổng lồ mà nó phải sắp xếp để xem những tệp nào có thể bị xóa. Memcache có thể tự động hết hạn những thời lượng phiên đã cho mà bạn đã đặt trong mã của mình.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.