這裏是一個關於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);
}
}
}
大功告成