Tomcat 8 ném - org.apache.catalina.webresources.Cache.getResource Không thể thêm tài nguyên


111

Tôi vừa nâng cấp Tomcat từ phiên bản 7.0.52 lên 8.0.14.

Tôi nhận được điều này cho rất nhiều tệp hình ảnh tĩnh:

org.apache.catalina.webresources.Cache.getResource Không thể thêm tài nguyên tại [/base/1325/WA6144-150x112.jpg] vào bộ nhớ cache vì không có đủ dung lượng trống sau khi loại bỏ các mục nhập bộ nhớ cache đã hết hạn - hãy xem xét tăng kích thước tối đa của bộ nhớ cache

Tôi chưa chỉ định bất kỳ cài đặt tài nguyên cụ thể nào và tôi không nhận được điều này cho 7.0.52.

Tôi đã tìm thấy đề cập đến điều này xảy ra khi khởi động trong một báo cáo lỗi được cho là đã được sửa. Đối với tôi, điều này xảy ra không phải khi khởi động mà liên tục khi tài nguyên được yêu cầu.

Bất kỳ ai khác có vấn đề này?

Cố gắng ít nhất chỉ vô hiệu hóa bộ nhớ cache, nhưng tôi không thể tìm thấy ví dụ về cách chỉ định không sử dụng bộ nhớ cache. Các thuộc tính đã biến mất khỏi ngữ cảnh trong Tomcat phiên bản 8. Đã thử thêm tài nguyên nhưng không thể cấu hình đúng.

<Resource name="file" 
    cachingAllowed="false"
    className="org.apache.catalina.webresources.FileResourceSet"
/>  

Cảm ơn.


Không có câu trả lời - Tôi đoán tôi phải là người duy nhất gặp vấn đề này.
iainmac999

2
Giải pháp là ở đây: serverfault.com/questions/644415/…
Dmitry

1
Về thuộc tính bị thiếu trong ngữ cảnh Tomcat 8, đây là một đoạn trích từ hướng dẫn di chuyển (mỏ nhấn mạnh): " Việc cấu trúc lại tài nguyên cũng dẫn đến một số thuộc tính bị xóa khỏi triển khai Ngữ cảnh mặc định (org.apache.catalina.core .StandardContext). Các thuộc tính sau có thể được định cấu hình thông qua việc triển khai tài nguyên được ứng dụng web sử dụng ". Thông tin thêm trong hướng dẫn di chuyển liên quan .
Informatik01

@ iainmac999 chưa bao giờ chọn một câu trả lời đúng sau 2 năm, chúng tôi có thể đồng ý rằng nó hoạt động theo cả hai cách?
davidjmcclelland Ngày

Câu trả lời:


161

Trong $CATALINA_BASE/conf/context.xmlkhối bổ sung của bạn bên dưới trước đây</Context>

<Resources cachingAllowed="true" cacheMaxSize="100000" />

Để biết thêm thông tin: http://tomcat.apache.org/tomcat-8.0-doc/config/resources.html


11
Người đọc cá nhân có thể sẽ muốn điều chỉnh giá trị cacheMaxSize đó thành giá trị nhỏ hơn 100 megs.
Eric Spiegelberg

cho đến nay thông báo lỗi đã tràn ngập nhật ký bảng điều khiển của tôi. Bây giờ nó rõ ràng. Cảm ơn
Abubacker Siddik

152

Tôi đã gặp vấn đề tương tự khi nâng cấp từ Tomcat 7 lên 8: một loạt các cảnh báo nhật ký liên tục về bộ nhớ cache.

1. Câu trả lời ngắn

Thêm điều này trong Contextphần tử xml của $CATALINA_BASE/conf/context.xml:

<!-- The default value is 10240 kbytes, even when not added to context.xml.
So increase it high enough, until the problem disappears, for example set it to 
a value 5 times as high: 51200. -->
<Resources cacheMaxSize="51200" />

Vì vậy, mặc định là 10240(10 mbyte), vì vậy hãy đặt kích thước cao hơn mức này. Điều chỉnh để có cài đặt tối ưu, nơi các cảnh báo biến mất. Lưu ý rằng các cảnh báo có thể quay lại trong các tình huống giao thông cao hơn.

