-
Andrew Morgan authoredAndrew Morgan authored
Scaling synapse via workers
Synapse has experimental support for splitting out functionality into multiple separate python processes, helping greatly with scalability. These processes are called 'workers', and are (eventually) intended to scale horizontally independently.
All of the below is highly experimental and subject to change as Synapse evolves, but documenting it here to help folks needing highly scalable Synapses similar to the one running matrix.org!
All processes continue to share the same database instance, and as such, workers only work with postgres based synapse deployments (sharing a single sqlite across multiple processes is a recipe for disaster, plus you should be using postgres anyway if you care about scalability).
The workers communicate with the master synapse process via a synapse-specific TCP protocol called 'replication' - analogous to MySQL or Postgres style database replication; feeding a stream of relevant data to the workers so they can be kept in sync with the main synapse process and database state.
Configuration
To make effective use of the workers, you will need to configure an HTTP reverse-proxy such as nginx or haproxy, which will direct incoming requests to the correct worker, or to the main synapse instance. Note that this includes requests made to the federation port. See reverse_proxy.md for information on setting up a reverse proxy.
To enable workers, you need to add two replication listeners to the master synapse, e.g.:
listeners:
# The TCP replication port
- port: 9092
bind_address: '127.0.0.1'
type: replication
# The HTTP replication port
- port: 9093
bind_address: '127.0.0.1'
type: http
resources:
- names: [replication]
Under no circumstances should these replication API listeners be exposed to the public internet; it currently implements no authentication whatsoever and is unencrypted.
(Roughly, the TCP port is used for streaming data from the master to the workers, and the HTTP port for the workers to send data to the main synapse process.)
You then create a set of configs for the various worker processes. These should be worker configuration files, and should be stored in a dedicated subdirectory, to allow synctl to manipulate them. An additional configuration for the master synapse process will need to be created because the process will not be started automatically. That configuration should look like this:
worker_app: synapse.app.homeserver
daemonize: true
Each worker configuration file inherits the configuration of the main homeserver configuration file. You can then override configuration specific to that worker, e.g. the HTTP listener that it provides (if any); logging configuration; etc. You should minimise the number of overrides though to maintain a usable config.
You must specify the type of worker application (worker_app
). The currently
available worker applications are listed below. You must also specify the
replication endpoints that it's talking to on the main synapse process.
worker_replication_host
should specify the host of the main synapse,
worker_replication_port
should point to the TCP replication listener port and
worker_replication_http_port
should point to the HTTP replication port.
Currently, the event_creator
and federation_reader
workers require specifying
worker_replication_http_port
.
For instance:
worker_app: synapse.app.synchrotron
# The replication listener on the synapse to talk to.
worker_replication_host: 127.0.0.1
worker_replication_port: 9092
worker_replication_http_port: 9093
worker_listeners:
- type: http
port: 8083
resources:
- names:
- client
worker_daemonize: True
worker_pid_file: /home/matrix/synapse/synchrotron.pid
worker_log_config: /home/matrix/synapse/config/synchrotron_log_config.yaml
...is a full configuration for a synchrotron worker instance, which will expose a
plain HTTP /sync
endpoint on port 8083 separately from the /sync
endpoint provided
by the main synapse.
Obviously you should configure your reverse-proxy to route the relevant
endpoints to the worker (localhost:8083
in the above example).