Tomcat 7'den 8'e yükseltirken aynı sorunu yaşadım: önbellekle ilgili sürekli büyük günlük uyarıları.
1. Kısa Cevap
Bunu Context
xml öğenizin içine ekleyin $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" />
Yani varsayılan 10240
(10 mbyte) 'dır, bu nedenle bundan daha büyük bir boyut ayarlayın. Daha sonra uyarıların kaybolduğu optimum ayarları ayarlayın. Uyarıların yüksek trafik koşullarında geri gelebileceğini unutmayın.
1.1 Nedeni (kısa açıklama)
Sorun, Tomcat'in bu girişlerin TTL'sinden daha düşük önbellek girişleri nedeniyle hedef önbellek boyutuna ulaşamamasından kaynaklanıyor. Yani Tomcat'in süresi dolabilecek kadar önbellek girişi yoktu, çünkü bunlar çok yeniydi, bu yüzden yeterince önbellek boşaltamadı ve bu nedenle uyarılar çıktı.
Sorun Tomcat 7'de görünmedi çünkü Tomcat 7 bu durumda uyarı vermedi. (Size ve bana bildirilmeden önbellek ayarlarını kötü kullanmamıza neden oluyor.)
Önbelleğin boyutuna ve TTL'sine kıyasla görece kısa bir süre içinde kaynaklar için görece büyük miktarda HTTP isteği (genellikle statik) alırken sorun ortaya çıkar. Önbellek, boyutunun% 95'inden fazlasını yeni önbellek girişleriyle (önbellekte 5 saniyeden az anlamına gelir) maksimum değerine (varsayılan olarak 10mb) ulaşıyorsa, Tomcat'in denediği her webResource için bir uyarı mesajı alacaksınız önbelleğe yüklemek için.
1.2 İsteğe bağlı bilgiler
Çalışan bir sunucuda cacheMaxSize'ı yeniden başlatmadan ayarlamanız gerekiyorsa JMX'i kullanın.
En hızlı çözüm <Resources cachingAllowed="false" />
, önbelleği tamamen devre dışı bırakmak olacaktır: ancak bu yetersiz, bu nedenle az önce açıkladığım gibi cacheMaxSize değerini artırın.
2. Uzun Cevap
2.1 Arka plan bilgisi
Web Kaynağı , bir web uygulamasındaki bir dosya veya dizindir. Performans nedenleriyle Tomcat, Web Kaynaklarını önbelleğe alabilir. Statik kaynak önbelleği maksimum (toplamda bütün kaynaklar) varsayılan 10240 kbyte (10 Mbyte) gereğidir. WebResource istendiğinde (örneğin, statik bir görüntü yüklerken) önbelleğe bir webResource yüklenir ve buna önbellek girişi denir. Her önbellek girişinin bir TTL'si (yaşam süresi) vardır ve bu, önbellek girişinin önbellekte kalmasına izin verilen zamandır. TTL'nin süresi dolduğunda, önbellek girişi önbellekten kaldırılmaya uygun hale gelir. CacheTTL'nin varsayılan değeri 5000 milisaniyedir (5 saniye).
Önbelleğe alma hakkında söylenecek daha çok şey var, ancak bu sorunla ilgili değil.
2.2 Nedeni
Cache sınıfından alınan aşağıdaki kod , önbelleğe alma politikasını ayrıntılı olarak gösterir:
152 // İçerik önbelleğe alınmayacak, ancak yine de meta veri boyutuna ihtiyacımız var
153 uzun delta = cacheEntry. getSize ();
154 beden. addAndGet (delta);
156 ise (boyut. Get ()> maxSize) {
157 // Süreç kaynakları hız için sırasız. İşlem önbelleği
158 // verimlilik (daha genç girdiler daha eski
159 olanlardan // önce çıkarılabilir ) çünkü bu,
160 için kritik yolda olduğundan // istek işleme
161 uzun targetSize =
162 maxSize * (100 - TARGET_FREE_PERCENT_GET) / 100;
163 uzun newSize = evict (
164 . TargetSize, ResourceCache değerleri (). Yineleyici ());
165 if (newSize> maxSize) {
166 // Bu kaynak için yeterli alan oluşturulamıyor
167 // Önbellekten kaldır
168 removeCacheEntry (yol);
169 günlük. warn (sm. getString ("cache.addFail", yol));
170 }
171 }
Bir webResource yüklenirken, kod önbelleğin yeni boyutunu hesaplar. Hesaplanan boyut varsayılan maksimum boyuttan büyükse, önbelleğe alınmış birden fazla girişin kaldırılması gerekir, aksi takdirde yeni boyut maksimum boyutu aşacaktır. Bu nedenle kod, önbelleğin altında kalmak istediği boyut olan (optimum olarak), varsayılan olarak maksimumun% 95'i olan bir "targetSize" hesaplayacaktır. Bu targetSize'ye ulaşmak için, girişlerin önbellekten kaldırılması / çıkarılması gerekir. Bu, aşağıdaki kod kullanılarak yapılır:
215 özel uzun evict ( uzun targetSize, Iterator < CachedResource > iter) {
217 long now = System. currentTimeMillis ();
219 uzun newSize = boyut. get ();
221 while (newSize> targetSize && iter. HasNext ()) {
222 CachedResource resource = iter. sonraki ();
224 // Do TTL içinde kontrol edildikten şey süresi dolmaz
225 ise (kaynak. GetNextCheck ()> şimdi) {
226 devam et ;
227 }
229 // Girdiyi önbellekten kaldır
230 removeCacheEntry (resource. GetWebappPath ());
232 newSize = boyut. get ();
233 }
235 dönüş newSize;
236 }
Dolayısıyla, TTL'sinin süresi dolduğunda ve targetSize henüz ulaşılmadığında bir önbellek girişi kaldırılır.
Önbellek girişlerini kaldırarak önbelleği boşaltma girişiminden sonra, kod şunları yapacaktır:
165 if (newSize> maxSize) {
166 // Bu kaynak için yeterli alan oluşturulamıyor
167 // Önbellekten kaldır
168 removeCacheEntry (yol);
169 günlük. warn (sm. getString ("cache.addFail", yol));
170 }
Bu nedenle, önbelleği boşaltma girişiminden sonra, boyut yine de maksimum değeri aşarsa, serbest bırakılamama konusunda uyarı mesajı gösterecektir:
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 Sorun
Yani uyarı mesajının dediği gibi, sorun
süresi dolan önbellek girişlerini çıkardıktan sonra kullanılabilir boş alan yetersiz - önbelleğin maksimum boyutunu artırmayı düşünün
Web uygulamanız kısa bir süre (5 saniye) içinde çok sayıda önbelleğe alınmamış webResources (varsayılan olarak maksimum önbellek yaklaşık 10mb) yüklerse, uyarıyı alırsınız.
Kafa karıştıran kısım, Tomcat 7'nin uyarıyı göstermemesidir. Bunun nedeni basitçe bu Tomcat 7 kodudur:
1606 önbelleğe yeni bir girdi ekleyin //
1607 senkronize (cache) {
1608 çok büyük olursa // Kontrol önbellek boyutu ve kaldır elemanları
1609 ise ((önbelleği. Araması (isim) == boş ) && önbellek. Ayrılamadı (entry.size) ) {
1610 önbellek. yük (giriş);
1611 }
1612 }
ile kombine:
231 iken (mesleğini serbestçe> 0) {
232 ise (girişimlerini == maxAllocateIterations) {
233 // Vazgeç hiçbir değişiklik geçerli önbelleğe yapılan
234 dönüş FALSE ;
235 }
Bu yüzden Tomcat 7, önbelleği boşaltamadığında herhangi bir uyarı vermezken Tomcat 8 bir uyarı verir.
Dolayısıyla, Tomcat 8'i Tomcat 7 ile aynı varsayılan önbelleğe alma yapılandırmasıyla kullanıyorsanız ve Tomcat 8'de Tomcat 7'nin (ve benim) önbelleğe alma ayarlarınızın uyarı olmadan kötü performans gösterdiğinden farklı uyarılar aldıysanız.
2.4 Çözümler
Birden çok çözüm var:
- Önbelleği artır (önerilir)
- TTL'yi düşürün (önerilmez)
- Önbellek günlüğü uyarılarını bastır (önerilmez)
- Önbelleği devre dışı bırakın
2.4.1. Önbelleği artır (önerilir)
Burada açıklandığı gibi: http://tomcat.apache.org/tomcat-8.0-doc/config/resources.html
"XXXXX", kbayt cinsinden belirtilen artırılmış önbellek boyutunu ifade ettiği, <Resources cacheMaxSize="XXXXX" />
içindeki Context
öğenin içine eklenerek $CATALINA_BASE/conf/context.xml
. Varsayılan değer 10240'tır (10 mbyte), bu nedenle bundan daha büyük bir boyut ayarlayın.
Optimum ayarlar için ayarlamanız gerekecek. Trafik / kaynak isteklerinde aniden bir artış olduğunda sorunun geri gelebileceğini unutmayın.
Her yeni önbellek boyutunu denemek istediğinizde sunucuyu yeniden başlatmak zorunda kalmamak için, JMX kullanarak yeniden başlatmadan değiştirebilirsiniz.
İçin JMX etkinleştirmek için bu eklemek $CATALINA_BASE/conf/server.xml
içinde Server
eleman:
<Listener className="org.apache.catalina.mbeans.JmxRemoteLifecycleListener" rmiRegistryPortPlatform="6767" rmiServerPortPlatform="6768" />
ve indirme catalina-jmx-remote.jar
dan https://tomcat.apache.org/download-80.cgi ve koyun $CATALINA_HOME/lib
. Ardından sunucuya JMX üzerinden bağlanmak için jConsole'u (varsayılan olarak Java JDK ile birlikte gelir) kullanın ve sunucu çalışırken önbellek boyutunu artırmak için ayarlara bakın. Bu ayarlarda yapılan değişiklikler hemen yürürlüğe girmelidir.
2.4.2. TTL'yi düşürün (önerilmez)
Alt cacheTtl
optimum ayarları için düşük 5000 milisaniye daha bir şey tarafından değer ve ayar.
Örneğin: <Resources cacheTtl="2000" />
Bu, kullanmadan ram içinde bir önbelleğe sahip olmak ve onu doldurmak için etkili bir şekilde gelir.
2.4.3. Önbellek günlüğü uyarılarını bastır (önerilmez)
Günlükçüyü devre dışı bırakmak için günlük kaydını yapılandırın org.apache.catalina.webresources.Cache
.
Tomcat'te oturum açma hakkında daha fazla bilgi için: http://tomcat.apache.org/tomcat-8.0-doc/logging.html
2.4.4. Önbelleği devre dışı bırakın
Sen ayarlayarak önbelleği devre dışı bırakabilir cachingAllowed
içinfalse
.
<Resources cachingAllowed="false" />
Tomcat 8'in beta sürümünde bunu hatırlayabilsem de, önbelleği devre dışı bırakmak için JMX kullanıyordum. (Tam olarak neden olduğundan emin değilim, ancak önbelleğin server.xml aracılığıyla devre dışı bırakılmasıyla ilgili bir sorun olabilir.)