1.1 Nguyên nhân (giải thích ngắn gọn)

Vấn đề là do Tomcat không thể đạt được kích thước bộ nhớ cache mục tiêu của nó do các mục nhập bộ nhớ cache nhỏ hơn TTL của các mục nhập đó. Vì vậy, Tomcat không có đủ các mục nhập bộ nhớ cache mà nó có thể hết hạn, vì chúng quá mới, vì vậy nó không thể giải phóng đủ bộ nhớ cache và do đó xuất ra các cảnh báo.

Sự cố không xuất hiện trong Tomcat 7 vì Tomcat 7 đơn giản là không xuất cảnh báo trong tình huống này. (Khiến bạn và tôi sử dụng cài đặt bộ nhớ đệm kém mà không được thông báo.)

Sự cố xuất hiện khi nhận được một lượng lớn tương đối các yêu cầu HTTP cho tài nguyên (thường là tĩnh) trong một khoảng thời gian ngắn tương đối so với kích thước và TTL của bộ nhớ cache. Nếu bộ nhớ cache đạt đến mức tối đa (10mb theo mặc định) với hơn 95% kích thước của nó với các mục nhập bộ nhớ cache mới (mới có nghĩa là ít hơn 5 giây trong bộ nhớ cache), bạn sẽ nhận được thông báo cảnh báo cho mỗi webResource mà Tomcat thử để tải vào bộ nhớ đệm.

1.2 Thông tin tùy chọn

Sử dụng JMX nếu bạn cần điều chỉnh cacheMaxSize trên một máy chủ đang chạy mà không cần khởi động lại nó.

Cách khắc phục nhanh nhất là vô hiệu hóa hoàn toàn bộ nhớ cache <Resources cachingAllowed="false" />:, nhưng điều đó là chưa tối ưu, vì vậy hãy tăng cacheMaxSize như tôi vừa mô tả.

2. Câu trả lời dài

2.1 Thông tin cơ bản

Một WebSource là một tập tin hoặc thư mục trong một ứng dụng web. Vì lý do hiệu suất, Tomcat có thể lưu WebSources vào bộ nhớ cache. Theo mặc định, tối đa của bộ đệm tài nguyên tĩnh (tổng số tài nguyên) là 10240 kbyte (10 mbyte). Một webResource được tải vào bộ nhớ cache khi webResource được yêu cầu (ví dụ: khi tải một hình ảnh tĩnh), khi đó nó được gọi là một mục nhập bộ nhớ cache. Mọi mục nhập bộ nhớ cache đều có TTL (thời gian tồn tại), là thời gian mục nhập bộ nhớ cache được phép lưu lại trong bộ nhớ cache. Khi TTL hết hạn, mục nhập bộ nhớ cache đủ điều kiện để được xoá khỏi bộ nhớ cache. Giá trị mặc định của cacheTTL là 5000 mili giây (5 giây).

Có nhiều điều để nói về bộ nhớ đệm, nhưng điều đó không liên quan đến vấn đề.

2.2 Nguyên nhân

Đoạn mã sau từ lớp Cache hiển thị chi tiết chính sách bộ nhớ đệm:

152   // Nội dung sẽ không được lưu vào bộ nhớ đệm nhưng chúng ta vẫn cần kích thước siêu dữ liệu 
153 long delta = cacheEntry. getSize ();
154 kích thước. addAndGet (delta);
156 nếu (kích thước. Lấy ()> MAXSIZE) {
157 nguồn // Process có thứ tự cho tốc độ. Bộ nhớ đệm giao dịch
158 // hiệu quả (các mục nhập trẻ hơn có thể bị loại bỏ trước các mục nhập cũ hơn
159 //) về tốc độ vì đây là đường dẫn quan trọng để xử lý yêu cầu
160 //
161 long targetSize =
162 maxSize * (100 - TARGET_FREE_PERCENT_GET) / 100;
163 dài newSize = đuổi (
164 . TargetSize, resourceCache giá trị (). Iterator ());
165 if (newSize> maxSize) {
166 // Không thể tạo đủ dung lượng cho tài nguyên này.
167 // Xóa nó khỏi bộ nhớ cache
168 removeCacheEntry (path);
169 nhật ký. cảnh báo (sm. getString ("cache.addFail", đường dẫn));
170 }
171 }

