You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
184 lines
6.4 KiB
184 lines
6.4 KiB
# HDStack multi-process deployment
|
|
|
|
HDStack raises the aggregate hotspot capacity of one FreeDMR container by
|
|
running two to five independent FreeDMR HBP workers. It does not raise the
|
|
connection limit of an individual worker.
|
|
|
|
Omitting `HDSTACK`, or setting `HDSTACK=1`, preserves the existing standard
|
|
single-FreeDMR process layout. Setting `HDSTACK` to a value from 2 through 5
|
|
selects the generated multi-process layout:
|
|
|
|
```text
|
|
hotspots -> proxy -> HBP workers -> no-HBP aggregator -> external FBP/OBP
|
|
|
|
|
+-> separate bridge.py instance
|
|
|
|
worker reports -> reporting MUX -> existing dashboard/reporting consumer
|
|
```
|
|
|
|
The aggregator owns all OpenBridge/FBP links from the main `freedmr.cfg` and
|
|
has no HBP `MASTER`, `PEER` or `XLXPEER` system. The separate `bridge.py`
|
|
process retains its own configuration and rules. The reporting MUX reads only
|
|
worker reports; aggregator and bridge reporting are not included.
|
|
|
|
## Container configuration
|
|
|
|
Add these environment values to the standard `freedmr` service:
|
|
|
|
```yaml
|
|
environment:
|
|
- HDSTACK=2
|
|
- HDSTACK_BASEID=23400
|
|
```
|
|
|
|
`HDSTACK_BASEID` is the aggregator server ID. Worker IDs are allocated by
|
|
adding their one-based worker number. For the example above, the aggregator is
|
|
`23400` and the two workers are `23401` and `23402`. With `HDSTACK=5`, worker
|
|
IDs continue through `23405`.
|
|
|
|
Multi-process mode also requires the existing separate bridge inputs:
|
|
|
|
```yaml
|
|
volumes:
|
|
- '/etc/freedmr/freedmr.cfg:/opt/freedmr/freedmr.cfg'
|
|
- '/etc/freedmr/freedmr-bridge.cfg:/opt/freedmr/freedmr-bridge.cfg:ro'
|
|
- '/etc/freedmr/rules-bridge.py:/opt/freedmr/rules.py:ro'
|
|
```
|
|
|
|
The paths can be changed with:
|
|
|
|
```yaml
|
|
environment:
|
|
- HDSTACK_BRIDGE_CONFIG=/opt/freedmr/freedmr-bridge.cfg
|
|
- HDSTACK_BRIDGE_RULES=/opt/freedmr/rules.py
|
|
```
|
|
|
|
The main `freedmr.cfg` remains the sysop-facing aggregator and worker-template
|
|
configuration. It must contain one enabled `[SYSTEM]` stanza in `MASTER` mode.
|
|
All enabled and disabled `OPENBRIDGE` sections are copied to the aggregator;
|
|
this includes external FBP/OBP links and the configured link to `bridge.py`.
|
|
Other protocol systems, including `[SYSTEM]` and `[ECHO]`, are not copied to
|
|
the aggregator.
|
|
|
|
Each worker receives the same `[SYSTEM]` policy. Only its base HBP port is
|
|
derived. Worker and aggregator configuration files are generated privately in
|
|
`/dev/shm/freedmr-hdstack` when the container starts. The mounted source
|
|
configuration and bridge files are not changed.
|
|
|
|
The bridge configuration must contain the reciprocal link to the aggregator
|
|
and any `PEER` or `XLXPEER` systems used by `bridge.py`. Its `rules.py` remains
|
|
the authority for bridge routing. Bridge reporting must either be disabled or
|
|
use a port which does not collide with the worker reports or MUX.
|
|
|
|
## Worker ports
|
|
|
|
The `[SYSTEM]` `PORT` and `GENERATOR` values define each worker range. With the
|
|
standard values `PORT=54000` and `GENERATOR=100`:
|
|
|
|
```text
|
|
worker 1 -> 54000..54099
|
|
worker 2 -> 54100..54199
|
|
worker 3 -> 54200..54299
|
|
worker 4 -> 54300..54399
|
|
worker 5 -> 54400..54499
|
|
```
|
|
|
|
The generated ranges must fit within the UDP port range and must not collide
|
|
with configured bridge, external OpenBridge or reporting ports.
|
|
|
|
Workers connect to the aggregator over generated loopback OBP v1 links. Worker
|
|
ports are `7001` through `7005`; reciprocal aggregator ports are `7101` through
|
|
`7105`. These links are private to the container.
|
|
|
|
## Session assignment
|
|
|
|
The proxy rotates new DMR IDs through the configured worker ranges. With two
|
|
workers the assignments are:
|
|
|
|
```text
|
|
new session 1 -> worker 1
|
|
new session 2 -> worker 2
|
|
new session 3 -> worker 1
|
|
new session 4 -> worker 2
|
|
```
|
|
|
|
Within the selected worker range, the proxy retains its existing random choice
|
|
of an available generated system port.
|
|
|
|
A DMR ID remains pinned to that exact generated port for the lifetime of its
|
|
active proxy session. Moving it would start a new HBP login and reset its
|
|
BRIDGES and OPTIONS state. The proxy does not rebalance or fail over an active
|
|
session. Once the session expires, a later login by the same DMR ID is a new
|
|
assignment. Affinity is not persisted across proxy restarts.
|
|
|
|
Existing explicit proxy configurations using `DestportStart` and `DestportEnd`
|
|
continue to describe one range. The equivalent direct multi-range setting is:
|
|
|
|
```ini
|
|
[PROXY]
|
|
BackendPortRanges: [[54000, 54099], [54100, 54199]]
|
|
```
|
|
|
|
or:
|
|
|
|
```sh
|
|
FDPROXY_BACKEND_PORT_RANGES='[[54000,54099],[54100,54199]]'
|
|
```
|
|
|
|
The standard HDStack entrypoint supplies this setting automatically.
|
|
|
|
## Proxy diagnostics
|
|
|
|
In multi-worker mode the proxy logs each backend number and port range during
|
|
startup. With the standard two-worker layout this includes:
|
|
|
|
```text
|
|
(PROXY)(HDSTACK) Backend:1 ports:54000-54099.
|
|
(PROXY)(HDSTACK) Backend:2 ports:54100-54199.
|
|
```
|
|
|
|
When `FDPROXY_CLIENTINFO=1`, as in the shipped Compose configuration, client
|
|
assignment and removal messages include both the backend number and exact
|
|
generated port. This makes round-robin assignment and retained session
|
|
affinity visible without enabling packet-level debug logging. Single-backend
|
|
startup output remains unchanged.
|
|
|
|
## Reporting MUX
|
|
|
|
When reporting is enabled in the main configuration, worker report ports are
|
|
derived from its `REPORT_PORT`. With the default output port `4321`:
|
|
|
|
```text
|
|
MUX output -> 4321
|
|
worker 1 -> 4322
|
|
worker 2 -> 4323
|
|
worker 3 -> 4324
|
|
worker 4 -> 4325
|
|
worker 5 -> 4326
|
|
```
|
|
|
|
The MUX preserves the existing netstring reporting protocol and the main
|
|
configuration's `REPORT_CLIENTS` allow-list. It merges worker configuration
|
|
and bridge snapshots and relays worker bridge events. System names are
|
|
prefixed with the stable worker number to prevent collisions:
|
|
|
|
```text
|
|
1:SYSTEM-001
|
|
2:SYSTEM-001
|
|
```
|
|
|
|
Only the system-name field is changed. The reporting protocol contains trusted
|
|
Python pickle data and must remain on a trusted network.
|
|
|
|
A failed or malformed worker reporting source is isolated from healthy
|
|
sources. Reporting failure does not affect the proxy or DMR traffic. If main
|
|
reporting is disabled, worker reporting and the MUX are both disabled.
|
|
|
|
## Limitations
|
|
|
|
HDStack deliberately provides no least-connections balancing, active backend
|
|
failover, live migration, persistent affinity or automatic reconfiguration.
|
|
A failed worker does not cause its active sessions to move to another worker.
|
|
The separate bridge config and rules remain sysop-managed; the runtime
|
|
generator does not create routing policy.
|