Embedded Jetty 从 6.1.7 升级到 9.4.43 的问题
Posted
技术标签:
【中文标题】Embedded Jetty 从 6.1.7 升级到 9.4.43 的问题【英文标题】:Embedded Jetty upgrade issues from 6.1.7 to 9.4.43 【发布时间】:2021-12-02 20:27:09 【问题描述】:我在旧的 jetty 版本中使用 jetty.xml 进行配置,看起来像这样:
<Configure id="Server" class="org.mortbay.jetty.Server">
<Set name="ThreadPool">
<New class="org.mortbay.thread.BoundedThreadPool">
<Set name="minThreads">10</Set>
<Set name="maxThreads">250</Set>
<Set name="lowThreads">25</Set>
</New>
</Set>
<Call name="addConnector">
<Arg>
<New class="org.mortbay.jetty.nio.SelectChannelConnector">
<Set name="host">
<SystemProperty name="jetty.host"/>
</Set>
<Set name="port">
<SystemProperty name="jetty.port" default="9096"/>
</Set>
<Set name="maxIdleTime">30000</Set>
<Set name="Acceptors">2</Set>
<Set name="statsOn">false</Set>
<Set name="confidentialPort">8443</Set>
<Set name="lowResourcesConnections">5000</Set>
<Set name="lowResourcesMaxIdleTime">5000</Set>
</New>
</Arg>
</Call>
<Set name="handler">
<New id="Handlers" class="org.mortbay.jetty.handler.HandlerCollection">
<Set name="handlers">
<Array type="org.mortbay.jetty.Handler">
<Item>
<New id="Contexts" class="org.mortbay.jetty.handler.ContextHandlerCollection"/>
</Item>
<!-- Disabling this as it is a security risk (by exposing all contexts) in production-->
<!--Item>
<New id="DefaultHandler" class="org.mortbay.jetty.handler.DefaultHandler"/>
</Item-->
<Item>
<New id="RequestLog" class="org.mortbay.jetty.handler.RequestLogHandler"/>
</Item>
</Array>
</Set>
</New>
</Set>
<Call name="addLifeCycle">
<Arg>
<New class="org.mortbay.jetty.deployer.ContextDeployer">
<Set name="contexts">
<Ref id="Contexts"/>
</Set>
<Set name="configurationDir">
<SystemProperty name="jetty.home" default="."/>/contexts</Set>
<Set name="scanInterval">1</Set>
</New>
</Arg>
</Call>
<New class="org.mortbay.jetty.servlet.Context">
<Arg>
<Ref id="Contexts"/>
</Arg>
<Arg>/cts/output</Arg>
<Set name="resourceBase">
<SystemProperty name="jetty.home" default="."/>/../cache/</Set>
<Call name="addServlet">
<Arg>com.myservlet.webservices.remote.FileProxyServlet</Arg>
<Arg>/</Arg>
</Call>
</New>
<Ref id="RequestLog">
<Set name="requestLog">
<New id="RequestLogImpl" class="org.mortbay.jetty.NCSARequestLog">
<Set name="filename">
<SystemProperty name="jetty.logs" default="../logs"/>/ws.request_yyyy_mm_dd.log</Set>
<Set name="filenameDateFormat">yyyy_MM_dd</Set>
<Set name="retainDays">90</Set>
<Set name="append">true</Set>
<Set name="extended">true</Set>
<Set name="logCookies">false</Set>
<Set name="LogTimeZone">GMT</Set>
</New>
</Set>
</Ref>
<!-- =========================================================== -->
<!-- extra options -->
<!-- =========================================================== -->
<Set name="stopAtShutdown">true</Set>
<Set name="sendServerVersion">true</Set>
<Set name="sendDateHeader">true</Set>
<Set name="gracefulShutdown">1000</Set>
</Configure>```
And to call this configuration following code has been written:
<Ref id="RequestLog">
<Set name="requestLog">
<New id="RequestLogImpl" class="org.mortbay.jetty.NCSARequestLog">
<Set name="filename">
<SystemProperty name="jetty.logs" default="../logs"/>/ws.request_yyyy_mm_dd.log</Set>
<Set name="filenameDateFormat">yyyy_MM_dd</Set>
<Set name="retainDays">90</Set>
<Set name="append">true</Set>
<Set name="extended">true</Set>
<Set name="logCookies">false</Set>
<Set name="LogTimeZone">GMT</Set>
</New>
</Set>
</Ref>
<!-- =========================================================== -->
<!-- extra options -->
<!-- =========================================================== -->
<Set name="stopAtShutdown">true</Set>
<Set name="sendServerVersion">true</Set>
<Set name="sendDateHeader">true</Set>
<Set name="gracefulShutdown">1000</Set>
</Configure>
已编写以下代码来调用此配置:
Server myServer;
File theConfigFile = new File( "C://jetty//etc//jetty.xml" );
XmlConfiguration theXmlConfiguration = new XmlConfiguration( theConfigFile.toURL() );
theXmlConfiguration.configure( myServer );
myServer.start();
我试图使用 jetty 9.4.43 创建类似的配置:
<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
<Configure id="jetty" class="org.eclipse.jetty.server.Server">
<New id="threadPool" class="org.eclipse.jetty.util.thread.QueuedThreadPool">
<Set name="minThreads" type="int"><Property name="jetty.threadPool.minThreads" deprecated="threads.min" default="10"/></Set>
<Set name="maxThreads" type="int"><Property name="jetty.threadPool.maxThreads" deprecated="threads.max" default="200"/></Set>
<Set name="reservedThreads" type="int"><Property name="jetty.threadPool.reservedThreads" default="25"/></Set>
<Set name="idleTimeout" type="int"><Property name="jetty.threadPool.idleTimeout" deprecated="threads.timeout" default="60000"/></Set>
<Set name="detailedDump" type="boolean"><Property name="jetty.threadPool.detailedDump" default="false"/></Set>
</New>
<Call name="addBean">
<Arg>
<New class="org.eclipse.jetty.util.thread.ScheduledExecutorScheduler"/>
</Arg>
</Call>
<Set name="connectors">
<Array type="org.eclipse.jetty.server.Connector">
<Item>
<New class="org.eclipse.jetty.server.ServerConnector">
<Arg><Ref refid="jetty"/></Arg>
<Set name="port">
<Property name="jetty.http.port" default="9096" />
</Set>
</New>
</Item>
</Array>
</Set>
<Set name="handler">
<New class="org.eclipse.jetty.server.handler.HandlerList">
<Set name="handlers">
<Array type="org.eclipse.jetty.server.Handler">
<Item>
<New class="org.eclipse.jetty.server.handler.ResourceHandler">
<Set name="directoriesListed">true</Set>
<Set name="resourceBase">.</Set>
</New>
</Item>
</Array>
</Set>
</New>
</Set>
<New class="org.eclipse.jetty.servlet.ServletContextHandler">
<Arg>
<Ref id="Contexts"/>
</Arg>
<Arg>/cts/output</Arg>
<Set name="resourceBase">
<SystemProperty name="jetty.home" default="."/>/../cache/</Set>
<Call name="addServlet">
<Arg>com.myservlet.webservices.remote.FileProxyServlet</Arg>
<Arg>/</Arg>
</Call>
</New>
<Set name="stopAtShutdown"><Property name="jetty.server.stopAtShutdown" default="true"/></Set>
<Set name="stopTimeout"><Property name="jetty.server.stopTimeout" default="5000"/></Set>
<Set name="dumpAfterStart"><Property name="jetty.server.dumpAfterStart" deprecated="jetty.dump.start" default="true"/></Set>
<Set name="dumpBeforeStop"><Property name="jetty.server.dumpBeforeStop" deprecated="jetty.dump.stop" default="true"/></Set>
</Configure>
使用新的 jetty.xml,端口 9096 被暴露,并且该目录下的所有可用文件都可以从运行 intelliJ 的位置访问,但 FileProxyServlet url 即 localhost:9096/cts/output 不可访问(显示 HTTP ERROR 404 Not Found) . 之前情况并非如此,而是只有 servlet 工作正常。
以下是使用新码头运行的控制台日志:
系统属性 [DEBUG] 已被弃用! (改用 org.eclipse.jetty.LEVEL=DEBUG)2021-10-16 13:56:48.162:INFO::main: 记录初始化 @80050ms 到 org.eclipse.jetty.util.log.StdErrLog [ShutdownMonitor] 未启用 (端口
开始 += QueuedThreadPool[qtp1589931229]@5ec46cddSTARTED,8 开始 | +- org.eclipse.jetty.util.thread.ThreadPoolBudget@2d7c53b6 | += ReservedThreadExecutor@16627f86s=0/2,p=0 - 已启动 | +> 线程 大小=8 | +> qtp1589931229-31 可运行 tid=31 prio=5 @ java.base@11.0.7/java.lang.invoke.InnerClassLambdaMetafactory.getParameterSize(InnerClassLambdaMetafactory.java:522) | +> qtp1589931229-34 TIMED_WAITING tid=34 prio=5 IDLE | +> qtp1589931229-29 TIMED_WAITING tid=29 prio=5 IDLE | +> qtp1589931229-27 TIMED_WAITING tid=27 prio=5 IDLE | +> qtp1589931229-32 TIMED_WAITING tid=32 prio=5 IDLE | +> qtp1589931229-33 RUNNABLE tid=33 prio=5 选择 | +> qtp1589931229-28 TIMED_WAITING tid=28 prio=5 IDLE | +> qtp1589931229-30 TIMED_WAITING tid=30 prio=5 IDLE += ScheduledExecutorScheduler@1e20e272STARTED - 已开始 += ServerConnector@70239ac0HTTP/1.1, (http/1.1)0.0.0.0:9096 - 开始 | +~ Server@4db85c57STARTING[9.4.43.v20210629] - 开始 | +~ QueuedThreadPool[qtp1589931229]@5ec46cddSTARTED,8 开始 | +~ ScheduledExecutorScheduler@1e20e272STARTED - 开始 | +- org.eclipse.jetty.io.ArrayByteBufferPool@3a1e66f1 | += HttpConnectionFactory@dc1f9ce[HTTP/1.1] - 开始 | | +- HttpConfiguration@1960af8332768/8192,8192/8192,https://:0,[] | | +> 定制器尺寸=0 | | +> formEncodedMethods 大小=2 | | | +> 发布 | | | +> 放 | | +> 输出缓冲区大小=32768 | | +> 输出聚合大小=8192 | | +> 请求头大小=8192 | | +> 响应头大小=8192 | | +> headerCacheSize=1024 | | +> 安全方案=https | | +> 安全端口=0 | | +> 空闲超时=-1 | | +> 阻塞超时=-1 | | +> 发送日期头=真 | | +> 发送服务器版本=真 | | +> sendXPoweredBy=false | | +> delayDispatchUntilContent=true | | +> 持久连接启用=真 | | +> 最大错误调度=10 | | +> minRequestDataRate=0 | | +> minResponseDataRate=0 | | +> cookieCompliance=RFC6265 | | +> setRequestCookieCompliance=RFC6265 | | +> notifyRemoteAsyncErrors=true | | +> 相对重定向允许=假 | += SelectorManager@ServerConnector@70239ac0HTTP/1.1, (http/1.1)0.0.0.0:9096 - 开始 | | += ManagedSelector@6ade7dbSTARTED id=0 键=0 选择=0 更新=0 - 开始 | | += EatWhatYouKill@6c4eab86/SelectorProducer@550ad4bd/PRODUCING/p=false/QueuedThreadPool[qtp1589931229]@5ec46cddSTARTED,8 开始 | | | +- SelectorProducer@550ad4bd | | | +~ QueuedThreadPool[qtp1589931229]@5ec46cddSTARTED,8 开始 | | +> 更新@ 2021-10-16T13:56:48.6732217+05:30 大小=0 | | +> 键@ 2021-10-16T13:56:48.674221+05:30 大小=0 | +- sun.nio.ch.ServerSocketChannelImpl[/0:0:0:0:0:0:0:0:9096] | +- qtp1589931229-31-acceptor-0@24c38c77-ServerConnector@70239ac0HTTP/1.1, (http/1.1)0.0.0.0:9096 += HandlerList@34d20482已启动 - 已启动 | += ResourceHandler@28a68c0STARTED - 开始 += ErrorHandler@61ad62a3STARTED - 开始 +> jdk.internal.loader.ClassLoaders$AppClassLoader@311d617d +> jdk.internal.loader.ClassLoaders$PlatformClassLoader@5e955596 键:+- bean,+= 托管,+~ 非托管,+?自动,+:可迭代,+] 数组,+@ 地图,+> 未定义 2021-10-16 13:56:48.679:INFO:oejs.Server:Jetty Web 服务器启动线程:已启动 @80567ms
这几天我一直在苦苦挣扎,谁能帮帮我?
【问题讨论】:
请编辑问题并包含您遇到的任何日志和错误。 另外,既然您只是使用嵌入式码头,为什么不完全在代码中完成呢? 嗨@JoakimErdfelt,我添加的FileProxyServlet 不起作用。我已经进一步更新了描述。让我知道是否需要共享任何其他信息。我正在升级码头 jar,因此,试图避免为相同的代码编写代码。 【参考方案1】:我会推荐一些更改。
首先,ResourceHandler
对你没有任何帮助。
<Array type="org.eclipse.jetty.server.Handler">
<Item>
<New class="org.eclipse.jetty.server.handler.ResourceHandler">
<Set name="directoriesListed">true</Set>
<Set name="resourceBase">.</Set>
</New>
</Item>
</Array>
它充其量只是坐在那里,什么也不做。 (因为它没有上下文,所以没有请求可以到达它)。
在最坏的情况下,您的设置方式现在已经通过 ResourceHandler
共享了您的整个驱动器。
删除它。
接下来,声明你的ServletContext
...
<New class="org.eclipse.jetty.servlet.ServletContextHandler">
<Arg>
<Ref id="Contexts"/>
</Arg>
<Arg>/cts/output</Arg>
<Set name="resourceBase"><SystemProperty name="jetty.home" default="."/>/../cache/</Set>
<Call name="addServlet">
<Arg>com.myservlet.webservices.remote.FileProxyServlet</Arg>
<Arg>/</Arg>
</Call>
关于这个声明的事情......
它没有结束它</New>
,所以它是一个损坏的 XML。
修复您的 XML。
第一个<Arg><Ref id="Contexts"/></Arg>
毫无意义并且也被破坏了。第一个参数似乎试图在其他地方指向 Contexts
引用,但该引用在任何地方都不存在,并且您对 <Ref>
元素的使用也是错误的,您已经声明了 <Ref>
本身id="Contexts"
并且没有引用其他 ID,即 <Ref refid="otherId"/>
。
完全删除 <Arg>
,它没有任何用处
使用<Arg>/cts/output</Arg>
设置上下文路径在多个方面都是错误的。
上下文路径规则是(必须以 /
开头,并且不能在其他任何地方包含任何其他斜杠,没有嵌套的上下文路径,这就是 url-patterns 的用途)
不要尝试使用构造函数来设置上下文路径,请使用 setter。
也删除这个<Arg>
,声明一个有效的上下文路径,然后使用setter代替<Set name="contextPath">/foo</Set>
您向/
url-pattern 添加了一个servlet,使resourceBase
上的努力无效。
修复此 url 模式。
您的ServletContextHandler
也不是服务器处理程序树的一部分。我认为您尝试使用第一个 <Arg>
来做到这一点,但这不是您将其添加到处理程序树的方式。
如果您直接声明它,只需将<New class="ServletContextHandler">...
放入处理程序树本身。
如果您稍后加载/实例化ServletContextHandler
,那么您必须使用DeploymentManager
和WebAppProvider
以及已经存在于处理程序树中的现有ContextHandlerCollection
,以便部署将其添加到.
你有一个奇怪的和坦率的混合使用,即使是 Jetty 6 也不应该允许。
您不能在默认 url 模式(即 /
)上使用 FileProxyServlet
并同时提供静态资源。
建议,正确使用 Jetty(这些建议在 Jetty 6 中也适用,并且在 Jetty 4 中同样有效!)
-
不要混用
ServletContextHandler
和 ResourceHandler
。
仅使用ServletContextHandler
。
只创建ServletContextHandler
contexPath /ctx
使ServletContextHandler
resourceBase
指向您的静态文件内容所在的位置(目录或jar:file:// url)。
将普通的DefaultServlet
添加到您的ServletContextHandler
(确保它被命名为“默认”并且是映射到/
的唯一 servlet)。
将您的 com.myservlet.webservices.remote.FileProxyServlet
添加到 url 模式 /output
。
最后,将您的ServletContextHandler
添加到服务器处理程序树中。
我鼓励您阅读过去答案中的更多信息。
Jetty: default servlet context path Serving static files from alternate path in embedded Jetty What is difference between ServletContextHandler.setResourceBase and ResourceHandler.setResourceBase when using Jetty embedded container? Embedded Jetty handling urls to serve content How to configure Jetty Handlers? Serving static files from alternate path in embedded Jetty Jetty: How to nest HandlerWrapper, HandlerList, and ContextHandlerCollection, and ContextHandler事情是,完全在单个 XML 文件中执行此操作令人费解(当 Jetty 6.0.0 首次发布时,不鼓励使用单个 XML 文件来配置 Jetty)。您是否考虑过使用 jetty-home
附带的 XML 文件,并在您自己的嵌入式码头启动时仅引用它们(以正确的顺序)?
这意味着您只需手动定义ServletContextHandler
,并将其放在您希望WebAppProvider
查找要部署的上下文的任何位置。
奖励是您升级 Jetty 版本的工作变得微不足道。
【讨论】:
嗨@Joakim Erdfelt,您是否考虑过使用jetty-home 附带的XML 文件并在您自己的嵌入式jetty 启动中引用它们(以正确的顺序)?您能否分享任何可以帮助我执行此步骤的文章? @AvinashModi 您已经在使用XmlConfiguration
,这就是 jetty-home 和 start.jar 的工作方式。看看XmlConfiguration.main()
method source,这是 Jetty 独立的入口点。
如果您想知道 xml 的顺序,请使用正确配置的 $jetty.base
上的 start.jar --list-config
来查看您需要的功能集的顺序。您甚至可以使用start.jar --dry-run
查看类路径和其他XmlConfiguration
参数。
嗨@Joakim Erdfelt,现在,我可以使用单个 jetty.xml 文件配置部署嵌入式码头。您能否确认这是否是正确的部署方式,因为没有提到这种方式?另外,是否可以在单个 jetty.xml 中以 https 模式配置码头?如果是,如何实现?
嗨@Joakim Erdfelt,您是否考虑过使用jetty-home 附带的XML 文件并在您自己的嵌入式jetty 启动中引用它们(以正确的顺序)?你能帮我应用这种方法吗?以上是关于Embedded Jetty 从 6.1.7 升级到 9.4.43 的问题的主要内容,如果未能解决你的问题,请参考以下文章
Embedded Jetty 无法识别 Spring MVC 安全性
Spring 3.1 WebApplicationInitializer & Embedded Jetty 8 AnnotationConfiguration
Embedded Jetty HTTP/2 不适用于 Firefox/Chrome,但在 Safari 上似乎没问题
Embedded Jetty:在安全的 https 服务器中,ContextHandler 重定向到 http URI