Khi tải một webResource, mã sẽ tính toán kích thước mới của bộ nhớ cache. Nếu kích thước được tính toán lớn hơn kích thước tối đa mặc định, thì phải xóa hơn một hoặc nhiều mục nhập được lưu trong bộ nhớ cache, nếu không kích thước mới sẽ vượt quá kích thước tối đa. Vì vậy, mã sẽ tính toán một "targetSize", là kích thước mà bộ nhớ cache muốn duy trì (như một mức tối ưu), theo mặc định là 95% của mức tối đa. Để đạt được targetSize này, các mục nhập phải được xóa / loại bỏ khỏi bộ đệm. Điều này được thực hiện bằng cách sử dụng mã sau:

215   private  long evict ( long targetSize, Iterator < CachedResource > iter) { 
217 long now = System. currentTimeMillis ();
219 dài newSize = kích thước. lấy ();
221 while (newSize> targetSize && iter. HasNext ()) {
222 CachedResource resource = iter. tiếp theo ();
224 // Không hết hạn bất kỳ thứ gì đã được kiểm tra trong TTL
225 if (resource. GetNextCheck ()> now) {
226 tiếp tục ;
227 }
229 // Xóa mục nhập khỏi bộ nhớ đệm
230 removeCacheEntry (resource. GetWebappPath ());
232 newSize = kích thước. lấy ();
233 }
235 trả về newSize;
236 }

Vì vậy, mục nhập trong bộ nhớ cache sẽ bị xóa khi TTL của nó hết hạn và targetSize vẫn chưa đạt được.

Sau khi cố gắng giải phóng bộ nhớ cache bằng cách loại bỏ các mục nhập bộ nhớ cache, mã sẽ thực hiện:

165   if (newSize> maxSize) { 
166 // Không thể tạo đủ dung lượng cho tài nguyên này.
167 // Xóa nó khỏi bộ nhớ cache
168 removeCacheEntry (path);
169 nhật ký. cảnh báo (sm. getString ("cache.addFail", đường dẫn));
170 }

Vì vậy, nếu sau khi cố gắng giải phóng bộ nhớ cache, kích thước vẫn vượt quá mức tối đa, nó sẽ hiển thị thông báo cảnh báo về việc không thể giải phóng:

cache.addFail=Unable to add the resource at [{0}] to the cache for web application [{1}] because there was insufficient free space available after evicting expired cache entries - consider increasing the maximum size of the cache

2.3 Vấn đề

Vì vậy, như thông báo cảnh báo cho biết, vấn đề là

không đủ dung lượng trống sau khi loại bỏ các mục nhập bộ nhớ cache đã hết hạn - hãy xem xét tăng kích thước tối đa của bộ nhớ cache

Nếu ứng dụng web của bạn tải nhiều webResources chưa được lưu trữ (khoảng tối đa bộ nhớ cache, theo mặc định là 10mb) trong một thời gian ngắn (5 giây), thì bạn sẽ nhận được cảnh báo.

Phần khó hiểu là Tomcat 7 không hiển thị cảnh báo. Điều này chỉ đơn giản là do mã Tomcat 7 này gây ra:

1606   // Thêm mục mới vào bộ nhớ cache 
1607 đồng bộ (cache) {
1608 kích thước bộ nhớ cache // Kiểm tra, và các yếu tố loại bỏ nếu quá lớn
1609 nếu ((cache. Lookup (tên) == rỗng ) && cache. Phân bổ (entry.size) ) {
1610 bộ nhớ cache. tải (nhập);
1611 }
1612 }

kết hợp với:

