【问题标题】:OpenLayers Ext.form.ComboBox store query creates memory leakOpenLayers Ext.form.ComboBox 存储查询创建内存泄漏
【发布时间】:2015-04-23 06:36:02
【问题描述】:

确认。使用 OpenLayers,我有一个 Ext.form.ComboBox,它运行 Ext.data.JsonStore 的查询以访问 ~1 Gb 的 shapefile 并返回结果表。然后,用户可以选择其中一个结果,然后地图会缩放到该位置。

这很好用。但!随着 ComboBox 的使用,JVM 的大小继续增长 - 内存泄漏? - 并且 Geoserver 引发了许多问题,大部分都与:

Caused by: java.io.IOException: Map failed
Caused by: java.lang.OutOfMemoryError: Map failed
ERROR [geotools.map] - Call MapContent dispose() to prevent memory leaks

在错误风暴淹没 Geoserver 之前,我可以在大约一分钟内运行 ComboBox 多达五次(例如 GetFeatureInfo 不返回任何结果,ComboBox 查询返回为空,出现粉红色瓷砖,编辑:GWC 停止制作新瓷砖!)。

我是否需要销毁 () 或清除存储或...?如何?想法??

GeoExt 1.1、OpenLayers 2.12.rc6、Ext 3.4、Ext 4.2.1.883、jquery-1.6、Geoserver 2.5、JDK i586 v7、Tomcat 7

代码:

查询:查找在 ComboBox 中输入的内容并填充到 Store

Ext.onReady(function() {
Ext.override(Ext.form.ComboBox, {
    doQuery: function(q, forceAll) {
        console.log('queryTpl', this.queryTpl, q); 
        q = Ext.isEmpty(q) ? '' : q;
        var qe = {
            query: q,
            forceAll: forceAll,
            combo: this,
            cancel: false
        };
        if (this.fireEvent('beforequery', qe) === false || qe.cancel) {
            return false;
        }
        q = qe.query;
        forceAll = qe.forceAll;
        if (forceAll === true || (q.length >= this.minChars)) {
            if (this.lastQuery !== q) {
                this.lastQuery = q;
                if (this.mode == 'local') {
                    this.selectedIndex = -1;
                    if (forceAll) {
                        this.store.clearFilter();
                    } else {
                        this.store.filter(this.displayField, q);
                    }
                    this.onLoad();
                } else {
                    this.store.baseParams[this.queryParam] = this.queryTpl ? String.format(this.queryTpl, q) : q;
                    this.store.load({
                        params: this.getParams(q)
                    });
                    this.expand();
                }
            } else {
                this.selectedIndex = -1;
                this.onLoad();
            }
        }
    },
});
})

商店

var dsm = new Ext.data.JsonStore({
remoteFilter: true,
autoLoad: false,
autoDestroy: true,  // doesn't appear to help
url: '../geoserver/workspace',  // generalized, not for public access
storeId: 'myStore2',
baseParams: {
    service: 'WFS',
    version: '1.1.0',
    request: 'GetFeature',
    typeName: 'MRDS_LUT',    // *shp in geoserver defined by var
    srsName: 'EPSG:4326',
    outputFormat: 'json',
    propertyName: 'SiteName,Municipal,Commodity,Status,Longitude,Latitude'
},
root: 'features',
fields: [{
    name: 'SiteName',
    mapping: 'properties.SiteName'
}, {
    name: 'Municipal',
    mapping: 'properties.Municipal'
}, {
    name: 'Commodity',
    mapping: 'properties.Commodity'
}, {
    name: 'Status',
    mapping: 'properties.Status'
}, {
    name: 'Longitude',
    mapping: 'properties.Longitude'
}, {
    name: 'Latitude',
    mapping: 'properties.Latitude'
},{
    name: 'bbox',
    mapping: 'properties.bbox'
}],
sortInfo: {
    field: "Municipal",
    direction: "ASC"
}
});

组合框

var panelSiteNameSearch = new Ext.form.ComboBox({
store: dsm,
fieldLabel: "<b>Search</b>",
queryParam: "cql_filter",
queryTpl: "SiteName Like '{0}%'",
minChars: 5,
displayField: "SiteName",
valueField: "SiteName",
typeAhead: false,
loadingText: "Searching...",
width: 230,
emptyText: "Mine/Mineral Site Search",
hideTrigger: true,
tpl: '<tpl for="."><div class="search-item"><b>Site Name:</b> {SiteName}<br><b>Commodity: </b> {Commodity}<br><b>Municipality:</b> {Municipal}<br><b>Status:</b> {Status}</div><hr/></tpl>',
itemSelector: "div.search-item",
    listeners: {
        "select": function (combo, record) {
            mrdsprimary.setVisibility(true);
            mrdssecondary.setVisibility(true);
            mrdstertiary.setVisibility(true);
            map.setCenter(new OpenLayers.LonLat(record.data.Longitude,record.data.Latitude),13);
        },
        "focus": function () {
            keyboardnav.deactivate();
        },
        "blur": function () {
            keyboardnav.activate();
        }
    }
});   

【问题讨论】:

  • 我添加了 panelSiteNameSearch.store.removeAll();就在 map.setCenter 之后,我现在可以随心所欲地查询商店,并且无论 JVM 大小如何,ComboBox 都可以正常工作但是所有 GetFeatureInfo 和任何使用 GeoWebCache 的层仍然完全停止工作

标签: memory-leaks combobox openlayers geoserver jsonstore


【解决方案1】:

这个解决方案有点模糊。我最终通过确保所有组合框存储的总大小加上初始 Java -Xms 分配不超过 Java -Xmx 分配来防止内存不足错误。

例如,将 -Xms 设置为 500m,并且知道存储 #1 访问 600m 的数据库,而存储 #2 访问 800m 的数据库,在我的 Java 环境堆中总共有 1900mb。如果 -Xmx 设置为 2g,则不会引发错误。

理论上。我不能直接影响 Java 环境的 Xms 而不干扰 Tomcat/Java 的本机 GC。知道有总分配的 -Xmx 上限,以及直接计入它的内容,会鼓励极其精简的数据存储。

不幸的是,我仅限于 32 位 JDK i586,我在某处读到了 -Xmx 固有的 2gb 限制(这似乎是正确的)。据报道,64 位要高得多。

发现:远程存储“加载”整个数据存储,并在本地提交过滤结果...使用 removeAll 或 clearFilter 或 setValue() 或 NULL 和/或 SYNC 清除存储仅在本地有效,实际上并不触发任何远程 GC 或减少远程 Java 堆积的不必要存储。

长期解决方案:创建一个服务器端 PHP 脚本,将给定的 cql 或其他一些查询或 ComboBox 值直接传递到 SQL 或 PostGIS 数据库,并将 javascript 排除在外。但我还不知道怎么写。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-04-12
    • 1970-01-01
    • 1970-01-01
    • 2010-10-09
    • 2016-12-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多