ฉันมีปัญหาเดียวกันเมื่ออัปเกรดจาก Tomcat 7 เป็น 8: คำเตือนบันทึกจำนวนมากอย่างต่อเนื่องเกี่ยวกับแคช
1. คำตอบสั้น ๆ
เพิ่มสิ่งนี้ภายในContext
องค์ประกอบ xml ของคุณ$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" />
ดังนั้นค่าเริ่มต้นคือ10240
(10 mbyte) ดังนั้นให้กำหนดขนาดให้สูงกว่านี้ กว่าปรับแต่งการตั้งค่าที่เหมาะสมที่สุดที่คำเตือนหายไป โปรดทราบว่าคำเตือนอาจกลับมาอีกครั้งภายใต้สถานการณ์การจราจรที่สูงขึ้น
1.1 สาเหตุ (คำอธิบายสั้น ๆ )
ปัญหาเกิดจาก Tomcat ไม่สามารถเข้าถึงขนาดแคชเป้าหมายได้เนื่องจากรายการแคชที่น้อยกว่า TTL ของรายการเหล่านั้น ดังนั้น Tomcat จึงไม่มีรายการแคชเพียงพอที่อาจหมดอายุได้เนื่องจากมันใหม่เกินไปจึงไม่สามารถเพิ่มแคชได้เพียงพอและส่งคำเตือนออกมา
ปัญหาไม่ปรากฏใน Tomcat 7 เนื่องจาก Tomcat 7 ไม่แสดงคำเตือนในสถานการณ์นี้ (ทำให้คุณและฉันใช้การตั้งค่าแคชที่ไม่ดีโดยไม่ได้รับแจ้ง)
ปัญหาจะปรากฏขึ้นเมื่อได้รับคำขอ HTTP จำนวนมากสำหรับทรัพยากร (โดยปกติจะเป็นแบบคงที่) ในช่วงเวลาสั้น ๆ เมื่อเทียบกับขนาดและ TTL ของแคช หากแคชมีขนาดถึงสูงสุด (10mb โดยค่าเริ่มต้น) โดยมีขนาดมากกว่า 95% พร้อมรายการแคชใหม่ (ใหม่หมายถึงน้อยกว่า 5 วินาทีในแคช) กว่าที่คุณจะได้รับข้อความเตือนสำหรับแต่ละ webResource ที่ Tomcat พยายาม เพื่อโหลดในแคช
1.2 ข้อมูลเพิ่มเติม
ใช้ JMX หากคุณต้องการปรับแต่ง cacheMaxSize บนเซิร์ฟเวอร์ที่รันอยู่โดยไม่ต้องรีบูตเครื่อง
การแก้ไขที่เร็วที่สุดคือการปิดการใช้งานแคชอย่างสมบูรณ์: <Resources cachingAllowed="false" />
แต่นั่นเป็นอันดับต่ำสุดดังนั้นให้เพิ่ม cacheMaxSize ตามที่ฉันอธิบายไว้
2. คำตอบแบบยาว
2.1 ข้อมูลความเป็นมา
WebSourceเป็นไฟล์หรือไดเรกทอรีในโปรแกรมประยุกต์บนเว็บ ด้วยเหตุผลด้านประสิทธิภาพ Tomcat สามารถแคช WebSources สูงสุดของแคชทรัพยากรแบบคงที่ (ทรัพยากรทั้งหมดในทั้งหมด) เป็นค่าเริ่มต้น 10240 กิโลไบต์ (10 Mbyte) webResource ถูกโหลดลงในแคชเมื่อมีการร้องขอ webResource (ตัวอย่างเช่นเมื่อโหลดภาพนิ่ง) จากนั้นเรียกว่ารายการแคช ทุกรายการแคชมีTTL (เวลาที่ใช้งานจริง) ซึ่งเป็นเวลาที่อนุญาตให้รายการแคชอยู่ในแคช เมื่อ TTL หมดอายุรายการแคชจะมีสิทธิ์ลบออกจากแคช ค่าเริ่มต้นของ cacheTTL คือ 5,000 มิลลิวินาที (5 วินาที)
มีข้อมูลเพิ่มเติมที่จะบอกเกี่ยวกับการแคช แต่ไม่เกี่ยวข้องกับปัญหา
2.2 สาเหตุ
รหัสต่อไปนี้จากคลาส Cacheจะแสดงนโยบายการแคชโดยละเอียด:
152 // เนื้อหาจะไม่ถูกแคช แต่เรายังต้องการข้อมูลเมตาขนาด
153 long delta = cacheEntry getSize (); ขนาด
154 . addAndGet (เดลต้า);
156 if (size. get ()> maxSize) {
157 // ประมวลผลทรัพยากรที่ไม่ได้เรียงลำดับเพื่อความรวดเร็ว เทรดแคช
158 // ประสิทธิภาพ (รายการที่อายุน้อยกว่าอาจถูกขับออกไปก่อนที่เก่ากว่า
159 // รายการ) เพื่อความรวดเร็วเนื่องจากนี่อยู่บนเส้นทางวิกฤตสำหรับ
160 // การประมวลผลคำขอ
161 เป้าหมายขนาดยาว =
162 maxSize * (100 - TARGET_FREE_PERCENT_GET) / 100;
163 newSize ยาว = ขับไล่ (
164 targetSize, resourceCache. values (). iterator ());
165 if (newSize> maxSize) {
166 // ไม่สามารถสร้างพื้นที่เพียงพอสำหรับทรัพยากรนี้
167 // ลบออกจากแคช
168 removeCacheEntry (เส้นทาง);
169 ล็อก เตือน (sm. getString ("cache.addFail", เส้นทาง));
170 }
171 }
เมื่อโหลด webResource โค้ดจะคำนวณขนาดใหม่ของแคช หากขนาดที่คำนวณได้ใหญ่กว่าขนาดสูงสุดเริ่มต้นจะต้องลบรายการแคชมากกว่าหนึ่งรายการขึ้นไปมิฉะนั้นขนาดใหม่จะเกินค่าสูงสุด ดังนั้นโค้ดจะคำนวณ "targetSize" ซึ่งเป็นขนาดที่แคชต้องการให้คงอยู่ (ตามค่าที่เหมาะสม) ซึ่งเป็นค่าเริ่มต้น 95% ของค่าสูงสุด ในการเข้าถึง targetSize นี้รายการจะต้องถูกลบ / ขับออกจากแคช ทำได้โดยใช้รหัสต่อไปนี้:
215 private longขับไล่ ( long targetSize, Iterator < CachedResource > iter) {
217 long now = System. currentTimeMillis (); ยาว
219 newSize = size. รับ (); 221 while (newSize> targetSize && iter. hasNext ()) { 222 CachedResource resource = iter. ถัดไป (); 224 // อย่าหมดอายุสิ่งที่ตรวจสอบภายใน TTL 225 if (resource. getNextCheck ()> now) { 226
ดำเนินการต่อ ;
227 }
229 // ลบรายการออกจากแคช
230 removeCacheEntry (resource. getWebappPath ());
232 newSize = ขนาด. รับ ();
233 }
235 ส่งคืน newSize;
236 }
ดังนั้นรายการแคชจะถูกลบออกเมื่อ TTL หมดอายุและยังไม่ถึง targetSize
หลังจากความพยายามในการเพิ่มแคชโดยการลบรายการแคชรหัสจะทำ:
165 if (newSize> maxSize) {
166 // ไม่สามารถสร้างพื้นที่เพียงพอสำหรับทรัพยากรนี้
167 // ลบออกจากแคช
168 removeCacheEntry (เส้นทาง);
169 ล็อก เตือน (sm. getString ("cache.addFail", เส้นทาง));
170 }
ดังนั้นหากหลังจากพยายามเพิ่มแคชแล้วขนาดยังเกินขีด จำกัด สูงสุดก็จะแสดงข้อความเตือนว่าไม่สามารถปล่อยให้ว่างได้:
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 ปัญหา
ดังที่ข้อความแจ้งเตือนปัญหาคือ
พื้นที่ว่างไม่เพียงพอหลังจากขับไล่รายการแคชที่หมดอายุ - ให้พิจารณาเพิ่มขนาดสูงสุดของแคช
หากเว็บแอปพลิเคชันของคุณโหลด webResources ที่ไม่ได้เชื่อมต่อจำนวนมาก (โดยประมาณสูงสุดของแคชโดยค่าเริ่มต้น 10mb) ภายในเวลาอันสั้น (5 วินาที) คุณจะได้รับคำเตือน
ส่วนที่สับสนคือ Tomcat 7 ไม่แสดงคำเตือน สิ่งนี้เกิดจากรหัส Tomcat 7 นี้:
1606 // เพิ่มรายการใหม่ไปยังแคช
1607 ที่ ซิงโครไนซ์ (แคช) {
1608 // ตรวจสอบขนาดแคชและลบองค์ประกอบหากใหญ่เกินไป
1609 ถ้า ((แคชค้นหา (ชื่อ) == null ) && แคชจัดสรร (รายการขนาด) ) {
1610 แคช โหลด (รายการ);
1611 }
1612 }
รวมกับ:
231 ในขณะที่ (toFree> 0) {
232 ถ้า (พยายาม == maxAllocateIterations) {
233 // ให้ขึ้นไม่มีการเปลี่ยนแปลงในปัจจุบันแคช
234 ผลตอบแทน เท็จ ;
235 }
ดังนั้น Tomcat 7 จึงไม่ส่งคำเตือนใด ๆ เลยเมื่อไม่สามารถเพิ่มแคชได้ในขณะที่ Tomcat 8 จะส่งคำเตือนออกมา
ดังนั้นหากคุณใช้ Tomcat 8 ด้วยการกำหนดค่าการแคชเริ่มต้นเดียวกันกับ Tomcat 7 และคุณได้รับคำเตือนใน Tomcat 8 การตั้งค่าการแคช (และของฉัน) ของ Tomcat 7 ทำงานได้ไม่ดีโดยไม่มีการเตือน
2.4 แนวทางแก้ไข
มีหลายวิธีแก้ไข:
- เพิ่มแคช (แนะนำ)
- ลด TTL (ไม่แนะนำ)
- ระงับคำเตือนบันทึกแคช (ไม่แนะนำ)
- ปิดการใช้งานแคช
2.4.1. เพิ่มแคช (แนะนำ)
ตามที่อธิบายไว้ที่นี่: http://tomcat.apache.org/tomcat-8.0-doc/config/resources.html
โดยการเพิ่ม<Resources cacheMaxSize="XXXXX" />
ภายในContext
องค์ประกอบใน$CATALINA_BASE/conf/context.xml
โดยที่ "XXXXX" หมายถึงขนาดแคชที่เพิ่มขึ้นระบุเป็นกิโลไบต์ ค่าเริ่มต้นคือ 10240 (10 mbyte) ดังนั้นกำหนดขนาดให้สูงกว่านี้
คุณจะต้องปรับแต่งการตั้งค่าที่เหมาะสม โปรดทราบว่าปัญหาอาจกลับมาเมื่อคุณมีคำขอปริมาณการใช้งาน / ทรัพยากรเพิ่มขึ้นอย่างกะทันหัน
เพื่อหลีกเลี่ยงการรีสตาร์ทเซิร์ฟเวอร์ทุกครั้งที่คุณต้องการลองขนาดแคชใหม่คุณสามารถเปลี่ยนได้โดยไม่ต้องรีสตาร์ทโดยใช้ JMX
ในการเปิดใช้งาน JMXให้เพิ่มสิ่งนี้$CATALINA_BASE/conf/server.xml
ในServer
องค์ประกอบ:
<Listener className="org.apache.catalina.mbeans.JmxRemoteLifecycleListener" rmiRegistryPortPlatform="6767" rmiServerPortPlatform="6768" />
และดาวน์โหลด catalina-jmx-remote.jar
จากhttps://tomcat.apache.org/download-80.cgiแล้วใส่ลง$CATALINA_HOME/lib
ไป จากนั้นใช้ jConsole (จัดส่งโดยค่าเริ่มต้นด้วย Java JDK) เพื่อเชื่อมต่อผ่าน JMX ไปยังเซิร์ฟเวอร์และดูการตั้งค่าสำหรับการตั้งค่าเพื่อเพิ่มขนาดแคชในขณะที่เซิร์ฟเวอร์กำลังทำงาน การเปลี่ยนแปลงการตั้งค่าเหล่านี้ควรมีผลทันที
2.4.2. ลด TTL (ไม่แนะนำ)
ลดcacheTtl
ค่าลงโดยสิ่งที่ต่ำกว่า 5,000 มิลลิวินาทีและปรับแต่งเพื่อการตั้งค่าที่เหมาะสมที่สุด
ตัวอย่างเช่น: <Resources cacheTtl="2000" />
สิ่งนี้มาพร้อมกับการมีและการเติมแคชใน ram โดยไม่ต้องใช้มัน
2.4.3. ระงับคำเตือนบันทึกแคช (ไม่แนะนำ)
org.apache.catalina.webresources.Cache
การเข้าสู่ระบบการกำหนดค่าการปิดการใช้งานสำหรับคนตัดไม้
สำหรับข้อมูลเพิ่มเติมเกี่ยวกับการเข้าสู่ระบบ Tomcat: http://tomcat.apache.org/tomcat-8.0-doc/logging.html
2.4.4. ปิดการใช้งานแคช
คุณสามารถปิดการแคชโดยการตั้งค่าไป
cachingAllowed
false
<Resources cachingAllowed="false" />
แม้ว่าฉันจะจำได้ว่าใน Tomcat 8 เวอร์ชันเบต้า แต่ฉันใช้ JMX เพื่อปิดการใช้งานแคช (ไม่แน่ใจว่าทำไมกันแน่ แต่อาจมีปัญหาในการปิดการใช้งานแคชผ่าน server.xml)