Expand description
ginepro
offers an enriched tonic Channel
using a pluggable service discovery
to periodcally update the active set of gRPC
servers.
Simple example
#[tokio::main]
async fn main() {
use ginepro::LoadBalancedChannel;
use shared_proto::pb::tester_client::TesterClient;
use std::convert::TryInto;
// Create a load balanced channel with the default lookup implementation.
let load_balanced_channel = LoadBalancedChannel::builder(("my.hostname", 5000))
.channel()
.await
.expect("failed to construct LoadBalancedChannel");
let tester_client = TesterClient::new(load_balanced_channel);
}
LoadBalancedChannel
also allows plugging in a different implementation of LookupService
.
use ginepro::{LookupService, ServiceDefinition};
use std::collections::HashSet;
use std::net::SocketAddr;
// This does nothing
struct DummyLookupService;
#[async_trait::async_trait]
impl LookupService for DummyLookupService {
async fn resolve_service_endpoints(
&self,
_definition: &ServiceDefinition,
) -> Result<HashSet<SocketAddr>, anyhow::Error> {
Ok(HashSet::new())
}
}
#[tokio::main]
async fn main() {
use ginepro::LoadBalancedChannel;
use shared_proto::pb::tester_client::TesterClient;
use std::convert::TryInto;
// Create a load balanced channel with the default lookup implementation.
let load_balanced_channel = LoadBalancedChannel::builder(("my.hostname", 5000))
.lookup_service(DummyLookupService)
.channel()
.await
.expect("failed to construct LoadBalancedChannel");
let tester_client = TesterClient::new(load_balanced_channel);
}
For systems with lower churn, the probe interval can be lowered.
#[tokio::main]
async fn main() {
use ginepro::{LoadBalancedChannel, LoadBalancedChannelBuilder};
use shared_proto::pb::tester_client::TesterClient;
use std::convert::TryInto;
let load_balanced_channel = LoadBalancedChannelBuilder::new_with_service(("my.hostname", 5000))
.dns_probe_interval(std::time::Duration::from_secs(3))
.channel()
.await
.expect("failed to construct LoadBalancedChannel");
let tester_client = TesterClient::new(load_balanced_channel);
}
It’s also possible to associate a timeout for every new endpoint that the
LoadBalancedChannel
tries to connect to.
.
#[tokio::main]
async fn main() {
use ginepro::LoadBalancedChannel;
use shared_proto::pb::tester_client::TesterClient;
use std::convert::TryInto;
let load_balanced_channel = LoadBalancedChannel::builder(("my.hostname", 5000))
.timeout(std::time::Duration::from_secs(10))
.channel()
.await
.expect("failed to construct LoadBalancedChannel");
let tester_client = TesterClient::new(load_balanced_channel);
}
It’s also possible to eagerly resolve the service endpoints once before
LoadBalancedChannel
is constructed.
.
#[tokio::main]
async fn main() {
use ginepro::{LoadBalancedChannel, ResolutionStrategy};
use shared_proto::pb::tester_client::TesterClient;
use std::time::Duration;
use std::convert::TryInto;
let load_balanced_channel = LoadBalancedChannel::builder(("my.hostname", 5000))
.timeout(std::time::Duration::from_secs(10))
.resolution_strategy(ginepro::ResolutionStrategy::Eager {
timeout: Duration::from_secs(20),
})
.channel()
.await
.expect("failed to construct LoadBalancedChannel");
let tester_client = TesterClient::new(load_balanced_channel);
}
Internals
The tonic Channel
exposes the function
balance_channel
which returnes a bounded channel through which
endpoint changes can be sent.
ginepro
uses this message passing mechanism to report when servers are added and removed.
Structs
Implements LookupService
by using DNS queries to lookup ServiceDefinition::hostname
.
Implements tonic GrpcService
for a client-side load balanced Channel
(using The Power of Two Choices
).
Builder to configure and create a LoadBalancedChannel
.
Defines a gRPC service with a hostname
and a port
.
The hostname will be resolved to the concrete ips of the service servers.
Enums
Enumerates the different domain name resolution strategies that
the LoadBalancedChannelBuilder
supports.
Traits
Interface that provides functionality to acquire a list of ips given a valid host name.