Đây là vấn đề mà tôi đã cố gắng theo dõi trong vài tháng nay. Tôi có một ứng dụng java đang chạy xử lý nguồn cấp dữ liệu xml và lưu trữ kết quả trong cơ sở dữ liệu. Đã có những vấn đề về tài nguyên không liên tục mà rất khó theo dõi.
Thông tin cơ bản: Trên hộp sản xuất (nơi vấn đề đáng chú ý nhất), tôi không có quyền truy cập đặc biệt tốt vào hộp và không thể chạy Jprofiler. Hộp đó là một máy 64bit lõi tứ, 8gb chạy centos 5.2, tomcat6 và java 1.6.0.11. Nó bắt đầu với những java-opt này
JAVA_OPTS="-server -Xmx5g -Xms4g -Xss256k -XX:MaxPermSize=256m -XX:+PrintGCDetails -
XX:+PrintGCTimeStamps -XX:+UseConcMarkSweepGC -XX:+PrintTenuringDistribution -XX:+UseParNewGC"
Công nghệ như sau:
- Centos 64-bit 5.2
- Java 6u11
- Tomcat 6
- Spring / WebMVC 2.5
- Ngủ đông 3
- Thạch anh 1.6.1
- DBCP 1.2.1
- Mysql 5.0.45
- Ehcache 1.5.0
- (và tất nhiên là một loạt các phụ thuộc khác, đặc biệt là các thư viện jakarta-commons)
Gần nhất tôi có thể tái tạo vấn đề là máy 32 bit có yêu cầu bộ nhớ thấp hơn. Điều đó tôi có quyền kiểm soát. Tôi đã kiểm tra nó đến chết với JProfiler và khắc phục nhiều vấn đề về hiệu suất (sự cố đồng bộ hóa, biên dịch trước / bộ nhớ đệm xpath truy vấn, giảm luồng và xóa tìm nạp trước ngủ đông không cần thiết và "làm nóng bộ nhớ cache" quá mức trong quá trình xử lý).
Trong mỗi trường hợp, trình mô tả cho thấy chúng chiếm một lượng lớn tài nguyên vì lý do này hay lý do khác, và chúng không còn là ổ chứa tài nguyên chính sau khi thay đổi diễn ra.
Vấn đề: JVM dường như hoàn toàn bỏ qua cài đặt sử dụng bộ nhớ, lấp đầy bộ nhớ và không phản hồi. Đây là vấn đề đối với khách hàng đang gặp phải, những người mong đợi một cuộc thăm dò thông thường (5 phút cơ bản và 1 phút thử lại), cũng như cho các nhóm vận hành của chúng tôi, những người liên tục được thông báo rằng một hộp không phản hồi và phải khởi động lại nó. Không có gì quan trọng khác chạy trên hộp này.
Vấn đề dường như là thu gom rác. Chúng tôi đang sử dụng bộ thu ConcurrentMarkSweep (như đã lưu ý ở trên) vì bộ thu STW ban đầu đã gây ra thời gian chờ của JDBC và ngày càng trở nên chậm hơn. Các bản ghi cho thấy rằng khi mức sử dụng bộ nhớ tăng lên, điều đó bắt đầu gây ra lỗi cms và quay trở lại bộ sưu tập dừng thế giới ban đầu, sau đó dường như không được thu thập đúng cách.
Tuy nhiên, khi chạy với jprofiler, nút "Run GC" dường như dọn dẹp bộ nhớ tốt hơn là hiển thị dấu vết ngày càng tăng, nhưng vì tôi không thể kết nối jprofiler trực tiếp với hộp sản xuất và việc giải quyết các điểm nóng đã được chứng minh dường như không hoạt động. còn lại với thói quen điều chỉnh Rác thải mù mịt.
Những gì tôi đã thử:
- Lập hồ sơ và sửa các điểm phát sóng.
- Sử dụng bộ thu gom rác STW, Parallel và CMS.
- Chạy với kích thước đống tối thiểu / tối đa ở mức tăng 1 / 2,2 / 4,4 / 5,6 / 6.
- Chạy với không gian permgen với gia số 256M lên đến 1Gb.
- Nhiều sự kết hợp của những điều trên.
- Tôi cũng đã tham khảo JVM [tham chiếu điều chỉnh] (http://java.sun.com/javase/technologies/hotspot/gc/gc_tuning_6.html), nhưng thực sự không thể tìm thấy bất kỳ điều gì giải thích hành vi này hoặc bất kỳ ví dụ nào về _which_ điều chỉnh tham số để sử dụng trong tình huống như thế này.
- Tôi cũng (không thành công) đã thử jprofiler ở chế độ ngoại tuyến, kết nối với jconsole, visualvm, nhưng dường như tôi không thể tìm thấy bất kỳ thứ gì xen vào dữ liệu nhật ký gc của tôi.
Thật không may, vấn đề cũng xuất hiện thường xuyên, nó dường như không thể đoán trước được, nó có thể chạy trong nhiều ngày hoặc thậm chí một tuần mà không gặp bất kỳ vấn đề nào hoặc có thể thất bại 40 lần trong một ngày và điều duy nhất tôi có thể nắm bắt một cách nhất quán là việc thu gom rác đang hoạt động.
Bất cứ ai có thể đưa ra bất kỳ lời khuyên nào về:
a) Tại sao một JVM sử dụng 8 hợp đồng biểu diễn vật lý và 2 gb không gian hoán đổi khi nó được định cấu hình để đạt tối đa ở mức nhỏ hơn 6.
b) Tham chiếu đến điều chỉnh GC thực sự giải thích hoặc đưa ra các ví dụ hợp lý về thời điểm và loại cài đặt nào để sử dụng các bộ sưu tập nâng cao.
c) Tham chiếu đến các lỗi rò rỉ bộ nhớ java phổ biến nhất (tôi hiểu các tham chiếu chưa được xác nhận quyền sở hữu, nhưng ý tôi là ở cấp thư viện / khung, hoặc một thứ gì đó khác trong mạng trong cấu trúc dữ liệu, như bản đồ băm).
Cảm ơn vì bất kỳ và tất cả thông tin chi tiết bạn có thể cung cấp.
CHỈNH SỬA
Emil H:
1) Có, cụm phát triển của tôi là một bản sao của dữ liệu sản xuất, cho máy chủ phương tiện. Sự khác biệt chính là 32 / 64bit và dung lượng RAM có sẵn, mà tôi không thể sao chép rất dễ dàng, nhưng mã và truy vấn và cài đặt giống hệt nhau.
2) Có một số mã kế thừa dựa trên JaxB, nhưng trong việc sắp xếp lại các công việc để cố gắng tránh xung đột lịch trình, tôi đã loại bỏ việc thực thi đó vì nó chạy mỗi ngày một lần. Trình phân tích cú pháp chính sử dụng các truy vấn XPath gọi xuống gói java.xml.xpath. Đây là nguồn gốc của một vài điểm nóng, đối với một truy vấn không được biên dịch trước và hai tham chiếu đến chúng ở dạng chuỗi mã cứng. Tôi đã tạo một bộ đệm threadsafe (hashmap) và tính toán các tham chiếu đến các truy vấn xpath thành các Chuỗi tĩnh cuối cùng, điều này đã giảm đáng kể mức tiêu thụ tài nguyên. Truy vấn vẫn là một phần lớn của quá trình xử lý, nhưng nó phải là vì đó là trách nhiệm chính của ứng dụng.
3) Một lưu ý bổ sung, người tiêu dùng chính khác là các thao tác hình ảnh từ JAI (xử lý lại hình ảnh từ nguồn cấp dữ liệu). Tôi không quen với các thư viện đồ họa của java, nhưng từ những gì tôi nhận thấy chúng không đặc biệt bị rò rỉ.
(cảm ơn vì những câu trả lời cho đến nay, mọi người!)
CẬP NHẬT:
Tôi đã có thể kết nối với phiên bản sản xuất bằng VisualVM, nhưng nó đã tắt tùy chọn GC visualization / run-GC (mặc dù tôi có thể xem nó cục bộ). Điều thú vị: Phân bổ heap của VM đang tuân theo JAVA_OPTS và heap được phân bổ thực tế đang ngồi thoải mái ở mức 1-1,5 hợp đồng biểu diễn và dường như không bị rò rỉ, nhưng theo dõi mức hộp vẫn cho thấy một mẫu rò rỉ, nhưng nó không được phản ánh trong giám sát VM. Không có gì khác đang chạy trên hộp này, vì vậy tôi bối rối.