如何在java项目中的引入grpc

  谷歌开源的grpc以性能高效而著称,在追求高并发高性能的今天,将其应用到项目中去显得十分必要,这里github已经有相关资源:https://github.com/grpc/grpc-java
  本文将举例作为抛砖引玉,实现一个简单的sayHello调用的demo。

加入grpc编译插件、依赖包

  <build>
	  <extensions>
		  <extension>
			  <groupId>kr.motd.maven</groupId>
			  <artifactId>os-maven-plugin</artifactId>
			  <version>1.6.2</version>
		  </extension>
	  </extensions>
    <sourceDirectory>src</sourceDirectory>
    <plugins>
		<plugin>
			<groupId>org.xolstice.maven.plugins</groupId>
			<artifactId>protobuf-maven-plugin</artifactId>
			<version>0.6.1</version>
			<!--添加.proto文件的编译工具-->
			<configuration>
				<!--protoc工具通过.proto文件生成对应的java对应的类-->
				<protocArtifact>com.google.protobuf:protoc:3.10.0:exe:${os.detected.classifier}</protocArtifact>
				<!--这是生成grpc工具类存放的文件夹的名字-->
				<pluginId>grpc-java</pluginId>
				<!--protoc-gen-grpc-java工具通过.proto文件生成grpc工具类-->
				<pluginArtifact>io.grpc:protoc-gen-grpc-java:1.25.0:exe:${os.detected.classifier}</pluginArtifact>
				<!--要编译的.proto文件的路径-->
				<protoSourceRoot>src/grpc/helloworld/proto</protoSourceRoot>
			</configuration>
			<executions>
				<!--这是上面两个编译工具用到的命令-->
				<execution>
					<goals>
						<goal>compile</goal>
						<goal>compile-custom</goal>
					</goals>
				</execution>
			</executions>
		</plugin>
		<plugin>
			<groupId>org.apache.maven.plugins</groupId>
			<artifactId>maven-compiler-plugin</artifactId>
			<version>3.3</version>
			<configuration>
				<source>1.8</source>
				<target>1.8</target>
				<encoding>UTF-8</encoding>
			</configuration>
		</plugin>
    </plugins>
  </build>

依赖包:

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

编写proto文件

  proto文件的语法规则可以参考:
      https://developers.google.com/protocol-buffers/docs/proto3

在src下建立package:grpc.helloworld.proto,创建一个Proto文件HelloMsg.proto。

syntax = "proto3";//指定版本为proto3,默认为proto2
option java_package = "grpc.helloword";//生成的java文件的包名
option java_multiple_files = true;
option java_outer_classname = "HelloWolrd";//编译proto文件会生成一个对应的描述文件,这里是文件名

option objc_class_prefix = "HLW";
//相当于服务的命名空间比如这里service_name是:jeffsmile.Greeter
package jeffsmile;

// 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;
}

使用maven的grpc插件编译proto

在这里插入图片描述
编译后会在target下生成一系列的java文件如图所示:
在这里插入图片描述

拷贝文件

在src下创建grpc.helloworld.generate用来存放刚生成的那些文件。
在这里插入图片描述

编写client和server端程序

服务端:

/*
 * Copyright 2015 The gRPC Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package grpc.helloworld;

import grpc.helloworld.generate.GreeterGrpc;
import grpc.helloworld.generate.HelloReply;
import grpc.helloworld.generate.HelloRequest;
import io.grpc.Server;
import io.grpc.ServerBuilder;
import io.grpc.stub.StreamObserver;

import java.io.IOException;
import java.util.logging.Logger;
/**
 * Server that manages startup/shutdown of a {@code Greeter} server.
 */
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 = 50052;
    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 {

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

客户端:

/*
 * Copyright 2015 The gRPC Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package grpc.helloworld;

import grpc.helloworld.generate.GreeterGrpc;
import grpc.helloworld.generate.HelloReply;
import grpc.helloworld.generate.HelloRequest;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import io.grpc.StatusRuntimeException;

import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
 * A simple client that requests a greeting from the {@link HelloWorldServer}.
 */
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", 50052);
    try {
      String user = "jeffSmile";
      // Use the arg as the name to greet if provided
      if (args.length > 0) {
        user = args[0];
      }
      client.greet(user);
    } finally {
      client.shutdown();
    }
  }
}

启动服务端测试

启动服务端监听50052端口,然后使用客户端进行测试:
在这里插入图片描述
客户端打印:
在这里插入图片描述

总结

其实重点就是编写好proto文件,定义好grpc的访问路径、方法名、请求参数、响应参数,生成一系列的grpc文件,比如请求类、响应类、grpc类等。
到这里,案例已经结束,欢迎留言一起交流!

发布了222 篇原创文章 · 获赞 805 · 访问量 27万+

猜你喜欢

转载自blog.csdn.net/shengqianfeng/article/details/103052056