这里是一个关于gRpc的demo,和网上的例子一模一样,但是在运行demo时会出现各种各样的问题,导致放弃grpc的学习,本例子就是一步一步的教大家把demo运行通过,这里是用maven和Idea进行测试的
第一步 创建maven项目
在pom.xml添加以下依赖
<dependencies>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-protobuf</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-stub</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
并加入插件
<pluginRepositories><!-- 插件库 -->
<pluginRepository>
<id>protoc-plugin</id>
<url>https://dl.bintray.com/sergei-ivanov/maven/</url>
</pluginRepository>
</pluginRepositories>
配置插件和build环境
<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.0.0:exe:${os.detected.classifier}</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:0.15.0:exe:${os.detected.classifier}</pluginArtifact>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
第二步 编写服务.proto文件
接下来,需要添加.proto文件。
打开Project Structure—》Modules,先在src/main目录下新建一个文件夹proto,用来存放我们马上将要创建的proto文件。
然后新建一个名叫helloworld.proto文件,按照官方教程中的样子,编写一个自定义的grpc服务
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;
}
第三步 编译.proto文件
这一步最重要了,好多文章都忽略了这一步,导致程序出错,大家却找不到出错原因;
编译.proto文件的工作由protoc的Maven插件编译来完成,它会调用指定路径下protoc.exe解析.proto,并生成我们编写客户端和服务端代码基础。
由于protoc可执行程序是平台相关的,因此这里给出两种配置方式:
1. 使用protobuf-maven-plugin自己指定的protc可执行程序。这种方式,什么都不用配置,只需要把plugin加进我们的pom.xml中就行了,插件会自己下载需要的可执行程序,这一步参见pom.xml即可,前面已经做好了配置了。
2. 接下来进行编译
左侧我们在pom.xml中看到的有两个goal,此时选择第二个compile-custom,对hello.proto的修改在重新编译的时候才会生效,否则不会在target/generated-sources/protobuf/grpc-java目录下生成一个叫GreeterGrpc.java的文件,如下图所示
选择protobuf compile-custom进行编译,就能生成GreeterGrpc.java的类
在这一步我遇到了一个错误
Connect to maven.oschina.net:80 [maven.oschina.net/183.78.182.122] failed
从错误信息可知,我们所需要的插件在maven.oschina.net/183.78.182.122中已经不存在了,所以我修改了setting.xml文件,这个文件我把他放入了C:\Users\用户名.m2的文件加下面了,可以在IDEA的设置中配置,如图
把setting.xml文件中包含oschina的url全部替换为http://repo2.maven.org/maven2/即可,问题解决。
然后再选择protobuf compile,
这是就产生了helloworld.proto中所有的方法和类了
第四步,编写grpc服务端程序和客户端程序
服务端程序GrpcServer.java
package com;
import io.grpc.Server;
import io.grpc.ServerBuilder;
import io.grpc.examples.helloworld.GreeterGrpc;
import io.grpc.examples.helloworld.HelloReply;
import io.grpc.examples.helloworld.HelloRequest;
import io.grpc.stub.StreamObserver;
import java.io.IOException;
/**
*
* Created by jiely on 2017/7/13.
*/
public class RpcServer {
private int port = 50051;
private Server server;
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");
RpcServer.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 RpcServer server = new RpcServer();
server.start();
server.blockUntilShutdown();
}
// 实现 定义一个实现服务接口的类
private class GreeterImpl extends GreeterGrpc.GreeterImplBase {
public void sayHello(HelloRequest req, StreamObserver<HelloReply> responseObserver) {
System.out.println("service:"+req.getName());
HelloReply reply = HelloReply.newBuilder().setMessage(("Hello: " + req.getName())).build();
responseObserver.onNext(reply);
responseObserver.onCompleted();
}
}
}
grpc客户端代码GrpcClient.java
package com;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import io.grpc.examples.helloworld.GreeterGrpc;
import io.grpc.examples.helloworld.HelloReply;
import io.grpc.examples.helloworld.HelloRequest;
import java.util.concurrent.TimeUnit;
/**
*
* Created by jiely on 2017/7/15.
*/
public class RpcClient {
private final ManagedChannel channel;
private final GreeterGrpc.GreeterBlockingStub blockingStub;
public RpcClient(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 = blockingStub.sayHello(request);
System.out.println(response.getMessage());
}
public static void main(String[] args) throws InterruptedException {
RpcClient client = new RpcClient("127.0.0.1",50051);
for(int i=0;i<5;i++){
client.greet("world:"+i);
}
}
}
大功告成