2012-06-07 3 views
7

Я запускаю Tomcat7, сервер достаточно мощный, 8 ГБ оперативной памяти 8-ядерный.Управление памятью Tomcat

tomcat taking a LOT of memory for nothing ?

Моя проблема заключается в том, что память РЭС адресности выше и выше, пока сервер просто не отвечает, даже не называя OnOutOfMemoryError.

конфигурации Tomcat:

-Xms1024M 
-Xmx2048M 
-XX:PermSize=256m 
-XX:MaxPermSize=512m 
-XX:+UseConcMarkSweepGC 
-XX:OnOutOfMemoryError='/var/tomcat/conf/restart_tomcat.sh' 

информация Память:

Memory:  Non heap memory = 106 Mb (Perm Gen, Code Cache), 
Loaded classes = 14,055, 
Garbage collection time = 47,608 ms, 
Process cpu time = 4,296,860 ms, 
Committed virtual memory = 6,910 Mb, 
Free physical memory = 4,906 Mb, 
Total physical memory = 8,192 Mb, 
Free swap space = 26,079 Mb, 
Total swap space = 26,079 Mb 
Perm Gen memory: 88 Mb/512 Mb ++++++++++++ 
Free disk space: 89,341 Mb 

Память, используемая Tomcat не смотрит, что выше по сравнению с верхней командой.

app memory graph

Я также имел java.net.SocketException: No buffer space available при попытке подключиться к SMTP-серверу или при попытке подключиться к facebook серверам.

Я использую Hibernate, с C3P0 пула соединений с этой конфигурацией:

 <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> 
     <property name="hibernate.connection.url">jdbc:mysql://urldb/schema?autoReconnect=true</property> 
     <property name="hibernate.connection.username">username</property> 
     <property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property> 
     <property name="hibernate.connection.password"></property> 
     <property name="connection.characterEncoding">UTF-8</property> 

     <property name="hibernate.c3p0.acquire_increment">1</property> 
     <property name="hibernate.c3p0.idle_test_period">300</property> 
     <property name="hibernate.c3p0.timeout">5000</property> 
     <property name="hibernate.c3p0.max_size">50</property> 
     <property name="hibernate.c3p0.min_size">1</property> 
     <property name="hibernate.c3p0.max_statement">0</property> 
     <property name="hibernate.c3p0.preferredTestQuery">select 1;</property> 
     <property name="hibernate.connection.provider_class">org.hibernate.connection.C3P0ConnectionProvider</property> 

Я не мог найти что-нибудь ... кто-то есть намек, где я должен искать?

Спасибо!

[ОБНОВЛЕНИЕ 1] дамп кучи:

HEAP HISTOGRAM : 

