gRPC学习记录(二)--Hello World

作者: 此博废弃_更新在个人博客 | 来源:发表于2017-02-03 10:44 被阅读938次

    gRPC学习记录(二)--Hello World

    标签(空格分隔): javaWEB


    在上一篇的整体了解后,该篇则对应了快速上手,入门示例当然仍旧是Hello world,该一阶段不需要深究代码,所要求的的目的是先跑通,再回顾代码,然后分析需要什么知识,再去学什么.


    1.Maven配置

    首先是三个依赖包

     <properties>
            <grpc.version>1.0.3</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>
        </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.1.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>
    
    

    2.编写proto文件

    在main目录下建立一个proto文件夹,然后在里面建立hello.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;
    }
    
    

    接下来执行 mvn compile,就会生成如下代码,如果未被标记为源代码目录的话,就右键标记下:

    Paste_Image.png

    3.编写服务端代码

    public class HelloWorldServer {
    
        private int port = 50051;
        private Server server;
    
        /**
         * 启动服务
         * @throws IOException
         */
        private void start() throws IOException {
            server = ServerBuilder.forPort(port)
                                  .addService(new GreeterImpl())
                                  .build()
                                  .start();
    
            System.out.println("service start...");
    
            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.GreeterImplBase {
    
            public void sayHello(HelloRequest req, StreamObserver<HelloReply> responseObserver) {
                //获取参数
                System.out.println("收到的信息:"+req.getName());
    
                //这里可以放置具体业务处理代码 start
    
                //这里可以放置具体业务处理代码 end
    
                //构造返回
                HelloReply reply = HelloReply.newBuilder().setMessage(("Hello: " + req.getName())).build();
                responseObserver.onNext(reply);
                responseObserver.onCompleted();
            }
        }
    }
    
    

    4.编写客户端代码

    public class HelloWorldClient {
    
        private final ManagedChannel channel; //一个gRPC信道
        private final GreeterGrpc.GreeterBlockingStub blockingStub;//阻塞/同步 存根
    
       //初始化信道和存根
        public HelloWorldClient(String host,int port){
            this(ManagedChannelBuilder.forAddress(host, port)
                                      // Channels are secure by default (via SSL/TLS). For the example we disable TLS to avoid
                                      // needing certificates.
                                      .usePlaintext(true));
        }
    
        /** Construct client for accessing RouteGuide server using the existing channel. */
        private HelloWorldClient(ManagedChannelBuilder<?> channelBuilder) {
            channel = channelBuilder.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) {
                System.out.println("RPC调用失败:"+e.getMessage());
                return;
            }
            System.out.println("服务器返回信息:"+response.getMessage());
        }
    
        public static void main(String[] args) throws InterruptedException {
            HelloWorldClient client = new HelloWorldClient("127.0.0.1",50051);
            try {
                for(int i=0;i<5;i++){
                    client.greet("world:"+i);
                }
            }finally {
                client.shutdown();
            }
        }
    }
    

    5.测试

    服务端启动后,客户端访问

    客户端:


    Paste_Image.png

    服务端:


    Paste_Image.png

    6.回顾分析

    这一环节很重要,要对这个HelloWorld的Demo了解为什么跑通了.
    回顾下在这个过程中做了哪些事情?
    1.首先maven引入了三个依赖,分别是grpc-netty,grpc-protobuf,grpc-stub.应该是通讯,序列化,客户端调用三部分的东西吧.最后在build里面引入了一堆东西.
    2.写proto文件,大概就是定义了一个服务接口的输入输出类型,然后利用build里面的工具,生成一堆代码.

    //指定proto3格式
    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;
    
    //定义了一个service
    service Greeter {
      rpc SayHello (HelloRequest) returns (HelloReply) {}
    }
    
    //定义了一个消息请求体
    message HelloRequest {
      string name = 1;
    }
    
    //定义了一个消息回复体
    message HelloReply {
      string message = 1;
    }
    

    3.编写服务端
    服务端有如下代码,可以看出这个接口和proto里面定义的接口是一致的.

    private class GreeterImpl extends GreeterGrpc.GreeterImplBase{
        public void sayHello(HelloRequest req, StreamObserver<HelloReply> responseObserver) {};
    }
    

    然后使用如下代码把该service绑定,

     server = ServerBuilder.forPort(port)
                                  .addService(new GreeterImpl())
                                  .build()
                                  .start();
    

    4.编写客户端代码
    客户端通过如下方法创建了一个通信信道,然后和一个阻塞同步的通讯工具blockingStub.

    //初始化信道和存根
        public HelloWorldClient(String host,int port){
            this(ManagedChannelBuilder.forAddress(host, port)
                                      .usePlaintext(true));
        }
        private HelloWorldClient(ManagedChannelBuilder<?> channelBuilder) {
            channel = channelBuilder.build();
            blockingStub = GreeterGrpc.newBlockingStub(channel);
        }
    

    然后通过该blockingStub调用服务端方法.

     //客户端方法
        public  void greet(String name){
            HelloRequest request = HelloRequest.newBuilder().setName(name).build();
            HelloReply response;
            try {
                response = blockingStub.sayHello(request);
            } catch (StatusRuntimeException e) {
                System.out.println("RPC调用失败:"+e.getMessage());
                return;
            }
            System.out.println("服务器返回信息:"+response.getMessage());
        }
    

    接下来很自然的就去学proto3的一些相关知识了.

    附录:

    相关代码: https://github.com/nl101531/JavaWEB

    相关文章

      网友评论

        本文标题:gRPC学习记录(二)--Hello World

        本文链接:https://www.haomeiwen.com/subject/gpcdittx.html