Horizontal scaling
Introduction ¶
The print has a state containing the job queue and each job's state. To enable horizontal scaling, these states must be persisted.
Solution ¶
MapFish-Print's horizontal scaling solution is based on storing states in a database, for example
PostgreSQL. To enable this mode, the file
mapfish-spring-application-context-override-db.xml
must be copied to
mapfish-spring-application-context-override.xml
and database connection parameters must be
configured (see below).
The database connection must be configured with the following Java system properties:
db.host
: The database server host namedb.port
: The database server port (defaults to5432
)db.username
: The username to connect to the databasedb.password
: The password to connect to the databasedb.name
: The name of the databasedb.schema
: The schema to use (defaults topublic
)
The schema must exist, and the necessary tables are created automatically (print_accountings
,
print_job_results
, print_job_statuses
)
Database polling can be tuned with these two environment variables:
-
PRINT_CANCEL_OLD_POLL_INTERVAL
: How often in seconds the DB is polled for jobs to be canceled (default=60
s) -
PRINT_POLL_INTERVAL
: How often in seconds the DB is polled for new jobs (default=0.5
s)
Existing MapFish-Print Packages ¶
Existing MapFish-Print distribution packages may already contain functionality to ease the setup of horizontal scaling. For example, if you use the Docker image https://hub.docker.com/r/camptocamp/mapfish_print), you do not need to manually rename the file mentioned above, and a startup script contains functionality to verify database availability before the application server is started.
Docker ¶
In a Docker environment, the system properties should be added in the CATALINA_OPTS
environment
variable Like that: -D<property name>=<property value>
.
Kubernetes ¶
In Kubernetes, you can reuse an environment variable with:
env: - name: PROPERTY_VALUE value: test - name: CATALINA_OPTS value: -D<property name>==$(PROPERTY_VALUE)
The order is important.
Full example where we get the database credentials from a secret:
env: - name: PGHOST valueFrom: secretKeyRef: key: hostname name: database-credential-secret - name: PGPORT valueFrom: secretKeyRef: key: port name: database-credential-secret - name: PGUSER valueFrom: secretKeyRef: key: username name: database-credential-secret - name: PGPASSWORD valueFrom: secretKeyRef: key: password name: database-credential-secret - name: PGDATABASE valueFrom: secretKeyRef: key: database name: database-credential-secret - name: PGSCHEMA value: print - name: PGOPTIONS value: '-c statement_timeout=30000' - name: PRINT_POLL_INTERVAL value: '1' - name: CATALINA_OPTS value: >- -Ddb.host=$(PGHOST) -Ddb.port=$(PGPORT) -Ddb.username=$(PGUSER) -Ddb.password=$(PGPASSWORD) -Ddb.name=$(PGDATABASE) -Ddb.schema=$(PGSCHEMA)