Tomcat 与 WAR 捆绑在一起的 Memcached 依赖项
Tomcat Memcached dependencies bundled with WAR
我目前正在使用 memcached-tomcat-session-manager 和 Tomcat7 进行会话存储。
这是使用 $CATALINA_HOME/lib
和 $CATALINA_HOME/conf/context.xml
中的各种内存缓存/转码器/序列化器 JAR 以规定的方式设置的,带有 <Manager> ...
条目并且工作正常。
出现了一种情况,我想在我的 webapp 和(我的修改版本)memcached-session-manager 之间共享 类 的一些 static
属性。我相信在当前设置下它们位于不同的类加载器中,因此无法在 类 之间共享静态资源。
这导致我将所有依赖项与 /WEB_INF/lib
捆绑在一起,并将 <Manager ...
定义移动到 /META-INF/context.xml
。这不起作用,Tomcat 报告:
portal_1 | 2018-12-21 01:26:27,291 [Portal] SEVERE {localhost-startStop-1} Digester Begin event threw exception
portal_1 | java.lang.ClassNotFoundException: de.javakaffee.web.msm.MemcachedBackupSessionManager
portal_1 | at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
portal_1 | at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
portal_1 | at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
portal_1 | at org.apache.tomcat.util.digester.ObjectCreateRule.begin(ObjectCreateRule.java:144)
portal_1 | at org.apache.tomcat.util.digester.Digester.startElement(Digester.java:1303)
portal_1 | at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.startElement(AbstractSAXParser.java:509)
portal_1 | at com.sun.org.apache.xerces.internal.parsers.AbstractXMLDocumentParser.emptyElement(AbstractXMLDocumentParser.java:182)
portal_1 | at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanStartElement(XMLDocumentFragmentScannerImpl.java:1339)
portal_1 | at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2784)
portal_1 | at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:602)
portal_1 | at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:505)
portal_1 | at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:842)
portal_1 | at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:771)
portal_1 | at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141)
portal_1 | at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1213)
portal_1 | at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:643)
portal_1 | at org.apache.tomcat.util.digester.Digester.parse(Digester.java:1576)
portal_1 | at org.apache.catalina.startup.ContextConfig.processContextConfig(ContextConfig.java:644)
portal_1 | at org.apache.catalina.startup.ContextConfig.contextConfig(ContextConfig.java:606)
portal_1 | at org.apache.catalina.startup.ContextConfig.init(ContextConfig.java:842)
portal_1 | at org.apache.catalina.startup.ContextConfig.lifecycleEvent(ContextConfig.java:399)
portal_1 | at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:117)
portal_1 | at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:90)
portal_1 | at org.apache.catalina.util.LifecycleBase.setStateInternal(LifecycleBase.java:388)
portal_1 | at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:103)
portal_1 | at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:135)
portal_1 | at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:1018)
portal_1 | at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:994)
portal_1 | at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:652)
portal_1 | at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:1127)
portal_1 | at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:2021)
portal_1 | at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
portal_1 | at java.util.concurrent.FutureTask.run(FutureTask.java:266)
portal_1 | at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
portal_1 | at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
portal_1 | at java.lang.Thread.run(Thread.java:748)
我确信依赖项已捆绑在 WAR
中。在阅读 Tomcat 7 文档后,我不清楚我正在做的事情是否可行 - 在 WAR context.xml
中定义了 类 而 $CATALINA_HOME/lib
中没有定义,例如应用程序类加载器尚未创建。
memcached-session-manager (msm) jar 必须驻留在 $CATALINA_HOME/lib
中,因为它们正在使用 tomcat 内部 类(这在 webapp 中是不可能的)。更具体地说,这些 jar 是 memcached-session-manager.jar
、memcached-session-manager-tc7.jar
和 spymemcached.jar
。
唯一必须放在 /WEB_INF/lib
中的与 msm 相关的 jar 是与序列化相关的 jar,例如 msm-kryo-serializer
(通常定义为 maven/gradle/xyz 构建中的依赖项),因为它们必须能够访问特定应用程序 类.
另见相关 msm documentation。
关于您在 msm 和您的应用程序之间共享信息的目标:因为 msm jar 必须驻留在 $CATALINA_HOME/lib
中,从概念上讲,不可能将应用程序代码与 msm 代码静态地 "link"(与 msm 序列化程序相关的除外)代码)。这只有通过额外的间接方式才有可能:在 msm 中定义某个接口,应用程序在其中提供实现,然后 msm 通过反射加载该接口。这就是序列化程序如何挂接到 msm 中,请参阅 the TranscoderFactory interface (loaded from $CATALINA_HOME/lib
) and the KryoTranscoderFactory implementation(从 /WEB_INF/lib
加载)。
我目前正在使用 memcached-tomcat-session-manager 和 Tomcat7 进行会话存储。
这是使用 $CATALINA_HOME/lib
和 $CATALINA_HOME/conf/context.xml
中的各种内存缓存/转码器/序列化器 JAR 以规定的方式设置的,带有 <Manager> ...
条目并且工作正常。
出现了一种情况,我想在我的 webapp 和(我的修改版本)memcached-session-manager 之间共享 类 的一些 static
属性。我相信在当前设置下它们位于不同的类加载器中,因此无法在 类 之间共享静态资源。
这导致我将所有依赖项与 /WEB_INF/lib
捆绑在一起,并将 <Manager ...
定义移动到 /META-INF/context.xml
。这不起作用,Tomcat 报告:
portal_1 | 2018-12-21 01:26:27,291 [Portal] SEVERE {localhost-startStop-1} Digester Begin event threw exception
portal_1 | java.lang.ClassNotFoundException: de.javakaffee.web.msm.MemcachedBackupSessionManager
portal_1 | at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
portal_1 | at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
portal_1 | at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
portal_1 | at org.apache.tomcat.util.digester.ObjectCreateRule.begin(ObjectCreateRule.java:144)
portal_1 | at org.apache.tomcat.util.digester.Digester.startElement(Digester.java:1303)
portal_1 | at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.startElement(AbstractSAXParser.java:509)
portal_1 | at com.sun.org.apache.xerces.internal.parsers.AbstractXMLDocumentParser.emptyElement(AbstractXMLDocumentParser.java:182)
portal_1 | at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanStartElement(XMLDocumentFragmentScannerImpl.java:1339)
portal_1 | at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2784)
portal_1 | at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:602)
portal_1 | at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:505)
portal_1 | at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:842)
portal_1 | at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:771)
portal_1 | at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:141)
portal_1 | at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1213)
portal_1 | at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:643)
portal_1 | at org.apache.tomcat.util.digester.Digester.parse(Digester.java:1576)
portal_1 | at org.apache.catalina.startup.ContextConfig.processContextConfig(ContextConfig.java:644)
portal_1 | at org.apache.catalina.startup.ContextConfig.contextConfig(ContextConfig.java:606)
portal_1 | at org.apache.catalina.startup.ContextConfig.init(ContextConfig.java:842)
portal_1 | at org.apache.catalina.startup.ContextConfig.lifecycleEvent(ContextConfig.java:399)
portal_1 | at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:117)
portal_1 | at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:90)
portal_1 | at org.apache.catalina.util.LifecycleBase.setStateInternal(LifecycleBase.java:388)
portal_1 | at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:103)
portal_1 | at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:135)
portal_1 | at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:1018)
portal_1 | at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:994)
portal_1 | at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:652)
portal_1 | at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:1127)
portal_1 | at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:2021)
portal_1 | at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
portal_1 | at java.util.concurrent.FutureTask.run(FutureTask.java:266)
portal_1 | at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
portal_1 | at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
portal_1 | at java.lang.Thread.run(Thread.java:748)
我确信依赖项已捆绑在 WAR
中。在阅读 Tomcat 7 文档后,我不清楚我正在做的事情是否可行 - 在 WAR context.xml
中定义了 类 而 $CATALINA_HOME/lib
中没有定义,例如应用程序类加载器尚未创建。
memcached-session-manager (msm) jar 必须驻留在 $CATALINA_HOME/lib
中,因为它们正在使用 tomcat 内部 类(这在 webapp 中是不可能的)。更具体地说,这些 jar 是 memcached-session-manager.jar
、memcached-session-manager-tc7.jar
和 spymemcached.jar
。
唯一必须放在 /WEB_INF/lib
中的与 msm 相关的 jar 是与序列化相关的 jar,例如 msm-kryo-serializer
(通常定义为 maven/gradle/xyz 构建中的依赖项),因为它们必须能够访问特定应用程序 类.
另见相关 msm documentation。
关于您在 msm 和您的应用程序之间共享信息的目标:因为 msm jar 必须驻留在 $CATALINA_HOME/lib
中,从概念上讲,不可能将应用程序代码与 msm 代码静态地 "link"(与 msm 序列化程序相关的除外)代码)。这只有通过额外的间接方式才有可能:在 msm 中定义某个接口,应用程序在其中提供实现,然后 msm 通过反射加载该接口。这就是序列化程序如何挂接到 msm 中,请参阅 the TranscoderFactory interface (loaded from $CATALINA_HOME/lib
) and the KryoTranscoderFactory implementation(从 /WEB_INF/lib
加载)。