feat: make gRPC max message size consistently configurable - #2173
feat: make gRPC max message size consistently configurable#2173andygrove wants to merge 6 commits into
Conversation
At SF1000, some TPC-H plans (Q11, Q21, Q22) encode above the 16 MiB
default gRPC message-size ceiling, so submitting them fails with:
Status { code: OutOfRange, message: "Error, decoded message length
too large: found ~22 MB, the limit is: 16777216 bytes" }
Raising the runtime flags on scheduler and executor pods only lifts the
server-side receive limits. Several paths still use
`GrpcClientConfig::default()` (16 MiB) unconditionally — most notably
the scheduler-to-executor client in `ExecutorManager::new` — so
task-assignment RPCs with large plans reject even when the servers were
raised.
Bump every default that fed a 16 MiB ceiling to 128 MiB:
- ballista/core/src/config.rs — `BALLISTA_CLIENT_GRPC_MAX_MESSAGE_SIZE`
default (SessionConfig-driven client path).
- ballista/core/src/utils.rs — `GrpcClientConfig::default()`
`max_message_size` (used by scheduler-to-executor, flight proxy,
executor client pool default lookups).
- ballista/scheduler/src/config.rs and
ballista/executor/src/config.rs — both CLI flags
(`--grpc-server-max-{decoding,encoding}-message-size`) and the
matching struct defaults.
- ballista/executor/src/executor_process.rs — matching
ExecutorProcessConfig defaults.
The value is a ceiling, not a preallocation, so bumping it has no
runtime cost for messages below the old limit.
Adds a round-trip test confirming that
`ballista.client.grpc_max_message_size` set on a SessionConfig reaches
`BallistaConfig::grpc_client_max_message_size()` unchanged, since that
path (options.set -> ExtensionOptions -> get_usize_setting) had no
existing coverage.
Updates the `default_config` unit test to reflect the new default.
Signed-off-by: Andy Grove <agrove@apache.org>
Signed-off-by: Andy Grove <agrove@apache.org>
Bumping GrpcClientConfig::default().max_message_size to 128 MiB helps most cases but leaves no runtime knob for the scheduler's outbound gRPC client to executors — the client the task-assignment RPC actually flows through. Its config was only overridable via a Rust-side `override_config_producer`, which end users of the shipped binary can't set. Add `--grpc-client-max-message-size` on the scheduler CLI (default 134217728 == the new default), and use it to override `GrpcClientConfig::max_message_size` in `ExecutorManager::new` when no `override_config_producer` is wired. The producer path still takes precedence so embedders keep full control. Users can now scale beyond 128 MiB without recompiling. Signed-off-by: Andy Grove <agrove@apache.org>
|
There is also outstanding pr which helps reducing message size #1853 |
phillipleblanc
left a comment
There was a problem hiding this comment.
Looks good to me, one thing to check is whether we want to wire this into create_grpc_client_endpoint to pass along the max message size value.
i.e.
SchedulerConfig.grpc_client_max_message_size
v
GrpcClientConfig.max_message_size
v
create_grpc_client_endpoint(config) // here
v
ExecutorGrpcClient::new(channel)
create_grpc_client_endpoint reads settings such as:
- connection timeout
- keepalive interval
- HTTP/2 window sizes
But it never reads config.max_message_size. Message-size limits are Tonic codec settings, not HTTP/2 Endpoint settings.
It would need something like:
let client = ExecutorGrpcClient::new(connection)
.max_encoding_message_size(grpc_client_config.max_message_size)
.max_decoding_message_size(grpc_client_config.max_message_size);Co-authored-by: Martin Grigorov <martin-g@users.noreply.github.com>
Co-authored-by: Martin Grigorov <martin-g@users.noreply.github.com>
|
I wonder whether 128MiB is too much ?! |
…y configurable Revert the default bump and instead close the gaps that made the ceiling unconfigurable: the scheduler's outbound gRPC clients now honour a `--grpc-client-max-message-size` flag, and `ExecutorManager` applies that limit to the tonic codec so it is no longer silently dropped.
|
Thanks both, I've reworked this based on your feedback and updated the title and description. @martin-g fair point about losing the signal that messages are getting heavy. I've dropped the default bump entirely, so everything stays at 16 MiB and optimisations like #1853 still get noticed when a message grows too big. The PR is now only about making the ceiling configurable where it wasn't, so operators who genuinely need a bigger one can raise it. I've also taken your MiB wording suggestions, just with the value left at 16MiB. @phillipleblanc good catch, and it turned out to be worse than "not wired". The net diff against main is now purely additive. One new scheduler flag, |
Which issue does this PR close?
Related to #2168.
Rationale for this change
At SF1000 several TPC-H plans (Q11, Q21, Q22) encode above the 16 MiB gRPC message-size ceiling and fail with:
The obvious remedy is to raise the limit, but today that isn't reliably possible. Raising the runtime flags on the scheduler/executor pods (
--grpc-server-max-*-message-size=...) only lifts the server-side receive limits, and the scheduler-to-executor path ignores the setting entirely:ExecutorManager::newbuilds aGrpcClientConfigbut falls back toGrpcClientConfig::default()(16 MiB) with no way to override it short of writing a config producer in Rust.ExecutorManager::get_clientthen constructsExecutorGrpcClient::new(connection)without ever applyingmax_message_size. Message-size limits are tonic codec settings rather thanEndpointsettings, socreate_grpc_client_endpointcan't apply them, and the value that was carefully computed is silently dropped. Every other client construction in the codebase (executor_process.rs,executor_server.rs,standalone.rs,flight_proxy_service.rs) does apply it — this one path did not.So a user hitting the ceiling on task assignment has no supported knob to turn.
An earlier revision of this PR raised the defaults to 128 MiB. Per review feedback from @martin-g that a large default makes it harder to notice messages growing too heavy (and works against optimisations like #1853), the default stays at 16 MiB. This PR now only makes the ceiling consistently configurable, so operators who need a larger one can set it.
What changes are included in this PR?
ballista/scheduler/src/config.rs— new--grpc-client-max-message-sizeflag plus the matchingSchedulerConfigfield andwith_grpc_client_max_message_sizebuilder, defaulting to 16 MiB (unchanged behaviour).ballista/scheduler/src/state/executor_manager.rs:ExecutorManager::newuses that flag when nooverride_config_produceris wired. An explicit config producer still wins, so embedders keep full control.get_clientappliesmax_encoding_message_size/max_decoding_message_sizetoExecutorGrpcClient, so the configured limit actually takes effect (per @phillipleblanc's review).--grpc-server-max-*-message-sizeflags now state the default inMiBconsistently (@martin-g's suggestions, with the value left at 16 MiB).No default value changes, so
docs/source/user-guide/configs.mdis unchanged.New tests:
ballista-scheduler:--grpc-client-max-message-sizereachesExecutorManager's client config, and anoverride_config_producerstill takes precedence over it.ballista-core: round-trip test thatballista.client.grpc_max_message_size, set on aSessionConfigviaoptions_mut().set(...), reachesBallistaConfig::grpc_client_max_message_size()unchanged. That path (options.set→ExtensionOptions→get_usize_setting) had no existing coverage, and it's the one Python clients rely on via theircluster_configoverrides.Are there any user-facing changes?
One new scheduler CLI flag,
--grpc-client-max-message-size(default 16 MiB, i.e. what the scheduler already used). No behaviour changes for existing configurations, and no breaking API changes.