231   while (toFree> 0) { 
232 if (try == maxAllocateIterations) {
233 // Bỏ cuộc, không có thay đổi nào được thực hiện đối với bộ đệm hiện tại
234 return false ;
235 }

Vì vậy, Tomcat 7 chỉ đơn giản là không xuất ra bất kỳ cảnh báo nào khi nó không thể giải phóng bộ nhớ cache, trong khi Tomcat 8 sẽ xuất ra cảnh báo.

Vì vậy, nếu bạn đang sử dụng Tomcat 8 có cùng cấu hình bộ nhớ đệm mặc định như Tomcat 7 và bạn nhận được cảnh báo trong Tomcat 8, thì cài đặt bộ nhớ đệm của bạn (và của tôi) Tomcat 7 hoạt động kém mà không có cảnh báo.

2.4 Giải pháp

Có nhiều giải pháp:

  1. Tăng bộ nhớ đệm (khuyến nghị)
  2. Giảm TTL (không được khuyến nghị)
  3. Chặn cảnh báo nhật ký bộ nhớ cache (không được khuyến nghị)
  4. Vô hiệu hóa bộ nhớ cache

2.4.1. Tăng bộ nhớ đệm (khuyến nghị)

Như được mô tả ở đây: http://tomcat.apache.org/tomcat-8.0-doc/config/resources.html

Bằng cách thêm vào <Resources cacheMaxSize="XXXXX" />bên trong Contextphần tử $CATALINA_BASE/conf/context.xml, trong đó "XXXXX" là viết tắt của kích thước bộ nhớ cache tăng lên, được chỉ định bằng kbyte. Giá trị mặc định là 10240 (10 mbyte), vì vậy hãy đặt kích thước cao hơn kích thước này.

Bạn sẽ phải điều chỉnh các cài đặt tối ưu. Lưu ý rằng sự cố có thể quay trở lại khi bạn đột nhiên có sự gia tăng về lưu lượng / yêu cầu tài nguyên.

Để tránh phải khởi động lại máy chủ mỗi khi bạn muốn thử kích thước bộ nhớ cache mới, bạn có thể thay đổi nó mà không cần khởi động lại bằng cách sử dụng JMX.

Để kích hoạt JMX , hãy thêm nó vào $CATALINA_BASE/conf/server.xmlbên trong Serverphần tử: <Listener className="org.apache.catalina.mbeans.JmxRemoteLifecycleListener" rmiRegistryPortPlatform="6767" rmiServerPortPlatform="6768" />và tải xuống catalina-jmx-remote.jartừ https://tomcat.apache.org/download-80.cgi và đưa nó vào $CATALINA_HOME/lib. Sau đó, sử dụng jConsole (được vận chuyển theo mặc định với Java JDK) để kết nối qua JMX với máy chủ và xem qua cài đặt cho các cài đặt để tăng kích thước bộ nhớ cache trong khi máy chủ đang chạy. Những thay đổi trong các cài đặt này sẽ ảnh hưởng ngay lập tức.

2.4.2. Giảm TTL (không được khuyến nghị)

Giảm cacheTtlgiá trị thấp hơn 5000 mili giây và điều chỉnh để có cài đặt tối ưu.

Ví dụ: <Resources cacheTtl="2000" />

Điều này có hiệu quả phụ thuộc vào việc có và lấp đầy một bộ nhớ cache trong ram mà không sử dụng nó.

2.4.3. Chặn cảnh báo nhật ký bộ nhớ cache (không được khuyến nghị)

Định cấu hình ghi nhật ký để tắt trình ghi nhật ký cho org.apache.catalina.webresources.Cache.

Để biết thêm thông tin về cách đăng nhập Tomcat: http://tomcat.apache.org/tomcat-8.0-doc/logging.html

2.4.4. Vô hiệu hóa bộ nhớ cache

Bạn có thể tắt bộ nhớ cache bằng cách đặt cachingAllowedthành false. <Resources cachingAllowed="false" />

Mặc dù tôi có thể nhớ rằng trong phiên bản beta của Tomcat 8, tôi đã sử dụng JMX để tắt bộ nhớ cache. (Không chắc chắn lý do chính xác, nhưng có thể có sự cố khi tắt bộ nhớ cache qua server.xml.)


Tăng bộ nhớ cache? Tôi nghi ngờ nó sẽ hoạt động ... Tôi đã thấy điều này: private long maxSize = 10 * 1024 * 1024; trong nguồn. grepcode.com/file/repo1.maven.org/maven2/org.apache.tomcat/…
HoaPhan

bạn đã tìm thấy câu trả lời cho lý do tại sao tomcat8 tràn ngập cảnh báo bộ nhớ cache
PHP Avenger

@HoaPhan 10 * 1024 * 1024 là tổng cộng tối đa 10mb cho tất cả bộ nhớ cache. Tùy thuộc vào lưu lượng truy cập của ứng dụng web, điều này có thể đạt được trong vài giây. Tăng nó đủ xa, sẽ hiệu quả.
Devabc,

@PHPAvenger Tomcat 7 hoàn toàn không cảnh báo trong vị trí này, trong khi Tomcat 8 thì có, vì vậy nó có thể được coi là một tính năng cảnh báo. Vấn đề là nó cảnh báo không chỉ một lần, mà còn trên mọi yêu cầu tài nguyên vào bộ nhớ cache. Sẽ là một cải tiến nếu chỉ cảnh báo sau một khoảng thời gian nhất định hoặc truy cập mục tiêu bộ nhớ cache.
Devabc,

@Devabc câu trả lời hoàn hảo! Một SO cổ điển!
gaurav

9

Bạn có nhiều tài nguyên tĩnh hơn mà bộ nhớ cache có chỗ cho. Bạn có thể thực hiện một trong những cách sau:

  • Tăng kích thước của bộ nhớ cache
  • Giảm TTL cho bộ nhớ cache
  • Tắt bộ nhớ đệm

Để biết thêm chi tiết, hãy xem tài liệu về các tùy chọn cấu hình này.


1
Cảm ơn vì nhận xét. Tôi hiểu ý nghĩa của ngoại lệ và tất nhiên tôi đã đọc tài liệu mà bạn liên kết đến, tuy nhiên tôi không hiểu tại sao điều này sẽ thay đổi từ 7 thành 8 mà không có thay đổi cấu hình. Đó là, tại sao trình xử lý Tài nguyên Hệ thống Tệp mặc định sẽ khác từ 8 đến 7, mà không tham chiếu đến bất kỳ thay đổi nào và thật đáng ngờ rằng một lỗi khởi động đã được báo cáo và được cho là đã được sửa.
iainmac999,

1
Có lẽ nếu bạn đã đọc hướng dẫn di chuyển - cụ thể là tomcat.apache.org/migration-8.html#Web_application_resources - thì mọi thứ sẽ rõ ràng hơn.
Mark Thomas

Sẽ hữu ích nếu tài liệu hướng dẫn thêm một chút về a) giải thích những tài nguyên nào đi vào bộ nhớ cache này và tại sao (rất nhiều hiểu lầm về điều đó!) Và b) những cài đặt khác nhau có thể có tác động gì (ví dụ: chỉ tạo cài đặt bộ nhớ cache của mỗi ứng dụng web một cách mù quáng khá lớn có thể ăn một tấn bộ nhớ) và làm thế nào để điều chỉnh điều này đúng cách. Nó cũng sẽ hữu ích nếu có sự khác biệt về mã và cấu hình giữa tài nguyên tĩnh trong bộ đệm được sử dụng bởi chính ứng dụng so với các tệp tĩnh do tác nhân người dùng yêu cầu và chỉ được ứng dụng phân phối.
volkerk

4

Đây không phải là một giải pháp theo nghĩa là nó không giải quyết các điều kiện khiến thông báo xuất hiện trong nhật ký, nhưng thông báo có thể bị chặn bằng cách thêm các điều sau vào conf/logging.properties:

org.apache.catalina.webresources.Cache.level = SEVERE

Thao tác này sẽ lọc ra các nhật ký “Không thể thêm tài nguyên” ở cấp CẢNH BÁO.

Theo quan điểm của tôi, a WARNINGkhông nhất thiết là một lỗi cần được giải quyết, mà có thể được bỏ qua nếu muốn.


8
Haha. điều này không giải quyết được vấn đề. Nó chỉ không hiển thị nó. WTF!
T3rm1

Điều này giải quyết vấn đề ghi nhật ký quá mức, đây có thể là một vấn đề nghiêm trọng của riêng nó. Nó quay trở lại hành vi của các phiên bản tomcat trước đó, nơi mọi thứ hoạt động đủ tốt cho nhiều người, vì vậy theo nghĩa đó, nó "giải quyết" vấn đề. Nó không giải quyết vấn đề thực sự điều chỉnh bộ nhớ cache của tomcat, mà câu trả lời của devabc đề cập rất tốt.
volkerk
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.