google grpc 快速入門(mén)

為什么去使用gRPC

使用gRPC,我們可以在.proto文件中定義我們的服務(wù),并以任何gRPC支持的語(yǔ)言實(shí)現(xiàn)客戶(hù)端和服務(wù)器。 使用gRPC還具有protocol buffer的所有優(yōu)點(diǎn),包括高效的序列化,簡(jiǎn)單的IDL和簡(jiǎn)單的接口更新。

自己認(rèn)為rpc框架的優(yōu)點(diǎn)主要在于,性能好(使用高效的序列化框架,tcp傳輸協(xié)議),跨語(yǔ)言(服務(wù)端和客戶(hù)端可以使用不同的語(yǔ)言開(kāi)發(fā))。

引入依賴(lài)

使用maven構(gòu)建項(xiàng)目,maven依賴(lài):

<dependency>
  <groupId>io.grpc</groupId>
  <artifactId>grpc-netty</artifactId>
  <version>1.4.0</version>
</dependency>
<dependency>
  <groupId>io.grpc</groupId>
  <artifactId>grpc-protobuf</artifactId>
  <version>1.4.0</version>
</dependency>
<dependency>
  <groupId>io.grpc</groupId>
  <artifactId>grpc-stub</artifactId>
  <version>1.4.0</version>
</dependency>

使用Gradle構(gòu)建項(xiàng)目,Gradle依賴(lài):

compile 'io.grpc:grpc-netty:1.4.0'
compile 'io.grpc:grpc-protobuf:1.4.0'
compile 'io.grpc:grpc-stub:1.4.0'

Android開(kāi)發(fā),使用grpc-okhttp代替grpc-netty,使用grpc-protobuf-lite,或者grpc-protobuf-nano代替grpc-protobuf

compile 'io.grpc:grpc-okhttp:1.4.0'
compile 'io.grpc:grpc-protobuf-lite:1.4.0'
compile 'io.grpc:grpc-stub:1.4.0'

使用插件根據(jù)指定的.proto文件生成代碼,要將.proto文件放在src/main/protosrc/test/proto目錄下,這樣插件就可以找到.proto文件并且生成代碼。

使用maven插件如下:

<build>
  <extensions>
    <extension>
      <groupId>kr.motd.maven</groupId>
      <artifactId>os-maven-plugin</artifactId>
      <version>1.4.1.Final</version>
    </extension>
  </extensions>
  <plugins>
    <plugin>
      <groupId>org.xolstice.maven.plugins</groupId>
      <artifactId>protobuf-maven-plugin</artifactId>
      <version>0.5.0</version>
      <configuration>
        <protocArtifact>com.google.protobuf:protoc:3.3.0:exe:${os.detected.classifier}</protocArtifact>
        <pluginId>grpc-java</pluginId>
        <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.4.0:exe:${os.detected.classifier}</pluginArtifact>
      </configuration>
      <executions>
        <execution>
          <goals>
            <goal>compile</goal>
            <goal>compile-custom</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>

或者使用gradle插件:

apply plugin: 'java'
apply plugin: 'com.google.protobuf'

buildscript {
  repositories {
    mavenCentral()
  }
  dependencies {
    // ASSUMES GRADLE 2.12 OR HIGHER. Use plugin version 0.7.5 with earlier
    // gradle versions
    classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.0'
  }
}

protobuf {
  protoc {
    artifact = "com.google.protobuf:protoc:3.2.0"
  }
  plugins {
    grpc {
      artifact = 'io.grpc:protoc-gen-grpc-java:1.4.0'
    }
  }
  generateProtoTasks {
    all()*.plugins {
      grpc {}
    }
  }
}

build.gradle中加入相應(yīng)的插件之后,idea出現(xiàn)gradle插件圖形顯示

gradle插件

如果要將.proto文件放在其他路徑,可以加入下面的指令:

sourceSets {
  main {
    proto {
      // In addition to the default 'src/main/proto'
      srcDir 'src/main/protobuf'
      srcDir 'src/main/protocolbuffers'
      // In addition to the default '**/*.proto' (use with caution).
      // Using an extension other than 'proto' is NOT recommended,
      // because when proto files are published along with class files, we can
      // only tell the type of a file from its extension.
      include '**/*.protodevel'
    }
    java {
      ...
    }
  }
  test {
    proto {
      // In addition to the default 'src/test/proto'
      srcDir 'src/test/protocolbuffers'
    }
  }
}

相應(yīng)的gradle插件的配置說(shuō)明

編寫(xiě).proto文件

src/main/proto目錄下編寫(xiě)Student.proto文件

syntax = "proto3";

package com.zhihao.miao.proto;

option java_package = "com.zhihao.miao.proto";
option java_outer_classname ="StudentProto";
//將屬性生成多個(gè)文件,便于代碼管理
option java_multiple_files = true;

//定義rpc方法
service StudentService{

    //一元RPC
    rpc GetRealNameByUsername(MyRequest) returns (MyResponse){}
}

message MyRequest{
    string username = 1;
}

message MyResponse{
    string realname = 2;
}

使用gradle插件編譯

gradle generateProto 
生成的代碼

將生成的代碼copy到main/java的制定的包下,生成的類(lèi)有以下幾個(gè),MyRequestMyRequestOrBuilder,MyResponse,MyResponseOrBuilderStudentProto是GRPC消息傳輸?shù)腗essage,后面的一個(gè)StudentServiceGrpc類(lèi)是遠(yuǎn)程調(diào)用的接口,服務(wù)端要重寫(xiě).proto中的方法要實(shí)現(xiàn)其內(nèi)部類(lèi)StudentServiceImplBase

