grpc-java入门实例

本文主要介绍如何在Intellij IDEA环境下,快速搭建出grpc-java的入门实例。这个入门实例是一个HelloWorld程序,客户端发送world到服务端,服务端接收到请求后,拼装成 Hello,world返回。

环境配置
JDK1.8
Maven 3.6
Intellij IDEA

创建一个Project

使用Maven自带的maven-archetype-webapp原型创建一个webapp项目,在src/main下新建对应的java和proto文件夹,并将java文件夹转换为 Source Root,项目结构如下图所示:
grpc-java demo

pom文件中引入相关依赖和插件

	<dependency>
		<groupId>io.grpc</groupId>
		<artifactId>grpc-netty-shaded</artifactId>
    	<version>1.27.2</version>
	</dependency>
	<dependency>
    	<groupId>io.grpc</groupId>
    	<artifactId>grpc-protobuf</artifactId>
    	<version>1.27.2</version>
	</dependency>
	<dependency>
    	<groupId>io.grpc</groupId>
        <artifactId>grpc-stub</artifactId>
        <version>1.27.2</version>
	</dependency>
	<build>
        <finalName>grpc-java</finalName>
        <extensions>
            <extension>
                <groupId>kr.motd.maven</groupId>
                <artifactId>os-maven-plugin</artifactId>
                <version>1.6.2</version>
            </extension>
        </extensions>
        <plugins>
            <plugin>
                <groupId>org.xolstice.maven.plugins</groupId>
                <artifactId>protobuf-maven-plugin</artifactId>
                <version>0.6.1</version>
                <configuration>
                    <protocArtifact>com.google.protobuf:protoc:3.11.0:exe:${os.detected.classifier}</protocArtifact>
                    <pluginId>grpc-java</pluginId>
                    <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.27.2:exe:${os.detected.classifier}</pluginArtifact>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>compile</goal>
                            <goal>compile-custom</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

编写.proto文件,定义服务接口

在proto文件夹下编写一个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;
}

通过protocol buffer编译器生成服务端和客户端代码

选中Project,执行Maven Compile操作,会在target/generate-sources下生成对应的代码。
grpc-java proto buffer

使用Java gRPC API为上面定义的服务接口编写客户端和服务端

在src/main/java文件夹下新建,io.grpc.examples.helloworldPackage,并将代码放在此文件夹下,与helloworld.proto文件中指定的java_package参数对应。(如果放在其它文件夹下,代码要做适当调整,因为代码的引用位置变了)。

客户端代码
HelloWorldClient.java

public class HelloWorldClient {
  private static final Logger logger = Logger.getLogger(HelloWorldClient.class.getName());

  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()
        .build());
  }

  /** Construct client for accessing HelloWorld server using the existing channel. */
  HelloWorldClient(ManagedChannel channel) {
    this.channel = channel;
    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.log(Level.WARNING, "RPC failed: {0}", 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 {
    // Access a service running on the local machine on port 50051
    HelloWorldClient client = new HelloWorldClient("localhost", 50051);
    try {
      String user = "world";
      // Use the arg as the name to greet if provided
      if (args.length > 0) {
        user = args[0];
      }
      client.greet(user);
    } finally {
      client.shutdown();
    }
  }
}

服务端代码
HelloWorldServer.java

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

  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");
        try {
          HelloWorldServer.this.stop();
        } catch (InterruptedException e) {
          e.printStackTrace(System.err);
        }
        System.err.println("*** server shut down");
      }
    });
  }

  private void stop() throws InterruptedException {
    if (server != null) {
      server.shutdown().awaitTermination(30, TimeUnit.SECONDS);
    }
  }

  /**
   * 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();
    }
  }
}

执行代码

先运行HelloWorldServer,再运行HelloWorldClient,结果如下:
HelloWorldServer
HelloWorldClient
有兴趣的话可以改改这个示例,然后看看运行效果。

注意:
如果想在Eclipse环境运行该实例,需要注意以下几个不同点:

  1. pom文件中插件引用
    Intellij中:
	<extensions>
    	<extension>
    		<groupId>kr.motd.maven</groupId>
    		<artifactId>os-maven-plugin</artifactId>
    		<version>1.6.2</version>
     	</extension>
     </extensions>

eclipse中:

	<plugin>
		<groupId>kr.motd.maven</groupId>
		<artifactId>os-maven-plugin</artifactId>
		<version>1.6.1</version>
		<executions>
			<execution>
			<phase>initialize</phase>
			<goals>
				<goal>detect</goal>
			</goals>
		</execution>
		</executions>
	</plugin>
  1. .proto文件经过IDE编译后生成的代码引用问题
    Intellij中可以直接引用target目录下生成的protobuf代码,eclipse下不行,需要将生成的文件copy到src/main/java对应的文件夹下(和.proto中配置的java_package参数一致)。另外,因为jdk编译版本的问题,文件copy过后,需要去掉一些@java.lang.Override,否则代码报错(网上查阅资料,jdk高与1.6版本后就会有这个问题,具体没有测试过)。

参考资料
gRPC Quick Start
grpc-java源码地址

------------本文结束感谢您的阅读------------
  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
`io.grpc:protoc-gen-grpc-java:1.0.0:exe:${os.detected.classifier}` 是一个 Maven 坐标,用于使用 gRPC 的 Protocol Buffers 编译器插件来生成 gRPC 相关的 Java 代码。 这个坐标指定了以下部分: - `io.grpc` 是 Maven 组织 ID,表示该插件是由 gRPC 提供的。 - `protoc-gen-grpc-java` 是插件的名称,用于生成 gRPC 相关的 Java 代码。 - `1.0.0` 是插件的版本号,表示要使用的插件版本。 - `exe:${os.detected.classifier}` 指定了插件的文件类型和操作系统相关的后缀。 `${os.detected.classifier}` 是一个 Maven 变量,用于根据操作系统自动选择相应的插件文件。它会根据当前操作系统选择适当的文件后缀,例如在 Windows 上是 `.exe`,在 Linux 上是 `.linux-x86_64`。 通过在 Maven 项目的 `pom.xml` 文件中添加该依赖项,您可以在构建过程中自动下载并使用该插件来生成 gRPC 的 Java 代码。例如: ```xml <plugins> <plugin> <groupId>org.xolstice.maven.plugins</groupId> <artifactId>protobuf-maven-plugin</artifactId> <version>0.6.1</version> <configuration> <protocArtifact>com.google.protobuf:protoc:3.17.3:exe:${os.detected.classifier}</protocArtifact> <pluginId>grpc-java</pluginId> <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.0.0:exe:${os.detected.classifier}</pluginArtifact> </configuration> <executions> <execution> <goals> <goal>compile</goal> <goal>compile-custom</goal> </goals> </execution> </executions> </plugin> </plugins> ``` 这样配置后,您可以使用 `mvn compile` 命令来自动生成 gRPC 的 Java 代码。生成的代码将位于 `target/generated-sources/protobuf` 目录下。 请确保您的 Maven 项目中已经包含了正确的依赖项,并且配置文件中的版本号与您所需的版本一致。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值