一、前因
一份大数据,在用户登录时生存新session,并存进去,而session timeout设为了5h
二、过程
1、找进程
root@rise-vm-244:/usr/local/resin/conf# jps 9613 WatchdogManager 17028 Jps 9660 Resin
2、找进程所属用户
ps -ef | grep 9660 www-data 9660 9613 7 00:33 ? 00:09:44 /usr/local/jrockit-R2
3、参看java命令相关参数
root@rise-vm-244:/usr/local/resin/conf# java -X -Xbootclasspath:<directories and zip/jar files separated by :> set search path for bootstrap classes and resources -Xbootclasspath/a:<directories and zip/jar files separated by :> append to end of bootstrap class path -Xbootclasspath/p:<directories and zip/jar files separated by :> prepend in front of bootstrap class path -Xgcprio:[throughput|pausetime|deterministic] sets priority for the garbage collector (gc) throughput optimizes the gc behavior to achieve optimal throughput (default in server mode) pausetime optimizes the gc behavior to achieve minimal pause times deterministic optimizes the gc behavior to ensure extremely short pause times and limit the total number of those pauses within a prescribed window (this feature requires a valid license)
root@rise-vm-244:/usr/local/resin/conf# jrcmd -h Usage: <jrockit pid> [<command> [<arguments>]] [-l] [-f file] or: -p or: -h <command> is a valid JRockit command. Try "help". If the pid is 0, commands will be sent to all JRockit processes. If no options are given, lists JRockit processes (same as -p). -l display the counters exposed by this process -f read and execute commands from the file -p list JRockit processes on the local machine -h this help
root@rise-vm-244:/usr/local/resin/conf# sudo -u www-data jrcmd 9660 help 9660: The following commands are available: kill_rmp_server start_rmp_server kill_management_server start_management_server checkjrarecording stopjrarecording startjrarecording print_object_summary memleakserver print_codegenlist print_class_summary run_optfile dump_codelayout dump_codelist dump_codemap print_utf8pool print_properties print_threads datadump_request runsystemgc runfinalization heap_diagnostics oom_diagnostics print_exceptions version timestamp command_line sanity verbosity set_filename help print_memusage
root@rise-vm-244:/usr/local/resin/conf# sudo -u www-data jrcmd 9660 print_object_summary 9660: --------- Detailed Heap Statistics: --------- 30.8% 18851k 223771 -2884k [C 15.9% 9698k 2061 -171k [B 6.7% 4073k 173796 -1799k java/lang/String 5.4% 3283k 105069 -3036k java/util/LinkedHashMap$Entry 4.6% 2823k 54897 -1854k [Ljava/util/HashMap$Entry; 4.1% 2491k 106286 -1764k java/util/HashMap$Entry 2.9% 1766k 56516 +0k com/caucho/loader/JarMap$JarList 2.4% 1456k 31072 -1010k java/util/HashMap 2.2% 1344k 21514 -1341k org/springframework/util/LinkedCaseInsensitiveMap 2.1% 1309k 39 +0k [Lcom/caucho/util/LruCache$CacheItem; 1.8% 1082k 9234 -8k java/lang/Class 1.6% 1006k 14587 -146k [Ljava/lang/Object; 1.3% 795k 10184 -188k java/lang/reflect/Method 0.9% 580k 14861 +0k java/lang/ref/WeakReference 0.6% 394k 8422 -3k java/lang/ref/SoftReference 0.6% 371k 47563 +0k java/lang/Object 0.6% 361k 9250 +0k com/caucho/util/LruCache$CacheItem 0.6% 342k 21947 -335k java/util/HashMap$EntrySet 0.5% 308k 4928 +231k com/mysql/jdbc/ConnectionPropertiesImpl$BooleanConnectionProperty 61148kB total --- --------- End of Detailed Heap Statistics ---
按最大对象查找工程代码,无果,细看代码,发现竟将大数据存进了session
三、解决办法
1、用Map<String, BigObject>:用户ID,大数据对象
2、用户每次登录,重写Map对象中的BigObject
3、BigObject有一个用户最后活跃时间字段,用户请求每次经过Filter,都用new Date()更新
4、另起一个定时线程,删除超时的BigObject
public class PrivilegeScheduler { private static final long RELOAD_DELAY = 1000L * 60 * 1; private static final long RELOAD_PERIOD = 1000L * 60 * 30; private static final long TIMEOUT_PERIOD = 1000L * 60 * 30; private static ScheduledExecutorService es = Executors.newScheduledThreadPool(5); /** * 定时清理缓存 */ public static void schedule() { es.scheduleAtFixedRate(new TimerTask() { @Override public void run() { PrivilegeCache.removeTimeOutUserPrivilege(TIMEOUT_PERIOD); } }, RELOAD_DELAY, RELOAD_PERIOD, TimeUnit.MILLISECONDS); } }
5、定时线程,通过Listener,系统启动时启动
<listener> <description>用于实始化系统参数</description> <listener-class>com.package.company.common.web.listener.ServletContextInitListener</listener-class> </listener>
public class ServletContextInitListener implements ServletContextListener { @Override public void contextInitialized(ServletContextEvent sce) { WebApplicationContextUtils.getRequiredWebApplicationContext(sce.getServletContext()).getAutowireCapableBeanFactory().autowireBeanProperties(this, AutowireCapableBeanFactory.AUTOWIRE_BY_NAME,false); PrivilegeScheduler.schedule(); } }