class [C         269780 34210054 
class [B         5600 33836661 
class java.util.HashMap$Entry    221872 6212416 
class [Ljava.util.HashMap$Entry;   23797 6032056 
class java.lang.String      271170 5423400 
class org.hibernate.hql.ast.tree.Node  103588 4972224 
class net.bull.javamelody.CounterRequest 28809 2996136 
class org.hibernate.hql.ast.tree.IdentNode 23461 2205334 
class java.lang.Class      14677 2113488 
class org.hibernate.hql.ast.tree.DotNode 13045 1852390 
class [Ljava.lang.String;     48506 1335600 
class [Ljava.lang.Object;     12997 1317016 


Instance Counts for All Classes (excluding platform) : 

103588 instances of class org.hibernate.hql.ast.tree.Node 
33366 instances of class antlr.ANTLRHashString 
28809 instances of class net.bull.javamelody.CounterRequest 
24436 instances of class org.apache.tomcat.util.buf.ByteChunk 
23461 instances of class org.hibernate.hql.ast.tree.IdentNode 
22781 instances of class org.apache.tomcat.util.buf.CharChunk 
22331 instances of class org.apache.tomcat.util.buf.MessageBytes 
13045 instances of class org.hibernate.hql.ast.tree.DotNode 
10024 instances of class net.bull.javamelody.JRobin 
9084 instances of class org.apache.catalina.loader.ResourceEntry 
7931 instances of class org.hibernate.hql.ast.tree.SqlNode 

[ОБНОВЛЕНИЕ 2] server.xml:

<Connector port="8080" protocol="HTTP/1.1" 
       connectionTimeout="20000" 
       redirectPort="8443" 
       URIEncoding="UTF-8" 
       maxThreads="150" 
       minSpareThreads="25" 
       maxSpareThreads="75" 
       enableLookups="false" 
       acceptCount="1024" 
       server="unknown" 
       address="public_ip" 
    /> 

**** [ОБНОВЛЕНИЕ 3] Выход из лог-файлов: ****

2012-06-04 06:18:24,152 [http-bio-ip-8080-exec-3500] ERROR org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/api].[Jersey REST Service]- Servlet.ser 
vice() for servlet [Jersey REST Service] in context with path [/socialapi] threw exception 
java.net.SocketTimeoutException: Read timed out 

    at java.net.SocketInputStream.socketRead0(Native Method) 
    at java.net.SocketInputStream.read(SocketInputStream.java:129) 
    at org.apache.coyote.http11.InternalInputBuffer.fill(InternalInputBuffer.java:532) 
    at org.apache.coyote.http11.InternalInputBuffer.fill(InternalInputBuffer.java:501) 
    at org.apache.coyote.http11.InternalInputBuffer$InputStreamInputBuffer.doRead(InternalInputBuffer.java:563) 
    at org.apache.coyote.http11.filters.IdentityInputFilter.doRead(IdentityInputFilter.java:118) 
    at org.apache.coyote.http11.AbstractInputBuffer.doRead(AbstractInputBuffer.java:326) 
    at org.apache.coyote.Request.doRead(Request.java:422) 

[UPDATE 4] ServletContext

Я использую ServletContextListener в моем приложении к контроллерам и создание экземпляра сохранить ссылку с event.getServletContext().setAttribute. Эти контроллеры загружают конфигурации и переводы (88Mb в Перми).

Затем использовать базу данных я использую:

SessionFactory sf = dbManager.getSessionFactory(DatabaseManager.DB_KEY_DEFAULT); 
Session session = sf.openSession(); 
Transaction tx = null; 

try { 
    tx = session.beginTransaction(); 

    //Do stuuf 

    tx.commit(); 

} catch (Exception e){ 
    //Do something 
} finally { 
    session.close(); 
} 
  1. Может ли это быть источником утечки?
  2. Почему бы не использовать ручную транзакцию/сеанс и как бы вы это сделали?
+0

Когда сервер перестает отвечать на запросы, вы также должны получить дамп потока (см. Http://wiki.apache.org /tomcat/HowTo#How_do_I_obtain_a_thread_dump_of_my_running_webapp_.3F), чтобы узнать, что делает ваша JVM. Можете ли вы также разместить свою конфигурацию с сайта server.xml, сообщить нам о каких-либо функциях «отказанного соединения», включенных в вашем DBCP, а также сообщить нам, что ограничение файла ограничено для вашего процесса JVM? Что угодно в журналах - особенно logs/catalina.out (или везде, где идет stdout)? –

+0

Обновление 2: server.xml. Хорошо спасибо, я попробую jstack в следующий раз, когда он блокируется! в моем списке процессов mysql я вижу плату, ожидающую соединения, ничего странного. В журналах я поместил его в update 3 –

+0

В вашем приложении много HQL? Hibernate аннотации или xml? Являются ли конечные статики HQL? – ssedano

ответ

14

Try с этим параметром:

+XX:+HeapDumpOnOutOfMemoryError -XX:+HeapDumpPath=dump.log 

попробовать также с более низкой начальной памяти параметры -Xms.

Затем вы можете проверить дамп, чтобы узнать, была ли проблема распределением объектов.

Во время работы TRY

jps 

Это будет выводить все процессы Java, позволяет сказать, что Tomcat является PID 4444:

jmap -dump:format=b,file=heapdump 4444 

И

jhat heapdump 

Если вы бежите из памяти время выполнение jhat просто добавляет больше памяти. Оттуда вы можете проверить кучу своего заявления.

Еще один способ - включить статистику Hibernate, чтобы проверить, что вы не получаете больше объектов. Хотя это выглядит как полная сборка мусора, каждый час не должно быть проблемой (комната для этого лучше там).

-verbose:gc -Xloggc:/opt/tomcat/logs/gc.out -XX:+PrintGCDetails -XX:+PrintGCTimeStamps 

И GCViewer, например, взгляните на каждом пространстве памяти (ternured, Иден, оставшихся в живых, завивка).

Еще один удобный инструмент:

jstack 4444 > stack.txt 

Это будет получить полную трассировку стеки каждого потока выполняется внутри процесса Java с Pid 4444.

Имейте в виде, что вам нужна привилегия, если вы начали Tomcat, как root или другого пользователя.

jps 

не выводит процесс, который у вас нет, поэтому вы не можете подключиться к нему.

Поскольку я не знаю, о чем ваше приложение (и, следовательно, я не знаю его требований), 3 миллиона экземпляров выглядят как много.

С помощью Hibernate statistics вы можете увидеть, какие классы вы конкретно создаете.

Затем настройка пропорций вашего eden and ternured отбор мусора может быть более эффективной.

Новые экземпляры объектов идут в eden. Когда он заполняет мизерные триггеры gc. То, что не удалено, попадает в пространство оставшегося в живых. Когда это заполняется, он переходит в состояние. Полный gc будет возникать, когда ternured заполнен.

На этом снимке (что является неточным) я оставил в стороне String, которые стали интернированными и отображенными в памяти файлами (которые не находятся в куче). Посмотрите, какие классы вы создаете больше всего. Интенсивное использование String может привести к быстрому заполнению перм.

Я предполагаю, что вы это делаете, но используйте управляемую фабрику сеансов, такую ​​как Spring (если в вашем стеке) и избегайте ручного управления транзакциями и сеансами.

Имейте в виду, что объекты удаляются в GC, если к нему не относится объект. Таким образом, пока объект доступен в вашем приложении, объект остается.

Если ваш ServletContextListener инстанцирует контроллеры и хранится в событии getServletContext. Убедитесь, что вы полностью удалили ссылку после этого, если вы сохраните ссылку, объекты не будут удалены, так как они все еще доступны.

Если вы управляете своими собственными транзакциями и сеансом (это нормально, если вы не можете использовать фреймворк), вы должны иметь дело с обслуживанием кода и ошибками, которые, например, решили и улучшили Spring-tx.

Я лично воспользовался FOSS. Но, конечно, иногда вы не можете увеличить стек.

Если вы используете Hibernate, я бы посмотрел Spring-orm и Spring-tx для управления транзакциями и сеансом. Также взгляните на Hibernate patter Open Session In View.

+0

спасибо, я добавлю это и проверил кучу дампа (я проверил его с javamelody, он выглядит нормально и соответствует графику: Heap Classes: 4,367, экземпляры: 3,376,160, Kilo-Bytes: 372,020) –

+0

Спасибо, поскольку мой сервер работает нормально, теперь jstack дает «бесполезную» информацию, но я сделаю это, если произойдет замораживание снова со сценарием –

+0

Но если спящий режим был протекающим объектом, не остался ли он в «используемой памяти» приложения (например: org.hibernate.hql.ast.tree.Node \t 240,128 экземпляров 11 МБ)? –

2

Я также рекомендую вам загрузить Visual VM 1.3.3, установить все плагины и прикрепить его к PMID Tomcat, чтобы вы могли видеть, что происходит в реальном времени. Зачем ждать свалку потока? Он также расскажет вам процессор, потоки, все поколения кучи, какие объекты потребляют большую часть памяти и т. Д.

+0

, для этого ему нужно будет добавить начальные параметры. Также jmap откачивается по требованию. jvisualvm почти так же хорош и не загружается. -Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port = 9004 -Dcom.sun.management.jmxremote.ssl = false -Dcom.sun.management.jmxremote.authenticate = false – ssedano

+0

Я пробовал YourKit (который похож на Visual VM), к сожалению, не помог мне решить проблему (я мог бы использовать ее только в среде разработки), есть ли способ подключить ее на рабочих серверах? –

+0

Спасибо ssedano, но это означает, что вы открываете порт JMX как общедоступный, что я не могу себе представить –

Смежные вопросы