gRPC Java:快速开始和项目原型

栏目: 服务器 · 发布时间: 8年前

内容简介:gRPC Java:快速开始和项目原型

之前一直用 Go 来写gRPC的服务,简单而直接。最近工作涉及用 Java 开发几个gRPC的服务,我们知道Java中有很多框架和Magical,所以这几个服务还是希望以Java的风格来写,因此打算写几篇文章对此做个整理。本篇做为开篇 ,先简单从快速开始一个项目原型开始写起。

开发环境

  • JDK 1.8
  • gradle 3.5
  • gRPC 1.30
  • protobuf 3.2.0

初始化项目原型

新建项目目录 grpc-java-demo

mkdir grpc-java-demo

使用gradle生成项目原型:

cd grpc-java-demo
gradle init --type=java-application

修改生成构建脚本build.gradle:

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

buildscript {
  repositories {
    mavenCentral()
  }
  dependencies {
    classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.1'
  }
}

repositories {
   mavenCentral()
}

sourceSets {
   main {
    java {
        srcDir 'build/generated/source/proto/main/java'
        srcDir 'build/generated/source/proto/main/grpc'
    }
   }
}

compileJava {
    sourceCompatibility=1.8
    targetCompatibility=1.8
    options.encoding='UTF-8'
}
compileTestJava {
    sourceCompatibility=1.8
    targetCompatibility=1.8
    options.encoding='UTF-8'
}

configurations { 
    all*.exclude group:'com.sun.xml.bind',module:'jaxb-impl'
    all*.exclude group:'xml-apis',module:'xml-apis'
    all*.exclude group:'stax',module:'stax-api'
    all*.exclude group:'org.slf4j',module:'slf4j-log4j12'
    all*.exclude group:'commons-logging'
}

ext {
    grpcVersion= '1.3.0'
    logbackVersion = '1.2.2'
    slf4jVersion='1.7.25'
}

dependencies {
    compile "io.grpc:grpc-netty:${grpcVersion}"
    compile "io.grpc:grpc-protobuf:${grpcVersion}"
    compile "io.grpc:grpc-stub:${grpcVersion}"

    compile "org.slf4j:slf4j-api:$slf4jVersion"
    compile "ch.qos.logback:logback-classic:$logbackVersion"
    runtime "org.slf4j:jcl-over-slf4j:$slf4jVersion"
    runtime "org.slf4j:log4j-over-slf4j:$slf4jVersion"
    runtime "org.slf4j:jul-to-slf4j:$slf4jVersion"
    testCompile 'junit:junit:4.12'
}

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

tasks.eclipse.dependsOn compileJava

新建src/main/resources目录,在目录下创建logback的配置文件logback.xml:

<?xml version="1.0" encoding="UTF-8"?>

<configuration debug="false" scan="false" scanPeriod="30 seconds">

  <contextName>grpc-java-demo</contextName>

  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
      <pattern>
        <![CDATA[
        [%date{yyyy-MM-dd HH:mm:ss.SSS}] [%thread] %level %logger - %message%n
        ]]>
      </pattern>
    </encoder>
  </appender>

  <logger name="com.frognew.grpc.demo" level="INFO"  additivity="false">
    <appender-ref ref="STDOUT" />
  </logger>

  <root level="WARN">
    <appender-ref ref="STDOUT" />
  </root>

</configuration>

删除src/main/java下的App.java文件和src/test/java下的AppTest.java文件。在src下新建名称为proto的源码目录,在此目录中新建helloworld.proto文件内容如下:

syntax = "proto3";

option java_multiple_files = true;
option java_package = "com.frognew.grpc.demo.helloworld";
option java_outer_classname = "HelloWorldProto";
option objc_class_prefix = "HLW";

package helloworld;

