新建maven项目
pom.xml
io.grpc
grpc-all
1.5.0
kr.motd.maven
os-maven-plugin
1.4.1.Final
org.xolstice.maven.plugins
protobuf-maven-plugin
0.5.0
com.google.protobuf:protoc:3.3.0:exe:${os.detected.classifier}
grpc-java
io.grpc:protoc-gen-grpc-java:1.5.0:exe:${os.detected.classifier}
src/main/resources
compile
compile-custom
定义服务
新建文件 src/main/resources/test.proto
syntax = "proto3";
option java_multiple_files = true;
option java_package = "com.acupt.grpc.proto";
option java_outer_classname = "HelloProto";
package com.acupt.grpc;
service HelloService {
rpc hello (InvokeRequest) returns (InvokeResponse) {
}
}
message InvokeRequest {
string name = 1;
}
message InvokeResponse {
string msg = 1;
}
构建
使用maven插件根据.proto文件生成Java代码,插件已在pom.xml中配置,只需执行命令:
mvn install
构建完成后可以在target中找到生成的Java代码,用这些代码可以实现gRPC远程调用。
但在项目中还无法直接引用上面的类,右键 -> Mark Directory as -> Generated Sources Root
现在就可以在项目中引用了
代码
3个类
package com.acupt.grpc;
import com.acupt.grpc.proto.HelloServiceGrpc;
import com.acupt.grpc.proto.InvokeRequest;
import com.acupt.grpc.proto.InvokeResponse;
import io.grpc.stub.StreamObserver;
/**
* 服务实现类
*/
public class HelloService extends HelloServiceGrpc.HelloServiceImplBase {
@Override
public void hello(InvokeRequest request, StreamObserver responseObserver) {
System.out.println("request -> " + request);
String name = request.getName();//自定义的字段名 name
InvokeResponse response = InvokeResponse.newBuilder()
.setMsg("hello," + name)//自定义的字段名 msg
.build();
responseObserver.onNext(response);
responseObserver.onCompleted();
}
}
package com.acupt.grpc;
import io.grpc.Server;
import io.grpc.ServerBuilder;
import java.io.IOException;
/**
* 服务提供方
*
* @author liujie
*/
public class MyServer {
public static void main(String[] args) throws IOException, InterruptedException {
int port = 50051;
Server server = ServerBuilder.forPort(port)
.addService(new HelloService())
.build()
.start();
System.out.println("started");
Thread.sleep(1000 * 60 * 2);
server.shutdown();
System.out.println("shutdown");
}
}
package com.acupt.grpc;
import com.acupt.grpc.proto.HelloServiceGrpc;
import com.acupt.grpc.proto.InvokeRequest;
import com.acupt.grpc.proto.InvokeResponse;
import io.grpc.Channel;
import io.grpc.ManagedChannelBuilder;
/**
* 服务调用方
*/
public class MyClient {
public static void main(String[] args) {
InvokeRequest request = InvokeRequest.newBuilder().setName("tom").build();
Channel channel = ManagedChannelBuilder.forAddress("localhost", 50051).usePlaintext(true).build();
HelloServiceGrpc.HelloServiceBlockingStub blockingStub = HelloServiceGrpc.newBlockingStub(channel);
InvokeResponse response = blockingStub.hello(request);
System.out.println(response.getMsg());
}
}
先启动MyServer,成功启动后再启动MyClient
请求方式
1.阻塞
同步请求,接口返回前是阻塞的。
HelloServiceGrpc.HelloServiceBlockingStub blockingStub = HelloServiceGrpc.newBlockingStub(channel);
InvokeResponse response = blockingStub.hello(request);
System.out.println(response.getMsg());
2.Future
调用后返回guava包里继承了Future的接口ListenableFuture(增加了listener支持),可以控制超时时间。
HelloServiceGrpc.HelloServiceFutureStub futureStub = HelloServiceGrpc.newFutureStub(channel);
ListenableFuture future = futureStub.hello(request);
future.addListener(
() -> System.out.println("listener 1"),
command -> {
System.out.println("execute 1 " + command);
command.run();
});
future.addListener(
() -> System.out.println("listener 2"),
command -> {
System.out.println("execute 2 " + command);
command.run();
});
System.out.println(future.get(10, TimeUnit.SECONDS));
3.回调
调用接口传入回调函数,调用后马上返回。
MyClient.done = false;
HelloServiceGrpc.HelloServiceStub stub = HelloServiceGrpc.newStub(channel);
stub.hello(request, new StreamObserver() {
@Override
public void onNext(InvokeResponse value) {
System.out.println("onNext " + value);
}
@Override
public void onError(Throwable t) {
System.out.println("onError " + t.getMessage());
t.printStackTrace();
MyClient.done = true;
}
@Override
public void onCompleted() {
System.out.println("onCompleted");
MyClient.done = true;
}
});
while (!MyClient.done) {
Thread.sleep(1000);
}