Skip to content

Commit b57d1f9

Browse files
committed
Make seeder thread pool sizes configurable via system properties / env vars
Allow GWC_SEEDER_CORE_POOL_SIZE and GWC_SEEDER_MAX_POOL_SIZE to be specified as Java system properties or OS environment variables, with system properties taking precedence. Falls back to the Spring XML constructor arguments (16/32) when not set or invalid. Invalid values (non-numeric, zero, negative) are logged as warnings and the defaults are used. If corePoolSize exceeds maxPoolSize after resolution, maxPoolSize is automatically adjusted upward to match. Includes unit tests and documentation updates. Closes #1429
1 parent 5d1c9e5 commit b57d1f9

9 files changed

Lines changed: 358 additions & 3 deletions

File tree

documentation/en/user/source/production/index.rst

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,43 @@ These applicaiton properties can be established by any of the following ways, in
9797
- 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`
9898

9999

100+
Seeder Thread Pool Size
101+
+++++++++++++++++++++++
102+
103+
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``:
104+
105+
.. code-block:: xml
106+
107+
<gwcConfiguration>
108+
...
109+
<seederCorePoolSize>24</seederCorePoolSize>
110+
<seederMaxPoolSize>64</seederMaxPoolSize>
111+
...
112+
</gwcConfiguration>
113+
114+
* ``seederCorePoolSize`` : the number of threads to keep in the pool, even if they are idle. Defaults to ``16``.
115+
* ``seederMaxPoolSize`` : the maximum number of threads allowed in the pool. Defaults to ``32``.
116+
117+
The configuration can be overridden at runtime using Java system properties or OS environment variables (useful for Docker and cloud deployments):
118+
119+
* ``GWC_SEEDER_CORE_POOL_SIZE`` : overrides ``seederCorePoolSize`` from the XML configuration.
120+
* ``GWC_SEEDER_MAX_POOL_SIZE`` : overrides ``seederMaxPoolSize`` from the XML configuration.
121+
122+
These overrides are resolved in the following order of precedence:
123+
124+
- As a Java system property: for example ``java -DGWC_SEEDER_CORE_POOL_SIZE=24 -DGWC_SEEDER_MAX_POOL_SIZE=64 ...``
125+
- As a System environment variable: ``export GWC_SEEDER_CORE_POOL_SIZE=24``
126+
127+
If the value is not set or is not a valid positive integer, the default is used. Invalid values are logged as warnings.
128+
129+
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.
130+
131+
.. note::
132+
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.
133+
134+
Increasing these values is useful when seeding many layers in parallel, especially in combination with a larger HTTP connection pool to the backend WMS.
135+
136+
100137
Resource Allocation
101138
-------------------
102139

geowebcache/core/src/main/java/org/geowebcache/config/GeoWebCacheConfiguration.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ public class GeoWebCacheConfiguration {
4646
/* Default values */
4747
private Integer backendTimeout;
4848

49+
private Integer seederCorePoolSize;
50+
51+
private Integer seederMaxPoolSize;
52+
4953
private String lockProvider;
5054

5155
private transient LockProvider lockProviderInstance;
@@ -128,6 +132,26 @@ public void setBackendTimeout(Integer backendTimeout) {
128132
this.backendTimeout = backendTimeout;
129133
}
130134

135+
/** @see ServerConfiguration#getSeederCorePoolSize() */
136+
public Integer getSeederCorePoolSize() {
137+
return seederCorePoolSize;
138+
}
139+
140+
/** @param seederCorePoolSize the core pool size for the seeder thread pool */
141+
public void setSeederCorePoolSize(Integer seederCorePoolSize) {
142+
this.seederCorePoolSize = seederCorePoolSize;
143+
}
144+
145+
/** @see ServerConfiguration#getSeederMaxPoolSize() */
146+
public Integer getSeederMaxPoolSize() {
147+
return seederMaxPoolSize;
148+
}
149+
150+
/** @param seederMaxPoolSize the maximum pool size for the seeder thread pool */
151+
public void setSeederMaxPoolSize(Integer seederMaxPoolSize) {
152+
this.seederMaxPoolSize = seederMaxPoolSize;
153+
}
154+
131155
/** @return the cacheBypassAllowed */
132156
public Boolean getCacheBypassAllowed() {
133157
return cacheBypassAllowed;

geowebcache/core/src/main/java/org/geowebcache/config/ServerConfiguration.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,4 +103,23 @@ public interface ServerConfiguration extends BaseConfiguration {
103103

104104
/** The version number should match the XSD namespace and the version of GWC */
105105
String getVersion();
106+
107+
/**
108+
* The core pool size for the seeder thread pool. This is the number of threads to keep in the pool, even if they
109+
* are idle.
110+
*
111+
* @return the configured core pool size, or {@code null} if not set (defaults to 16)
112+
*/
113+
default Integer getSeederCorePoolSize() {
114+
return null;
115+
}
116+
117+
/**
118+
* The maximum pool size for the seeder thread pool. This is the maximum number of threads allowed in the pool.
119+
*
120+
* @return the configured max pool size, or {@code null} if not set (defaults to 32)
121+
*/
122+
default Integer getSeederMaxPoolSize() {
123+
return null;
124+
}
106125
}

geowebcache/core/src/main/java/org/geowebcache/config/XMLConfiguration.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1304,6 +1304,18 @@ public void setBackendTimeout(Integer backendTimeout) throws IOException {
13041304
save();
13051305
}
13061306

1307+
/** @see ServerConfiguration#getSeederCorePoolSize() */
1308+
@Override
1309+
public Integer getSeederCorePoolSize() {
1310+
return gwcConfig.getSeederCorePoolSize();
1311+
}
1312+
1313+
/** @see ServerConfiguration#getSeederMaxPoolSize() */
1314+
@Override
1315+
public Integer getSeederMaxPoolSize() {
1316+
return gwcConfig.getSeederMaxPoolSize();
1317+
}
1318+
13071319
/** @see ServerConfiguration#isCacheBypassAllowed() */
13081320
@Override
13091321
public Boolean isCacheBypassAllowed() {

geowebcache/core/src/main/java/org/geowebcache/seed/SeederThreadPoolExecutor.java

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,90 @@ public class SeederThreadPoolExecutor extends ThreadPoolExecutor implements Disp
2828

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

31+
/**
32+
* Environment variable / system property name for configuring the core pool size. Looked up from Java system
33+
* properties first, then from OS environment variables. If neither is set or the value is not a valid positive
34+
* integer, the {@code corePoolSize} constructor argument is used as the default.
35+
*/
36+
public static final String GWC_SEEDER_CORE_POOL_SIZE = "GWC_SEEDER_CORE_POOL_SIZE";
37+
38+
/**
39+
* Environment variable / system property name for configuring the maximum pool size. Looked up from Java system
40+
* properties first, then from OS environment variables. If neither is set or the value is not a valid positive
41+
* integer, the {@code maxPoolSize} constructor argument is used as the default.
42+
*/
43+
public static final String GWC_SEEDER_MAX_POOL_SIZE = "GWC_SEEDER_MAX_POOL_SIZE";
44+
3145
public SeederThreadPoolExecutor(int corePoolSize, int maxPoolSize) {
32-
super(corePoolSize, maxPoolSize, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>(), tf);
46+
this(resolveAndValidateSizes(corePoolSize, maxPoolSize));
47+
}
48+
49+
private SeederThreadPoolExecutor(int[] sizes) {
50+
super(sizes[0], sizes[1], 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>(), tf);
51+
log.info("Seeder thread pool initialized with corePoolSize="
52+
+ getCorePoolSize()
53+
+ ", maxPoolSize="
54+
+ getMaximumPoolSize());
55+
}
56+
57+
/**
58+
* Resolves both pool sizes once and validates the core <= max constraint. Returns a two-element array [core, max].
59+
*/
60+
private static int[] resolveAndValidateSizes(int defaultCore, int defaultMax) {
61+
int core = resolvePoolSize(GWC_SEEDER_CORE_POOL_SIZE, defaultCore);
62+
int max = resolvePoolSize(GWC_SEEDER_MAX_POOL_SIZE, defaultMax);
63+
if (core > max) {
64+
log.warning(GWC_SEEDER_CORE_POOL_SIZE
65+
+ " ("
66+
+ core
67+
+ ") is greater than "
68+
+ GWC_SEEDER_MAX_POOL_SIZE
69+
+ " ("
70+
+ max
71+
+ "), adjusting maxPoolSize to match corePoolSize");
72+
max = core;
73+
}
74+
return new int[] {core, max};
75+
}
76+
77+
/**
78+
* Resolves a pool size configuration value by looking up the given property name first as a Java system property,
79+
* then as an OS environment variable. Falls back to the provided default if neither is set or the value is not a
80+
* valid positive integer.
81+
*
82+
* @param propertyName the system property / environment variable name to look up
83+
* @param defaultValue the fallback value if the property is not set or invalid
84+
* @return the resolved pool size
85+
*/
86+
static int resolvePoolSize(String propertyName, int defaultValue) {
87+
String value = System.getProperty(propertyName);
88+
if (value == null || value.isBlank()) {
89+
value = System.getenv(propertyName);
90+
}
91+
if (value != null && !value.isBlank()) {
92+
try {
93+
int parsed = Integer.parseInt(value.trim());
94+
if (parsed > 0) {
95+
log.info("Using configured value for " + propertyName + "=" + parsed);
96+
return parsed;
97+
} else {
98+
log.warning("Invalid value for "
99+
+ propertyName
100+
+ "="
101+
+ value
102+
+ " (must be a positive integer), using default "
103+
+ defaultValue);
104+
}
105+
} catch (NumberFormatException e) {
106+
log.warning("Invalid value for "
107+
+ propertyName
108+
+ "="
109+
+ value
110+
+ " (not a valid integer), using default "
111+
+ defaultValue);
112+
}
113+
}
114+
return defaultValue;
33115
}
34116

35117
/**

geowebcache/core/src/main/resources/geowebcache.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44
xsi:schemaLocation="http://geowebcache.org/schema/1.28.0 http://geowebcache.org/schema/1.28.0/geowebcache.xsd">
55
<version>1.8.0</version>
66
<backendTimeout>120</backendTimeout>
7+
<!-- Seeder thread pool configuration (optional, can be overridden by
8+
GWC_SEEDER_CORE_POOL_SIZE and GWC_SEEDER_MAX_POOL_SIZE env vars) -->
9+
<!-- <seederCorePoolSize>16</seederCorePoolSize> -->
10+
<!-- <seederMaxPoolSize>32</seederMaxPoolSize> -->
711
<serviceInformation>
812
<title>GeoWebCache</title>
913
<description>GeoWebCache is an advanced tile cache for WMS servers. It supports a large variety of protocols and

geowebcache/core/src/main/resources/org/geowebcache/config/geowebcache.xsd

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,26 @@
3838
</xs:documentation>
3939
</xs:annotation>
4040
</xs:element>
41+
<xs:element name="seederCorePoolSize" type="xs:positiveInteger" minOccurs="0">
42+
<xs:annotation>
43+
<xs:documentation xml:lang="en">
44+
The number of threads to keep in the seeder thread pool,
45+
even if they are idle. Defaults to 16.
46+
Can be overridden by the GWC_SEEDER_CORE_POOL_SIZE
47+
system property or environment variable.
48+
</xs:documentation>
49+
</xs:annotation>
50+
</xs:element>
51+
<xs:element name="seederMaxPoolSize" type="xs:positiveInteger" minOccurs="0">
52+
<xs:annotation>
53+
<xs:documentation xml:lang="en">
54+
The maximum number of threads allowed in the seeder
55+
thread pool. Defaults to 32.
56+
Can be overridden by the GWC_SEEDER_MAX_POOL_SIZE
57+
system property or environment variable.
58+
</xs:documentation>
59+
</xs:annotation>
60+
</xs:element>
4161
<xs:element name="lockProvider" type="xs:string" minOccurs="0">
4262
<xs:annotation>
4363
<xs:documentation xml:lang="en">

0 commit comments

Comments
 (0)