zoukankan      html  css  js  c++  java
  • Java 开发 gRPC 服务和客户端

    一、gRPC 简介

    gRPC 是Go实现的:一个高性能,开源,将移动和HTTP/2放在首位通用的RPC框架。使用gRPC可以在客户端调用不同机器上的服务端的方法,而客户端和服务端的开发语言和

    运行环境可以有很多种,基本涵盖了主流语言和平台。双方交互的协议可以在proto文件中定义,客户端和服务端可以很方便的通过工具生成协议和代理代码。而消息的编码是采

    google protocol buffer,数据量小、速度快。

    gRPC具有以下特点:

    (1)基于 HTTP/2, 继而提供了连接多路复用、Body 和 Header 压缩等机制。可以节省带宽、降低TCP链接次数、节省CPU使用和延长电池寿命等。

    (2)支持主流开发语言(C, C++, Python, PHP, Ruby, NodeJS, C#, Objective-C、Golang、Java)

    (3)IDL (Interface Definition Language) 层使用了 Protocol Buffers, 非常适合团队的接口设计

    下面我们就通过一个java的例子来看看怎么使用gRPC。

    二、配置pom文件,导入gRPC的依赖和插件

    新的工程创建出来之后,我们就可以先配置基础的maven相关的配置了,这里我们可以抄袭下官网的相关配置:

    <properties>
      <grpc.version>1.4.0</grpc.version><!-- CURRENT_GRPC_VERSION -->
    </properties>
    <dependencies>
      <dependency>
        <groupId>io.grpc</groupId>
        <artifactId>grpc-netty</artifactId>
        <version>${grpc.version}</version>
      </dependency>
      <dependency>
        <groupId>io.grpc</groupId>
        <artifactId>grpc-protobuf</artifactId>
        <version>${grpc.version}</version>
      </dependency>
      <dependency>
        <groupId>io.grpc</groupId>
        <artifactId>grpc-stub</artifactId>
        <version>${grpc.version}</version>
      </dependency>
      <dependency>
        <groupId>io.grpc</groupId>
        <artifactId>grpc-testing</artifactId>
        <version>${grpc.version}</version>
        <scope>test</scope>
      </dependency>
      <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.11</version>
        <scope>test</scope>
      </dependency>
      <dependency>
        <groupId>org.mockito</groupId>
        <artifactId>mockito-core</artifactId>
        <version>1.9.5</version>
        <scope>test</scope>
      </dependency>
    </dependencies>
    <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:${grpc.version}:exe:${os.detected.classifier}</pluginArtifact>
           </configuration>
          <executions>
            <execution>
              <goals>
                <goal>compile</goal>
                <goal>compile-custom</goal>
              </goals>
            </execution>
          </executions>
        </plugin>
      </plugins>
    </build>

    三、编写 proto 文件,并编译产生对应的 java文件

    简单起见,这里直接用的 helloworld.proto 文件,内容如下:

    syntax = "proto3";

    option java_multiple_files = true; 
    option java_package = "io.grpc.examples.helloworld"; 
    option java_outer_classname = "HelloWorldProto"; 
    option objc_class_prefix = "HLW";

    package helloworld;

    // The greeting service definition. 
    service Greeter { 
      // Sends a greeting 
      rpc SayHello (HelloRequest) returns (HelloReply) {} 
    }

    // The request message containing the user's name. 
    message HelloRequest { 
      string name = 1; 
    }

    // The response message containing the greetings 
    message HelloReply { 
      string message = 1; 

    这里注意下:如果客户端和服务端使用的语言不同,例如客户端使用Java,服务端是C++,务必保持 proto文件完全一致。

    之后我们参看官网给的教程进行编写服务端以及客户端的信息情况,在写好proto之后进行mvn install一下就会在target文件夹的相应目录下创建出了默认的类

    此时,我们只需要将这些类复制到我们java代码的目录中去,并开发服务端和客户端即可。

    四、服务端开发

    服务端代码如下,运行这个类的 main 方法,就可以在 50051 端口启动服务。

    public class HelloWorldServer {

        private static final Logger logger = Logger.getLogger(HelloWorldServer.class.getName());


        private int port = 50051; 
        private Server server;

        private void start() throws IOException{ 
            server = ServerBuilder.forPort(port) 
                    .addService(new GreeterImpl()) 
                    .build() 
                    .start(); 
            logger.info("Server started, listening on "+ port);

            Runtime.getRuntime().addShutdownHook(new Thread(){

                @Override 
                public void run(){

                    System.err.println("*** shutting down gRPC server since JVM is shutting down"); 
                    HelloWorldServer.this.stop(); 
                    System.err.println("*** server shut down"); 
                } 
            }); 
        }

        private void stop(){ 
            if (server != null){ 
                server.shutdown(); 
            } 
        }

        // block 一直到退出程序 
        private void blockUntilShutdown() throws InterruptedException { 
            if (server != null){ 
                server.awaitTermination(); 
            } 
        }


        public  static  void main(String[] args) throws IOException, InterruptedException {

            final HelloWorldServer server = new HelloWorldServer(); 
            server.start(); 
            server.blockUntilShutdown(); 
        }


        // 实现 定义一个实现服务接口的类 
        private class GreeterImpl extends GreeterGrpc.AbstractGreeter {

            @Override 
            public void sayHello(HelloRequest req,StreamObserver<HelloReply> responseObserver){ 
                HelloReply reply = HelloReply.newBuilder().setMessage(("Hello "+req.getName())).build(); 
                responseObserver.onNext(reply); 
                responseObserver.onCompleted(); 
            } 
        } 

    五、客户端开发

    public class HelloWorldClient {

        private final ManagedChannel channel; 
        private final GreeterGrpc.GreeterBlockingStub blockingStub; 
        private static final Logger logger = Logger.getLogger(HelloWorldClient.class.getName());

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

            blockingStub = GreeterGrpc.newBlockingStub(channel); 
        }


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

        public  void greet(String name){ 
            HelloRequest request = HelloRequest.newBuilder().setName(name).build(); 
            HelloReply response; 
            try{ 
                response = blockingStub.sayHello(request); 
            } catch (StatusRuntimeException e) 
            { 
                logger.log(Level.WARNING, "RPC failed: {0}", e.getStatus()); 
                return; 
            } 
            logger.info("Greeting: "+response.getMessage()); 
        }

        public static void main(String[] args) throws InterruptedException { 
            HelloWorldClient client = new HelloWorldClient("127.0.0.1",50051); 
            try{ 
                String user = "world"; 
                if (args.length > 0){ 
                    user = args[0]; 
                } 
                client.greet(user); 
            }finally { 
                client.shutdown(); 
            } 
        } 
    }

  • 相关阅读:
    [][]
    Spark笔记04
    Spark笔记03
    Spark笔记02
    Spark笔记01
    【熟能生巧】使用Screw快速生成数据库文档
    记一次关于jdbcTemplate.queryForList快速Debug及感悟
    【从零单排】Exception实战总结1
    【从零单排】Java性能排查实战模拟
    【从零单排】关于泛型Generic的一些思考
  • 原文地址:https://www.cnblogs.com/junjiang3/p/9096895.html
Copyright © 2011-2022 走看看