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=60s) -
PRINT_POLL_INTERVAL: How often in seconds the DB is polled for new jobs (default=0.5s)
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)