故障排除¶
检查WFS请求¶
用户经常报告手工创建的WFS请求不能按预期工作的问题。在大多数情况下,请求是错误的,但Geoserver不会抱怨,只是忽略错误的部分(这种行为是使较旧的WFS客户端与Geoserver一起正常工作的默认行为)。
如果希望geoserver验证大多数WFS XML请求,可以将其发布到以下URL::
http://host:port/geoserver/ows?strict=true
与所需结构的任何偏差将在错误消息中注明。在任何情况下,唯一未验证的请求类型是插入类型(这是一个geoserver自己的限制)。
利用geoserver自己的日志¶
地理服务器可以在 $GEOSERVER_DATA_DIR/logs/geoserver.log
文件。查找此类文件是解决问题时首先要做的事情之一,特别是查看与错误请求对应的日志内容非常有趣。根据在中选择的日志配置文件,记录的信息量可能有所不同。 服务器设置 配置页。
日志记录服务请求¶
Geoserver提供默认情况下处于非活动状态的请求记录功能。在中启用时 global settings Geoserver可以记录请求的URL和POST请求内容。

全局设置¶
要跟踪传入请求的历史记录,请执行以下操作:
通过导航到以下位置启用请求记录 Enable Request Logging 。
页面,向下滚动到 Logging Settings ,以及使用以下选项启用此功能 Enable Request Logging 。
可选的选择 Log Request Bodies 对POST或PUT请求(例如,WFS事务)进行故障排除。要记录的字符数设置将对记录的数据量设置上限,以避免与记录相关的性能问题。
可选的选择 Log Request Headers 排除请求标头的故障(例如,在检查安全凭据时)。
单击 Apply 以应用这些设置。
这将记录请求信息,结果如下:
08 gen 11:30:13 INFO [geoserver.filters] - 127.0.0.1 "GET /geoserver/wms?HEIGHT=330&WIDTH=660&LAYERS=nurc%3AArc_Sample&STYLES=&SRS=EPSG%3A4326&FORMAT=image%2Fjpeg&SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&EXCEPTIONS=application%2Fvnd.ogc.se_inimage&BBOX=-93.515625,-40.078125,138.515625,75.9375" "Mozilla/5.0 (X11; U; Linux i686; it; rv:1.9.0.15) Gecko/2009102815 Ubuntu/9.04 (jaunty) Firefox/3.0.15" "http://localhost:8080/geoserver/wms?service=WMS&version=1.1.0&request=GetMap&layers=nurc:Arc_Sample&styles=&bbox=-180.0,-90.0,180.0,90.0&width=660&height=330&srs=EPSG:4326&format=application/openlayers" 08 gen 11:30:13 INFO [geoserver.filters] - 127.0.0.1 "GET /geoserver/wms?HEIGHT=330&WIDTH=660&LAYERS=nurc%3AArc_Sample&STYLES=&SRS=EPSG%3A4326&FORMAT=image%2Fjpeg&SERVICE=WMS&VERSION=1.1.1&REQUEST=GetMap&EXCEPTIONS=application%2Fvnd.ogc.se_inimage&BBOX=-93.515625,-40.078125,138.515625,75.9375" took 467ms 08 gen 11:30:14 INFO [geoserver.filters] - 127.0.0.1 "GET /geoserver/wms?REQUEST=GetFeatureInfo&EXCEPTIONS=application%2Fvnd.ogc.se_xml&BBOX=-93.515625%2C-40.078125%2C138.515625%2C75.9375&X=481&Y=222&INFO_FORMAT=text%2Fhtml&QUERY_LAYERS=nurc%3AArc_Sample&FEATURE_COUNT=50&Layers=nurc%3AArc_Sample&Styles=&Srs=EPSG%3A4326&WIDTH=660&HEIGHT=330&format=image%2Fjpeg" "Mozilla/5.0 (X11; U; Linux i686; it; rv:1.9.0.15) Gecko/2009102815 Ubuntu/9.04 (jaunty) Firefox/3.0.15" "http://localhost:8080/geoserver/wms?service=WMS&version=1.1.0&request=GetMap&layers=nurc:Arc_Sample&styles=&bbox=-180.0,-90.0,180.0,90.0&width=660&height=330&srs=EPSG:4326&format=application/openlayers" 08 gen 11:30:14 INFO [geoserver.filters] - 127.0.0.1 "GET /geoserver/wms?REQUEST=GetFeatureInfo&EXCEPTIONS=application%2Fvnd.ogc.se_xml&BBOX=-93.515625%2C-40.078125%2C138.515625%2C75.9375&X=481&Y=222&INFO_FORMAT=text%2Fhtml&QUERY_LAYERS=nurc%3AArc_Sample&FEATURE_COUNT=50&Layers=nurc%3AArc_Sample&Styles=&Srs=EPSG%3A4326&WIDTH=660&HEIGHT=330&format=image%2Fjpeg" took 314ms
服务器状态JVM控制台¶
Geoserver提供了内置的 JVM控制台 用于获得:
线程转储信息
堆转储信息
此页面可用于检查当前状态并下载结果以供仔细查看。

