1 /* 2 * Copyright 2023 The gRPC Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package io.grpc.examples.customloadbalance; 18 19 import com.google.gson.Gson; 20 import io.grpc.Channel; 21 import io.grpc.Grpc; 22 import io.grpc.InsecureChannelCredentials; 23 import io.grpc.LoadBalancerRegistry; 24 import io.grpc.ManagedChannel; 25 import io.grpc.ManagedChannelBuilder; 26 import io.grpc.NameResolverRegistry; 27 import io.grpc.StatusRuntimeException; 28 import io.grpc.examples.helloworld.GreeterGrpc; 29 import io.grpc.examples.helloworld.HelloReply; 30 import io.grpc.examples.helloworld.HelloRequest; 31 import io.grpc.examples.loadbalance.ExampleNameResolverProvider; 32 import java.util.Map; 33 import java.util.concurrent.TimeUnit; 34 import java.util.logging.Level; 35 import java.util.logging.Logger; 36 37 /** 38 * This client is intended for connecting with the {@code LoadBalanceServer} in the "loadbalance" 39 * example. 40 */ 41 public class CustomLoadBalanceClient { 42 43 private static final Logger logger = Logger.getLogger(CustomLoadBalanceClient.class.getName()); 44 45 private final GreeterGrpc.GreeterBlockingStub blockingStub; 46 CustomLoadBalanceClient(Channel channel)47 public CustomLoadBalanceClient(Channel channel) { 48 blockingStub = GreeterGrpc.newBlockingStub(channel); 49 } 50 greet(String name)51 public void greet(String name) { 52 HelloRequest request = HelloRequest.newBuilder().setName(name).build(); 53 HelloReply response; 54 try { 55 response = blockingStub.sayHello(request); 56 } catch (StatusRuntimeException e) { 57 logger.log(Level.WARNING, "RPC failed: {0}", e.getStatus()); 58 return; 59 } 60 logger.info("Greeting: " + response.getMessage()); 61 } 62 63 main(String[] args)64 public static void main(String[] args) throws Exception { 65 // We need to register the provider of our custom load balancer implementation 66 LoadBalancerRegistry.getDefaultRegistry() 67 .register(new ShufflingPickFirstLoadBalancerProvider()); 68 69 NameResolverRegistry.getDefaultRegistry().register(new ExampleNameResolverProvider()); 70 71 String target = "example:///lb.example.grpc.io"; 72 73 logger.info("Use default first_pick load balance policy"); 74 ManagedChannel channel = Grpc.newChannelBuilder(target, InsecureChannelCredentials.create()) 75 .build(); 76 77 try { 78 CustomLoadBalanceClient client = new CustomLoadBalanceClient(channel); 79 for (int i = 0; i < 5; i++) { 80 client.greet("request" + i); 81 } 82 } finally { 83 channel.shutdownNow().awaitTermination(5, TimeUnit.SECONDS); 84 } 85 86 logger.info("Change to custom shuffling_pick_first policy with a configured random seed"); 87 // The load balancer name in the config needs to match what getPolicyName() in the provider 88 // returns. The randomSeed field we are using also needs to be understood by the provider when 89 // parseLoadBalancingPolicyConfig() gets called. 90 Map<String, ?> serviceConfig = new Gson().fromJson( 91 "{ \"loadBalancingConfig\": " + 92 " [ { \"grpc.examples.customloadbalance.ShufflingPickFirst\": { \"randomSeed\": 123 } } ]" + 93 "}", 94 Map.class); 95 channel = ManagedChannelBuilder.forTarget(target) 96 .defaultServiceConfig(serviceConfig) 97 .usePlaintext() 98 .build(); 99 try { 100 CustomLoadBalanceClient client = new CustomLoadBalanceClient(channel); 101 for (int i = 0; i < 5; i++) { 102 client.greet("request" + i); 103 } 104 } finally { 105 channel.shutdownNow().awaitTermination(5, TimeUnit.SECONDS); 106 } 107 } 108 } 109