編寫(xiě)服務(wù)器代碼

服務(wù)端業(yè)務(wù)接口實(shí)現(xiàn)

package com.zhihao.miao.gprc;

import com.zhihao.miao.proto.*;
import io.grpc.stub.StreamObserver;

public class StudentServiceImpl extends StudentServiceGrpc.StudentServiceImplBase{


    //第一個(gè)對(duì)象是請(qǐng)求參數(shù)對(duì)象,第二個(gè)參數(shù)是向客戶(hù)端返回結(jié)果的對(duì)象,方法定義不返回值,而是通過(guò)responseObserver去返回值
    @Override
    public void getRealNameByUsername(MyRequest request, StreamObserver<MyResponse> responseObserver) {
        System.out.println("接收到客戶(hù)端信息: "+request.getUsername());

        //onNext,onError,onCompletedB表示方法都是回調(diào)方法
        responseObserver.onNext(MyResponse.newBuilder().setRealname("王超").build());

        //onCompletedB表示方法方法執(zhí)行完畢
        responseObserver.onCompleted();


    }
}

編寫(xiě)服務(wù)器代碼
編寫(xiě)服務(wù)器端代碼,參考快速入門(mén)的服務(wù)端代碼,HelloWorldServer.java類(lèi)

cd /Users/naeshihiroshi/study/studySummarize/netty/grpc-java/examples
cd src/main/java/io/grpc/examples/helloworld

參考

服務(wù)器端代碼:

import io.grpc.Server;
import io.grpc.ServerBuilder;

import java.io.IOException;

public class GrpcServer {

    private Server server;

    //編寫(xiě)服務(wù)啟動(dòng)方法
    private void start() throws IOException{
        //增加實(shí)際業(yè)務(wù)代碼的實(shí)列,如果使用spring的話(huà)可以直接將StudentServiceImpl對(duì)象注入進(jìn)來(lái)
        this.server = ServerBuilder.forPort(8899).addService(new StudentServiceImpl()).build().start();

        System.out.println("server start!");

        //jvm回調(diào)鉤子的作用,Runtime.getRuntime()可以獲得java一些運(yùn)行期間的一些信息。
        //不管程序是正常關(guān)閉還是異常終端,在jvm關(guān)閉的時(shí)候做一些清理工作
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            System.out.println("關(guān)閉jvm");
            GrpcServer.this.stop();
            System.out.println("服務(wù)關(guān)閉");
        }));

        System.out.println("執(zhí)行到這里");
    }

    //停止服務(wù)器
    private void stop(){
        if(null != this.server){
            this.server.shutdown();
        }
    }

    //服務(wù)器阻塞
    private void blockUntilShutdown() throws InterruptedException {
        if(null != this.server){
            this.server.awaitTermination();
            //this.server.awaitTermination(3000, TimeUnit.MILLISECONDS);
        }
    }

    public static void main(String[] args) throws IOException,InterruptedException{
        GrpcServer server = new GrpcServer();

        server.start();;
        server.blockUntilShutdown();
    }
}

客戶(hù)端代碼:

import com.zhihao.miao.proto.*;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import io.grpc.stub.StreamObserver;

import java.time.LocalDateTime;
import java.util.Iterator;

public class GrpcClient {

    public static void main(String[] args) throws Exception{
        ManagedChannel managedChannel = ManagedChannelBuilder.forAddress("localhost",8899)
                //使用TLS來(lái)連接服務(wù)端
                .usePlaintext(true).build();

        //定義一個(gè)stub,用于實(shí)際和服務(wù)端連接的對(duì)象blockingStub
        StudentServiceGrpc.StudentServiceBlockingStub blockingStub = StudentServiceGrpc.newBlockingStub(managedChannel);

        MyResponse response =blockingStub.getRealNameByUsername(MyRequest.newBuilder()
                .setUsername("chao.wang").build());

        System.out.println(response.getRealname());
    }
}

運(yùn)行客戶(hù)端與服務(wù)器端,服務(wù)器端控制臺(tái)打?。?/p>

server start!
執(zhí)行到這里
接收到客戶(hù)端信息: chao.wang

客戶(hù)端控制臺(tái)打?。?/p>

王超
Disconnected from the target VM, address: '127.0.0.1:63197', transport: 'socket'

Process finished with exit code 0

關(guān)閉服務(wù)器,服務(wù)器控制臺(tái)上打印,執(zhí)行jvm回調(diào)鉤子。:

關(guān)閉jvm
服務(wù)關(guān)閉

參考資料

官網(wǎng)java指南
github地址

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • GRPC是基于protocol buffers3.0協(xié)議的. 本文將向您介紹gRPC和protocol buffe...
    二月_春風(fēng)閱讀 18,207評(píng)論 2 28
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 47,256評(píng)論 6 342
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,812評(píng)論 25 709
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,506評(píng)論 19 139
  • 每個(gè)人都會(huì)碰到喜歡的人,可怕的是,他是男人,我也是。 我們距離最近的時(shí)候,是我背著他,唱著歌,向我的洞府走去。 我...
    閷Ne貝良閱讀 348評(píng)論 0 0

友情鏈接更多精彩內(nèi)容