This is a gRPC client library that does automatic load-balancing using Agoda.Frameworks.LoadBalancing under the hood. It works by creating a custom gRPC CallInvoker which hold different channels to different servers. CallInvoker will load-balance between channels on each gRPC client method call.
Suppose you have this sample proto file.
syntax = "proto3";
option csharp_namespace = "Example.Proto";
service SampleApi {
rpc SampleRpcMethod (SampleRequest) returns (SampleResponse);
}
message SampleRequest {
string payload = 1;
}
message SampleResponse {
string payload = 1;
}
You will need to create a GrpcChannelManager to get the load-balancing call-invoker. The load-balancing client can be used as if you were using generated gPRC client object.
var channelManager = new GrpcChannelManager(
new string[] { "server1", "server2" },
timeout: TimeSpan.FromMilliseconds(200),
maxRetry: 3);
var lbCallInvoker = channelManager.GetCallInvoker();
var client = new SampleApi.SampleApiClient(lbCallInvoker);
client.SampleRpcMethod(...); // might call server1 or server2
var channelManager = new GrpcChannelManager(
new string[] { "server1", "server2" },
timeout: TimeSpan.FromMilliseconds(200),
maxRetry: 3);
var lbCallInvoker = channelManager.GetCallInvoker();
var client = new SampleApi.SampleApiClient(lbCallInvoker);
This constructor allows you to set custom endpoint weight, weighing strategy, timeout and retry predicate.
var channelManager = new GrpcChannelManager(
new Dictionary<string, WeightItem>()
{
["server1"] = new WeightItem(1000, 1000),
["server2"] = new WeightItem(3000, 3000)
},
new ExponentialWeightManipulationStrategy(10),
timeout: TimeSpan.FromMilliseconds(200),
(retryCount, exception) =>
{
// should retry logic
});
var lbCallInvoker = channelManager.GetCallInvoker();
var client = new SampleApi.SampleApiClient(lbCallInvoker);
Updating resources should be done by using GrpcChannelManager.UpdateResources
.
If you already have the client, updating the GrpcChannelManager will affect the client as well.
var channelManager = new GrpcChannelManager(
new string[] { "server1", "server2" },
timeout: TimeSpan.FromMilliseconds(200));
var lbCallInvoker = channelManager.GetCallInvoker();
var client = new SampleApi.SampleApiClient(lbCallInvoker);
client.SampleRpcMethod(...); // might call server1 or server2
channelManager.UpdateResources(new string[] { "server1", "server3" });
client.SampleRpcMethod(...); // might call server1 or server3, but not server2
The client supports automatic retry for DeadlineExceeded
, Unavailable
and Unknown
status code by default.
The number of retries can be set in the GrpcChannelManager
constructor.
Note that deadline
parameter in each gRPC call will be ignored and the timeout specified in GrpcChannelManager
will be used instead.
But if timeout is set to null, then the load-balancing client will repect the timeout set by deadline
parameter.