gRPCラーニングレコード(6)--クライアント接続プール

11055 ワード

クライアントにとってチャネルを確立するのは高価であり、チャネルを作成するには接続が必要であるが、stubを確立することは一般的なオブジェクトを作成するように簡単であるため、チャネルは多重化、すなわち接続プールアプリケーションを実現する必要がある.本明細書では、commons-pool2を用いる接続プールアプリケーションを実現する.このケースは、接続プールのテンプレートのケースとすることができる.
        
        <dependency>
            <groupId>org.apache.commonsgroupId>
            <artifactId>commons-pool2artifactId>
            <version>2.4.2version>
        dependency>

書き方のパッケージは私のもう一つの博文に似ています:Redis学習記録(二)--Jedis接続を使ってSpringJdbcTemplateテンプレート類の書き方を真似します.
まず、コールバックインタフェースを定義する.
public interface WorkCallBack<S> {

  void callback(S s);
}

さらに、接続プールを生成する工場を定義するには、接続プールを生成するために必要なクライアントを使用するBasePooledObjectFactoryから継承する必要がある.
public class HelloWorldFactory extends BasePooledObjectFactory<HelloWorldClientSingle> {

  private String host = "127.0.0.1";

  private int port = 50051;

  @Override
  public HelloWorldClientSingle create() throws Exception {
    return new HelloWorldClientSingle(this.host,this.port);
  }

  @Override
  public PooledObject wrap(HelloWorldClientSingle helloWorldClientSingle) {
    return new DefaultPooledObject<>(helloWorldClientSingle);
  }

  @Override
  public void destroyObject(PooledObject p) throws Exception {
    p.getObject().shutdown();
    super.destroyObject(p);
  }
}

対応する接続プールを実現するには、execute()の方法を参照してください.この方法はテンプレート方法であり、プールからクライアントを取得し、接続プールに返却することを行い、その主な論理はWorkCallBackインタフェースに定義されているので、サービス側から持ち帰ったデータもその中で処理しなければなりません.
public class HelloWorldClientPool {

  private static GenericObjectPool objectPool = null;

  static {
    //       
    GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig();
    //         
    poolConfig.setMaxTotal(8);
    //         
    poolConfig.setMinIdle(0);
    //         
    poolConfig.setMaxIdle(8);
    //          ,          ,          :   
    poolConfig.setMaxWaitMillis(-1);
    //            ,true         ,false        
    poolConfig.setLifo(true);
    //          ,               ,    30  
    poolConfig.setMinEvictableIdleTimeMillis(1000L * 60L * 30L);
    //          ,   true
    poolConfig.setBlockWhenExhausted(true);
    //      
    objectPool = new GenericObjectPool<>(new HelloWorldFactory(), poolConfig);
  }

  /**
   *         
   */
  private static HelloWorldClientSingle borrowObject(){
    try {
      HelloWorldClientSingle clientSingle = objectPool.borrowObject();
      System.out.println("      "+objectPool.getCreatedCount());
      return clientSingle;
    } catch (Exception e) {
      e.printStackTrace();
    }
    //          
    return createClient();
  }

  /**
   *       ,       
   */
  private static HelloWorldClientSingle createClient(){
    return new HelloWorldClientSingle("127.0.0.1", 55001);
  }

  /**
   *    
   * @param workCallBack       
   */
  public static Runnable execute(WorkCallBack workCallBack){
    return () -> {
      HelloWorldClientSingle client = borrowObject();
      try {
       workCallBack.callback(client);
      } finally {
        /**             */
        objectPool.returnObject(client);
      }
    };
  }

}

クライアントにとって、ルートは共有できないので、ルートは呼び出し関数にインスタンス化し、パフォーマンスの問題を心配しないでください.この操作はオブジェクトを作成することです.greeterBlockingStub = GreeterGrpc.newBlockingStub(channel).withCompression("gzip");このコードは、前のコンストラクタからgreetにシフト.
public class HelloWorldClientSingle {

    private final ManagedChannel channel; //  gRPC  
    private GreeterGrpc.GreeterBlockingStub greeterBlockingStub;//  /     

   //        
    public HelloWorldClientSingle(String host,int port){
      channel = ManagedChannelBuilder.forAddress(host, port).usePlaintext(true).build();
    }

    public void shutdown() throws InterruptedException {
        channel.shutdown().awaitTermination(5, TimeUnit.SECONDS);
    }

    //     
    public  void greet(String name){
        //         ,    
        greeterBlockingStub = GreeterGrpc.newBlockingStub(channel).withCompression("gzip");
        HelloRequest request = HelloRequest.newBuilder().setName(name).build();
        HelloReply response;
        try {
            response = greeterBlockingStub.sayHello(request);
        } catch (StatusRuntimeException e) {
            System.out.println("RPC    :"+e.getMessage());
            return;
        }
        System.out.println("       :"+response.getMessage());
    }
}

簡単なテストクラスを書く
public class HelloWorldClientTest {

  public static void main(String[] args) {
    for (int i = 0; i < 100; i++) {
      new Thread( HelloWorldClientPool.execute(clientSingle -> {
          clientSingle.greet("world");
      })).start();
    }
  }
}

私が限定した8つのクライアントなので、最高でも8つのチャンネルでまた走りました.
Paste_Image.png
参考文献:http://zk-chs.iteye.com/blog/2308730
コードアドレス:https://github.com/nl101531/JavaWEB
作者:このブログは破棄されました_個人ブログで更新
リンク:https://www.jianshu.com/p/267078010c68
出典:簡書
著作権は作者の所有である.商業転載は著者に連絡して許可を得てください.非商業転載は出典を明記してください.