JVM控制台¶
使用JDK工具获取堆栈和内存转储¶
JDK包含三个有用的命令行工具,可用于收集有关正在泄漏内存或未按要求执行的地理服务器实例的信息: jps
, jstack
和 jmap
.
所有的工具都是针对一个活的Java虚拟机,特别是运行GeoServer的。为了让它们正常工作,您必须使用具有足够权限连接到JVM进程的用户来运行它们,特别是超级用户或运行JVM的同一用户通常具有所需的权限。
日元¶
jps 是一个列出所有正在运行的Java进程的工具。它可用于检索 pid
运行Geoserver的虚拟机的(进程ID)。例如::
> jps -mlv
16235 org.apache.catalina.startup.Bootstrap start -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Djava.util.logging.config.file=/home/aaime/devel/webcontainers/apache-tomcat-6.0.18/conf/logging.properties -Djava.endorsed.dirs=/home/aaime/devel/webcontainers/apache-tomcat-6.0.18/endorsed -Dcatalina.base=/home/aaime/devel/webcontainers/apache-tomcat-6.0.18 -Dcatalina.home=/home/aaime/devel/webcontainers/apache-tomcat-6.0.18 -Djava.io.tmpdir=/home/aaime/devel/webcontainers/apache-tomcat-6.0.18/temp
11521 -XX:MinHeapFreeRatio=10 -XX:MaxHeapFreeRatio=20 -Djava.library.path=/usr/lib/jni -Dosgi.requiredJavaVersion=1.5 -XX:MaxPermSize=256m -Xms64m -Xmx1024m -XX:CMSClassUnloadingEnabled -XX:CMSPermGenSweepingEnabled -XX:+UseParNewGC
16287 sun.tools.jps.Jps -mlv -Dapplication.home=/usr/lib/jvm/java-6-sun-1.6.0.16 -Xms8m
输出显示 pid
,主类名(如果可用),以及在启动时传递给JVM的参数。在这个例子中 16235
是Tomcat托管geoserver, 11521
是Eclipse实例,并且 16287
是 jps
本身。在一般情况下,您只有很少的JVM,并且运行geoserver的JVM可以通过传递给它的参数来标识。
J定位¶
jstack 是一个用于提取在虚拟机中运行的每个线程的当前堆栈跟踪的工具。它可以用来识别可伸缩性问题,并收集程序实际在做什么。
它通常需要详细了解Geoserver的内部工作原理,才能正确解释jStack输出。
用法示例:
> jstack -F -l 16235 > /tmp/tomcat-stack.txt
Attaching to process ID 16235, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 14.2-b01
文件内容可能如下:
Deadlock Detection:
No deadlocks found.
Thread 16269: (state = BLOCKED)
- java.lang.Object.wait(long) @bci=0 (Interpreted frame)
- org.apache.tomcat.util.threads.ThreadPool$MonitorRunnable.run() @bci=10, line=565 (Interpreted frame)
- java.lang.Thread.run() @bci=11, line=619 (Interpreted frame)
Locked ownable synchronizers:
- None
Thread 16268: (state = IN_NATIVE)
- java.net.PlainSocketImpl.socketAccept(java.net.SocketImpl) @bci=0 (Interpreted frame)
- java.net.PlainSocketImpl.accept(java.net.SocketImpl) @bci=7, line=390 (Interpreted frame)
- java.net.ServerSocket.implAccept(java.net.Socket) @bci=60, line=453 (Interpreted frame)
- java.net.ServerSocket.accept() @bci=48, line=421 (Interpreted frame)
- org.apache.jk.common.ChannelSocket.accept(org.apache.jk.core.MsgContext) @bci=46, line=306 (Interpreted frame)
- org.apache.jk.common.ChannelSocket.acceptConnections() @bci=72, line=660 (Interpreted frame)
- org.apache.jk.common.ChannelSocket$SocketAcceptor.runIt(java.lang.Object[]) @bci=4, line=870 (Interpreted frame)
- org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run() @bci=167, line=690 (Interpreted frame)
- java.lang.Thread.run() @bci=11, line=619 (Interpreted frame)
Locked ownable synchronizers:
- None
Thread 16267: (state = BLOCKED)
- java.lang.Object.wait(long) @bci=0 (Interpreted frame)
- java.lang.Object.wait() @bci=2, line=485 (Interpreted frame)
- org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run() @bci=26, line=662 (Interpreted frame)
- java.lang.Thread.run() @bci=11, line=619 (Interpreted frame)
Locked ownable synchronizers:
- None
...
内存图¶
jmap 是一个用于收集有关Java虚拟机的信息的工具。它可以以几种有趣的方式使用。
通过不带参数(而不是JVM的进程ID)运行它,它将输出一个 dump of the native libraries used by the JVM 。当用户想要再次检查Geoserver是否实际使用了某个版本的本地库(例如,GDAL)时,这会很方便:
> jmap 17251
Attaching to process ID 17251, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 14.2-b01
0x08048000 46K /usr/lib/jvm/java-6-sun-1.6.0.16/jre/bin/java
0x7f87f000 6406K /usr/lib/jvm/java-6-sun-1.6.0.16/jre/lib/i386/libNCSEcw.so.0
0x7f9b2000 928K /usr/lib/libstdc++.so.6.0.10
0x7faa1000 7275K /usr/lib/jvm/java-6-sun-1.6.0.16/jre/lib/i386/libgdal.so.1
0x800e9000 1208K /usr/lib/jvm/java-6-sun-1.6.0.16/jre/lib/i386/libclib_jiio.so
0x80320000 712K /usr/lib/jvm/java-6-sun-1.6.0.16/jre/lib/i386/libNCSUtil.so.0
0x80343000 500K /usr/lib/jvm/java-6-sun-1.6.0.16/jre/lib/i386/libNCSCnet.so.0
0x8035a000 53K /lib/libgcc_s.so.1
0x8036c000 36K /usr/lib/jvm/java-6-sun-1.6.0.16/jre/lib/i386/libnio.so
0x803e2000 608K /usr/lib/jvm/java-6-sun-1.6.0.16/jre/lib/i386/libawt.so
0x80801000 101K /usr/lib/jvm/java-6-sun-1.6.0.16/jre/lib/i386/libgdaljni.so
0x80830000 26K /usr/lib/jvm/java-6-sun-1.6.0.16/jre/lib/i386/headless/libmawt.so
0x81229000 93K /usr/lib/jvm/java-6-sun-1.6.0.16/jre/lib/i386/libnet.so
0xb7179000 74K /usr/lib/jvm/java-6-sun-1.6.0.16/jre/lib/i386/libzip.so
0xb718a000 41K /lib/tls/i686/cmov/libnss_files-2.9.so
0xb7196000 37K /lib/tls/i686/cmov/libnss_nis-2.9.so
0xb71b3000 85K /lib/tls/i686/cmov/libnsl-2.9.so
0xb71ce000 29K /lib/tls/i686/cmov/libnss_compat-2.9.so
0xb71d7000 37K /usr/lib/jvm/java-6-sun-1.6.0.16/jre/lib/i386/native_threads/libhpi.so
0xb71de000 184K /usr/lib/jvm/java-6-sun-1.6.0.16/jre/lib/i386/libjava.so
0xb7203000 29K /lib/tls/i686/cmov/librt-2.9.so
0xb725d000 145K /lib/tls/i686/cmov/libm-2.9.so
0xb7283000 8965K /usr/lib/jvm/java-6-sun-1.6.0.16/jre/lib/i386/server/libjvm.so
0xb7dc1000 1408K /lib/tls/i686/cmov/libc-2.9.so
0xb7f24000 9K /lib/tls/i686/cmov/libdl-2.9.so
0xb7f28000 37K /usr/lib/jvm/java-6-sun-1.6.0.16/jre/lib/i386/jli/libjli.so
0xb7f32000 113K /lib/tls/i686/cmov/libpthread-2.9.so
0xb7f51000 55K /usr/lib/jvm/java-6-sun-1.6.0.16/jre/lib/i386/libverify.so
0xb7f60000 114K /lib/ld-2.9.so
也有可能得到 JVM堆状态的快速摘要 ::
> jmap -heap 17251
Attaching to process ID 17251, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 14.2-b01
using thread-local object allocation.
Parallel GC with 2 thread(s)
Heap Configuration:
MinHeapFreeRatio = 40
MaxHeapFreeRatio = 70
MaxHeapSize = 778043392 (742.0MB)
NewSize = 1048576 (1.0MB)
MaxNewSize = 4294901760 (4095.9375MB)
OldSize = 4194304 (4.0MB)
NewRatio = 8
SurvivorRatio = 8
PermSize = 16777216 (16.0MB)
MaxPermSize = 67108864 (64.0MB)
Heap Usage:
PS Young Generation
Eden Space:
capacity = 42401792 (40.4375MB)
used = 14401328 (13.734176635742188MB)
free = 28000464 (26.703323364257812MB)
33.96396076845054% used
From Space:
capacity = 4718592 (4.5MB)
used = 2340640 (2.232208251953125MB)
free = 2377952 (2.267791748046875MB)
49.60462782118056% used
To Space:
capacity = 4587520 (4.375MB)
used = 0 (0.0MB)
free = 4587520 (4.375MB)
0.0% used
PS Old Generation
capacity = 43188224 (41.1875MB)
used = 27294848 (26.0303955078125MB)
free = 15893376 (15.1571044921875MB)
63.19974630121396% used
PS Perm Generation
capacity = 38404096 (36.625MB)
used = 38378640 (36.60072326660156MB)
free = 25456 (0.0242767333984375MB)
99.93371540369027% used
结果可以看出,允许JVM使用多达742MB的内存,而目前JVM使用130MB(每个堆段的容量的粗略总和)。如果发生持久性内存泄漏,JVM将最终使用允许使用的任何内容,堆的每个部分将几乎100%地被使用。
去看看 记忆是如何被简洁地使用的 可以使用以下命令(在Windows上,替换 head -25
具有 more
):
> jmap -histo:live 17251 | head -25
num #instances #bytes class name
----------------------------------------------
1: 81668 10083280 <constMethodKlass>
2: 81668 6539632 <methodKlass>
3: 79795 5904728 [C
4: 123511 5272448 <symbolKlass>
5: 7974 4538688 <constantPoolKlass>
6: 98726 3949040 org.hsqldb.DiskNode
7: 7974 3612808 <instanceKlassKlass>
8: 9676 2517160 [B
9: 6235 2465488 <constantPoolCacheKlass>
10: 10054 2303368 [I
11: 83121 1994904 java.lang.String
12: 27794 1754360 [Ljava.lang.Object;
13: 9227 868000 [Ljava.util.HashMap$Entry;
14: 8492 815232 java.lang.Class
15: 10645 710208 [S
16: 14420 576800 org.hsqldb.CachedRow
17: 1927 574480 <methodDataKlass>
18: 8937 571968 org.apache.xerces.dom.ElementNSImpl
19: 12898 561776 [[I
20: 23122 554928 java.util.HashMap$Entry
21: 16910 541120 org.apache.xerces.dom.TextImpl
22: 9898 395920 org.apache.xerces.dom.AttrNSImpl
通过转储,我们可以看到大部分内存由geoserver代码本身(前5项)使用,接着是包含几行epsg数据库的hsql缓存。在内存泄漏的情况下,一些对象类型将占据绝大多数活动堆。注意,要查找泄漏,应该在服务器几乎空闲的情况下收集转储文件。例如,如果服务器正在加载getmap请求,则主内存使用量将是呈现图像时保存图像的字节[],但这不是泄漏,这是合法的临时使用。
如果内存泄漏,开发人员可能会要求 完全堆转储 使用高端分析工具进行分析。可以使用以下命令生成此类转储:
> jmap -dump:live,file=/tmp/dump.hprof 17251
Dumping heap to /tmp/dump.hprof ...
Heap dump file created
转储文件通常与所使用的内存大小相同,因此建议在将其发送给开发人员之前压缩生成的文件。
XStream¶
Geoserver和GeoWebCache使用XStream来读写用于配置和REST API的XML。为了安全地完成这项工作,它需要一个Java类列表,这些类可以安全地在对象和XML之间进行转换。如果不在该列表上类被提供给XStream,它将生成错误 com.thoughtworks.xstream.security.ForbiddenClassException
。作为问题的特定类也应该包括在内。这可能是因为允许类的列表缺少一个类,这应该报告为错误,或者可能是因为扩展/插件没有将其类添加到列表中(最后,可能是有人试图执行“远程执行”攻击,这正是允许列表旨在防止的)。
可以通过设置系统属性来解决此问题 GEOSERVER_XSTREAM_WHITELIST
对于Geoserver或 GEOWEBCACHE_XSTREAM_WHITELIST
对于GeoWebCache,设置为以分号分隔的限定类名列表。类名称可以包括通配符 ?
对于单个字符, *
对于不包括分隔符的任意数量的字符 .
,以及 **
用于任意数量的字符,包括分隔符。例如, org.example.blah.SomeClass; com.demonstration.*; ca.test.**
将允许,特定的类 org.example.blah.SomeClass
,紧接在包中的任何类 com.demonstration
,以及包中的任何类 ca.test
或它的任何后代套餐。
GEOSERVER_XSTREAM_WHITELIST
和 GEOWEBCACHE_XSTREAM_WHITELIST
应仅在Geoserver、GWC或导致问题的扩展更新之前用作解决办法,因此请尽快向用户报告缺少的类。