Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions documentation/en/user/source/production/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,43 @@ These applicaiton properties can be established by any of the following ways, in
- As a System environment variable: `export GWC_SEED_ABORT_LIMIT=2000; <your usual command to run GWC here>` (or for Tomcat, use the Tomcat's `CATALINA_OPTS` in Tomcat's `bin/catalina.sh` as this: `CATALINA_OPTS="GWC_SEED_ABORT_LIMIT=2000 GWC_SEED_RETRY_COUNT=2`


Seeder Thread Pool Size
+++++++++++++++++++++++

The seeder thread pool controls how many seeding threads can run concurrently. By default, the core pool size is ``16`` and the maximum pool size is ``32``. These can be configured in ``geowebcache.xml``:

.. code-block:: xml

<gwcConfiguration>
...
<seederCorePoolSize>24</seederCorePoolSize>
<seederMaxPoolSize>64</seederMaxPoolSize>
...
</gwcConfiguration>

* ``seederCorePoolSize`` : the number of threads to keep in the pool, even if they are idle. Defaults to ``16``.
* ``seederMaxPoolSize`` : the maximum number of threads allowed in the pool. Defaults to ``32``.

The configuration can be overridden at runtime using Java system properties or OS environment variables (useful for Docker and cloud deployments):

* ``GWC_SEEDER_CORE_POOL_SIZE`` : overrides ``seederCorePoolSize`` from the XML configuration.
* ``GWC_SEEDER_MAX_POOL_SIZE`` : overrides ``seederMaxPoolSize`` from the XML configuration.

These overrides are resolved in the following order of precedence:

- As a Java system property: for example ``java -DGWC_SEEDER_CORE_POOL_SIZE=24 -DGWC_SEEDER_MAX_POOL_SIZE=64 ...``
- As a System environment variable: ``export GWC_SEEDER_CORE_POOL_SIZE=24``

If the value is not set or is not a valid positive integer, the default is used. Invalid values are logged as warnings.

If ``seederCorePoolSize`` (or its override) is set to a value greater than ``seederMaxPoolSize``, the maximum pool size will be automatically adjusted upward to match the core pool size.

.. note::
Unlike the seed failure tolerance settings above, the environment variable overrides are resolved directly by the Java code and do not support servlet context parameters in ``WEB-INF/web.xml``. Only Java system properties (``-D``) and OS environment variables are supported as overrides.

Increasing these values is useful when seeding many layers in parallel, especially in combination with a larger HTTP connection pool to the backend WMS.


Resource Allocation
-------------------

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ public class GeoWebCacheConfiguration {
/* Default values */
private Integer backendTimeout;

private Integer seederCorePoolSize;

private Integer seederMaxPoolSize;

private String lockProvider;

private transient LockProvider lockProviderInstance;
Expand Down Expand Up @@ -128,6 +132,26 @@ public void setBackendTimeout(Integer backendTimeout) {
this.backendTimeout = backendTimeout;
}

/** @see ServerConfiguration#getSeederCorePoolSize() */
public Integer getSeederCorePoolSize() {
return seederCorePoolSize;
}

/** @param seederCorePoolSize the core pool size for the seeder thread pool */
public void setSeederCorePoolSize(Integer seederCorePoolSize) {
this.seederCorePoolSize = seederCorePoolSize;
}

/** @see ServerConfiguration#getSeederMaxPoolSize() */
public Integer getSeederMaxPoolSize() {
return seederMaxPoolSize;
}

/** @param seederMaxPoolSize the maximum pool size for the seeder thread pool */
public void setSeederMaxPoolSize(Integer seederMaxPoolSize) {
this.seederMaxPoolSize = seederMaxPoolSize;
}

/** @return the cacheBypassAllowed */
public Boolean getCacheBypassAllowed() {
return cacheBypassAllowed;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,4 +103,23 @@ public interface ServerConfiguration extends BaseConfiguration {

/** The version number should match the XSD namespace and the version of GWC */
String getVersion();

/**
* The core pool size for the seeder thread pool. This is the number of threads to keep in the pool, even if they
* are idle.
*
* @return the configured core pool size, or {@code null} if not set (defaults to 16)
*/
default Integer getSeederCorePoolSize() {
return null;
}

/**
* The maximum pool size for the seeder thread pool. This is the maximum number of threads allowed in the pool.
*
* @return the configured max pool size, or {@code null} if not set (defaults to 32)
*/
default Integer getSeederMaxPoolSize() {
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1304,6 +1304,18 @@ public void setBackendTimeout(Integer backendTimeout) throws IOException {
save();
}

/** @see ServerConfiguration#getSeederCorePoolSize() */
@Override
public Integer getSeederCorePoolSize() {
return gwcConfig.getSeederCorePoolSize();
}

/** @see ServerConfiguration#getSeederMaxPoolSize() */
@Override
public Integer getSeederMaxPoolSize() {
return gwcConfig.getSeederMaxPoolSize();
}

/** @see ServerConfiguration#isCacheBypassAllowed() */
@Override
public Boolean isCacheBypassAllowed() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,87 @@ public class SeederThreadPoolExecutor extends ThreadPoolExecutor implements Disp

private static final ThreadFactory tf = new CustomizableThreadFactory("GWC Seeder Thread-");

/**
* Environment variable / system property name for configuring the core pool size. Looked up from Java system
* properties first, then from OS environment variables. If neither is set or the value is not a valid positive
* integer, the {@code corePoolSize} constructor argument is used as the default.
*/
public static final String GWC_SEEDER_CORE_POOL_SIZE = "GWC_SEEDER_CORE_POOL_SIZE";

/**
* Environment variable / system property name for configuring the maximum pool size. Looked up from Java system
* properties first, then from OS environment variables. If neither is set or the value is not a valid positive
* integer, the {@code maxPoolSize} constructor argument is used as the default.
*/
public static final String GWC_SEEDER_MAX_POOL_SIZE = "GWC_SEEDER_MAX_POOL_SIZE";

public SeederThreadPoolExecutor(int corePoolSize, int maxPoolSize) {
super(corePoolSize, maxPoolSize, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>(), tf);
this(resolveAndValidateSizes(corePoolSize, maxPoolSize));
}

private SeederThreadPoolExecutor(int[] sizes) {
super(sizes[0], sizes[1], 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>(), tf);
log.info("Seeder thread pool initialized with corePoolSize="
+ getCorePoolSize()
+ ", maxPoolSize="
+ getMaximumPoolSize());
}

/**
* Resolves both pool sizes once and validates the core <= max constraint. Returns a two-element array [core, max].
*/
private static int[] resolveAndValidateSizes(int defaultCore, int defaultMax) {
int core = resolvePoolSize(GWC_SEEDER_CORE_POOL_SIZE, defaultCore);
int max = resolvePoolSize(GWC_SEEDER_MAX_POOL_SIZE, defaultMax);
if (core > max) {
log.warning("Configured corePoolSize ("
+ core
+ ") is greater than maxPoolSize ("
+ max
+ "), adjusting maxPoolSize to match corePoolSize");
max = core;
}
return new int[] {core, max};
}

/**
* Resolves a pool size configuration value by looking up the given property name first as a Java system property,
* then as an OS environment variable. Falls back to the provided default if neither is set or the value is not a
* valid positive integer.
*
* @param propertyName the system property / environment variable name to look up
* @param defaultValue the fallback value if the property is not set or invalid
* @return the resolved pool size
*/
static int resolvePoolSize(String propertyName, int defaultValue) {
String value = System.getProperty(propertyName);
if (value == null || value.isBlank()) {
value = System.getenv(propertyName);
}
if (value != null && !value.isBlank()) {
try {
int parsed = Integer.parseInt(value.trim());
if (parsed > 0) {
log.info("Using configured value for " + propertyName + "=" + parsed);
return parsed;
} else {
log.warning("Invalid value for "
+ propertyName
+ "="
+ value
+ " (must be a positive integer), using default "
+ defaultValue);
}
} catch (NumberFormatException e) {
log.warning("Invalid value for "
+ propertyName
+ "="
+ value
+ " (not a valid integer), using default "
+ defaultValue);
}
}
return defaultValue;
}

/**
Expand Down
4 changes: 4 additions & 0 deletions geowebcache/core/src/main/resources/geowebcache.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
xsi:schemaLocation="http://geowebcache.org/schema/1.28.0 http://geowebcache.org/schema/1.28.0/geowebcache.xsd">
<version>1.8.0</version>
<backendTimeout>120</backendTimeout>
<!-- Seeder thread pool configuration (optional, can be overridden by
GWC_SEEDER_CORE_POOL_SIZE and GWC_SEEDER_MAX_POOL_SIZE env vars) -->
<!-- <seederCorePoolSize>16</seederCorePoolSize> -->
<!-- <seederMaxPoolSize>32</seederMaxPoolSize> -->
<serviceInformation>
<title>GeoWebCache</title>
<description>GeoWebCache is an advanced tile cache for WMS servers. It supports a large variety of protocols and
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,26 @@
</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="seederCorePoolSize" type="xs:positiveInteger" minOccurs="0">
<xs:annotation>
<xs:documentation xml:lang="en">
The number of threads to keep in the seeder thread pool,
even if they are idle. Defaults to 16.
Can be overridden by the GWC_SEEDER_CORE_POOL_SIZE
system property or environment variable.
</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="seederMaxPoolSize" type="xs:positiveInteger" minOccurs="0">
<xs:annotation>
<xs:documentation xml:lang="en">
The maximum number of threads allowed in the seeder
thread pool. Defaults to 32.
Can be overridden by the GWC_SEEDER_MAX_POOL_SIZE
system property or environment variable.
</xs:documentation>
</xs:annotation>
</xs:element>
<xs:element name="lockProvider" type="xs:string" minOccurs="0">
<xs:annotation>
<xs:documentation xml:lang="en">
Expand Down
Loading
Loading