service Greeter {
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

message HelloRequest {
  string name = 1;
}

message HelloReply {
  string message = 1;
}

运行 gradle eclipse 生成eclipse项目,此过程中会调用gradle的 com.google.protobuf 插件基于src/main/proto中的PB文件生成Java代码。将生成的项目导入eclipse中。

gRPC Java:快速开始和项目原型

后续开发过程中,当PB文件发生修改时,只需要执行 gradle eclipse 再刷新eclipse项目即可。

HelloWorldServer和HelloWorldClient

基于官方demo中的代码进行修改:

com.frognew.grpc.demo.helloworld.HelloWorldServer.java:

package com.frognew.grpc.demo.helloworld;

import java.io.IOException;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.grpc.Server;
import io.grpc.ServerBuilder;
import io.grpc.stub.StreamObserver;

public class HelloWorldServer {

    private static final Logger LOGGER = LoggerFactory.getLogger(HelloWorldServer.class);

     private Server server;

      private void start() throws IOException {
        /* The port on which the server should run */
        int port = 50051;
        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() {
            // Use stderr here since the logger may have been reset by its JVM shutdown hook.
            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();
        }
      }

      /**
       * Await termination on the main thread since the grpc library uses daemon threads.
       */
      private void blockUntilShutdown() throws InterruptedException {
        if (server != null) {
          server.awaitTermination();
        }
      }

      /**
       * Main launches the server from the command line.
       */
      public static void main(String[] args) throws IOException, InterruptedException {
        final HelloWorldServer server = new HelloWorldServer();
        server.start();
        server.blockUntilShutdown();
      }

      static class GreeterImpl extends GreeterGrpc.GreeterImplBase {

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

com.frognew.grpc.demo.helloworld.HelloWorldClient.java:

package com.frognew.grpc.demo.helloworld;

import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import io.grpc.StatusRuntimeException;

public class HelloWorldClient {
    private static final Logger LOGGER = LoggerFactory.getLogger(HelloWorldClient.class);

    private final ManagedChannel channel;
      private final GreeterGrpc.GreeterBlockingStub blockingStub;

      /** Construct client connecting to HelloWorld server at {@code host:port}. */
      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. */
      HelloWorldClient(ManagedChannelBuilder<?> channelBuilder) {
        channel = channelBuilder.build();
        blockingStub = GreeterGrpc.newBlockingStub(channel);
      }

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

      /** Say hello to server. */
      public void greet(String name) {
        LOGGER.info("Will try to greet " + name + " ...");
        HelloRequest request = HelloRequest.newBuilder().setName(name).build();
        HelloReply response;
        try {
          response = blockingStub.sayHello(request);
        } catch (StatusRuntimeException e) {
          LOGGER.warn("RPC failed: {}", e.getStatus());
          return;
        }
        LOGGER.info("Greeting: " + response.getMessage());
      }

      /**
       * Greet server. If provided, the first element of {@code args} is the name to use in the
       * greeting.
       */
      public static void main(String[] args) throws Exception {
        HelloWorldClient client = new HelloWorldClient("localhost", 50051);
        try {
          /* Access a service running on the local machine on port 50051 */
          String user = "world";
          if (args.length > 0) {
            user = args[0]; /* Use the arg as the name to greet if provided */
          }
          client.greet(user);
        } finally {
          client.shutdown();
        }
      }
}

运行Server输出:

Server started, listening on 50051

运行Client,向Server发送RPC请求,输出:

Will try to greet world ...
Greeting: Hello world

总结

本篇主要是根据gRPC Java官方示例代码演示怎么快速使用Gradle快速创建gRPC Java项目的框架原型,因为gRPC HelloWorld的代码十分简单,就不展开多写了。

参考


以上所述就是小编给大家介绍的《gRPC Java:快速开始和项目原型》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Python Machine Learning

Python Machine Learning

Sebastian Raschka / Packt Publishing - ebooks Account / 2015-9 / USD 44.99

About This Book Leverage Python' s most powerful open-source libraries for deep learning, data wrangling, and data visualization Learn effective strategies and best practices to improve and opti......一起来看看 《Python Machine Learning》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具