解决jetty在windows下锁静态文件的问题

本文原英文地址:http://www.eclipse.org/jetty/documentation/9.3.0.v20150612/troubleshooting-locked-files-on-windows.html#d0e26059
在jetty容器内,对于静态文件,会采用内存缓存的实现方式,如采用buteBuffer的方式来进行缓存。如果使用NIO连接器(默认情况),jetty就会采用文件映射(filemapper)的方式。但是这个方式在windows下会存在一个问题,即使用文件内存映射会导致这个文件被进程锁住,其它进程就不能但修改或者替换这个文件了。解决这个问题的一个方法就会停掉jetty,但这种方式显示不太靠谱。

jetty提供了一个开关标记来开启或者禁止内存映射,在类DefaultServlet中有一个属性useFileMappedBuffer,此属性值默认为false,并且在配置文件webdefault.xml中进行配置。

默认的配置文件存储在jar包jetty-webapp-${version}.jar中的org/eclipse/jetty/webapp/webdefault.xml,还有一份存储在jetty-home/etc/目录中。两者的区别在于,后者由jetty运行时配置文件中默认使用。前者由在代码中WebAppContext默认使用(没有配置值的情况下).最简单的作法就是修改这个配置文件,如下所示:

<init-param>
   <param-name>useFileMappedBuffer</param-name>
   <param-value>true</param-value> <!-- change to false -->
</init-param>

上面的配置文件的修改的前提在于保证jetty是使用了这个配置文件的,在etc/jetty-deploy.xml中,jetty会默认值此配置文件来配置相应的webAppContext属性,配置代码如下所示:

<Call id="webappprovider" name="addAppProvider">
  <Arg>
    <New class="org.eclipse.jetty.deploy.providers.WebAppProvider">
      .
      .
      <!-- this should be the new custom webdefault.xml or change should be made in this file -->
      <Set name="defaultsDescriptor"><Property name="jetty.home" default="." />/etc/webdefault.xml</Set>
      <Set name="scanInterval">1</Set>
      <Set name="extractWars">true</Set>
      .
      .
    </New>
  </Arg>
</Call>

如果我们在自定义的配置文件,那么也可以通过复制一份webdefault.xml文件,然后在自定义的context.xml中,指定相对应的配置描述符路径信息,如下所示:

<New id="myWebAppContext"  class="org.eclipse.jetty.webapp.WebAppContext">
  <Set name="contextPath">/</Set>
  <Set name="war">./webapps/fredapp</Set>
  <Set name="defaultsDescriptor">/home/fred/jetty/mywebdefaults.xml</Set>
  .
  .
</New>

在这个复制的webdefault配置文件当中,我们就可以修改相应的配置属性,将其修改为false,如下参考所示:

<web-app ...>
 ...
 <servlet>
     <servlet-name>Default</servlet-name>
     <servlet-class>org.eclipse.jetty.servlet.DefaultServlet</servlet-class>
     <init-param>
       <param-name>useFileMappedBuffer</param-name>
       <param-value>false</param-value>
     </init-param>
     <load-on-startup>0</load-on-startup>
   </servlet>
 ...
 </web-app>

备注:

在使用idea中的jetty插件时,idea会提供一个新的context.xml文件,然后使用默认的webContext配置,因此相应的配置属性读取于jar内的webdefault.xml文件。因此,想要在idea中解决此问题,需要将相应的jar(etty-webapp-${version}.jar)解压开,修改相应的配置文件 ,再重新打包回jar中,通过替换jar的方式才能解决此问题。修改etc配置目录下的文件无效.

原英文全文如下:

Jetty buffers static content for webapps such as HTML files, CSS files, images, etc. If you are using NIO connectors, Jetty uses memory-mapped files to do this. The problem is that on Windows, memory mapping a file causes the file to lock, so that you cannot update or replace the file. Effectively this means that you have to stop Jetty to update a file.

Jetty provides a configuration switch in the webdefault.xml file for the DefaultServlet that enables or disables the use of memory-mapped files. If you are running on Windows and are having file-locking problems, you should set this switch to disable memory-mapped file buffers.

The default webdefault.xml file is found in the jetty distribution under the etc/ directory or in the jetty-webapp-${version}.jar artifact at org/eclipse/jetty/webapp/webdefault.xml. Edit the file in the distribution or extract it to a convenient disk location and edit it to change useFileMappedBuffer to false. The easiest option is to simply edit the default file contained in the jetty distribution itself.

<init-param>
   <param-name>useFileMappedBuffer</param-name>
   <param-value>true</param-value> <!-- change to false -->
</init-param>

Make sure to apply your custom webdefault.xml file to all of your webapps. You can do that by changing the configuration of the Deployment Manager in etc/jetty-deploy.xml.

<Call id="webappprovider" name="addAppProvider">
  <Arg>
    <New class="org.eclipse.jetty.deploy.providers.WebAppProvider">
      .
      .
      <!-- this should be the new custom webdefault.xml or change should be made in this file -->
      <Set name="defaultsDescriptor"><Property name="jetty.home" default="." />/etc/webdefault.xml</Set>
      <Set name="scanInterval">1</Set>
      <Set name="extractWars">true</Set>
      .
      .
    </New>
  </Arg>
</Call>

Alternatively, if you have individually configured your webapps with context xml files, you need to call the WebAppContext.setDefaultsDescriptor(String path) method:

<New id="myWebAppContext"  class="org.eclipse.jetty.webapp.WebAppContext">
  <Set name="contextPath">/</Set>
  <Set name="war">./webapps/fredapp</Set>
  <Set name="defaultsDescriptor">/home/fred/jetty/mywebdefaults.xml</Set>
  .
  .
</New>

Instead, you could redefine the DefaultServlet in your web.xml file, making sure to set useFileMappedBuffer to false:

<web-app ...>
 ...
 <servlet>
     <servlet-name>Default</servlet-name>
     <servlet-class>org.eclipse.jetty.servlet.DefaultServlet</servlet-class>
     <init-param>
       <param-name>useFileMappedBuffer</param-name>
       <param-value>false</param-value>
     </init-param>
     <load-on-startup>0</load-on-startup>
   </servlet>
 ...
 </web-app>

转载请标明出处:i flym
本文地址:https://www.iflym.com/index.php/code/201510130001.html

相关文章:

作者: flym

I am flym,the master of the site:)

发表评论

邮箱地址不会被公开。 必填项已用*标注