| Crates.io | warm_channels |
| lib.rs | warm_channels |
| version | 0.2.1 |
| created_at | 2025-01-16 21:32:52.631467+00 |
| updated_at | 2025-06-29 18:51:51.997626+00 |
| description | Always-ready HTTP client channels for gRPC or other RPC-like requests. |
| homepage | https://github.com/vandry/warm_channels |
| repository | https://github.com/vandry/warm_channels.git |
| max_upload_size | |
| id | 1519967 |
| size | 284,895 |
Always-ready HTTP client channels for gRPC or other RPC-like requests.
In a microservices environment, components usually serve RPCs from their clients in part by making further requests to backends of their own. For example an application frontend serves a request by making a query to a storage backend and a notification queue before applying business logic and constructing a response to send to its own client, the end user.
When RPC frontends and backends are both replicated as multiple tasks, discipline in managing and load balancing the flow of requests is important. This crate aims to offer the client side of that function.
The main focus is on offering an always-ready gRPC client channel type
(in the [grpc] module) which load-balances over multiple individual
actively health-checked connections. A generic HTTP client channel typr
(in the [http] module) is also provided but it is currently less
polished.
The building blocks revolve around [tower] (for the service stack) and
[hyper] (for HTTP), plus [tokio] and rustls. In particular, the
basic load balancing uses [tower::balance::p2c]. Finally, the gRPC
layer on top is designed to be used with tonic.
Some of the features brought by this crate are:
tower::balance::p2c::Balance], which only polls (and potentially
evicts) members on use.This crate can be used by itself but is designed to be used with
comprehensive which will further add the following features:
use std::sync::Arc;
use trust_dns_resolver::system_conf::read_system_conf;
use trust_dns_resolver::TokioAsyncResolver;
let (resolver_config, mut resolver_opts) = read_system_conf().unwrap();
let r = Arc::new(TokioAsyncResolver::tokio(resolver_config, resolver_opts));
let uri = "https://example.org".try_into().unwrap();
let stream = warm_channels::resolve_uri(&uri, r).unwrap();
let (stack, worker) = warm_channels::grpc_channel(
uri.clone(),
warm_channels::grpc::GRPCChannelConfig::default(),
"demo",
warm_channels::stream::TCPConnector::default(),
stream,
|h| println!("healthy: {}", h),
);
tokio::task::spawn(worker);
let client = pb::test_client::TestClient::with_origin(stack, uri);
println!("{:?}", client.greet(tonic::Request::new(())).await);
comprehensiveuse comprehensive_grpc::GrpcClient;
#[derive(GrpcClient)]
struct Client(
pb::test_client::TestClient<comprehensive_grpc::client::Channel>,
comprehensive_grpc::client::ClientWorker,
);
Client may then be included as a dependency in a Comprehensive Assembly.
See the full gRPC hello world client example.
All are enabled by default.