之前介绍了grpc的四种服务类型,在定义服务的时候可以定义流式客户端,实现客户端以异步的方式返回多个对象,当然可以返回单个对象以实现异步的操作。在grpc中可以在客户端上进行同步异步的调用。
阻塞调用(blockingCall)
void blockingCall() {
HelloServiceGrpc.HelloServiceBlockingStub stub = HelloServiceGrpc.newBlockingStub(channel);
stub.simpleHello(person).getString();
}
这是最简单的方式,通过block的形式调用rpc,并在当前线程返回结果。
Future直接调用(futureCallDirect)
void futureCallDirect() {
HelloServiceGrpc.HelloServiceFutureStub stub = HelloServiceGrpc.newFutureStub(channel);
ListenableFuture<ProtoObj.Result> response = stub.simpleHello(person);
try {
response.get();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException(e);
} catch (ExecutionException e) {
}
}
这种方式是通过创建futureStub调用rpc并获得future对象,通过get方法来阻塞调用,这里的future是guava包中的而不是jdk内置的。
Future回调调用(furueCallCallback)
void futureCallCallback() {
final CountDownLatch latch = new CountDownLatch(1);
HelloServiceGrpc.HelloServiceFutureStub stub = HelloServiceGrpc.newFutureStub(channel);
ListenableFuture<ProtoObj.Result> response = stub.simpleHello(person);
Futures.addCallback(
response,
new FutureCallback<ProtoObj.Result>() {
@Override
public void onSuccess(@Nullable ProtoObj.Result result) {
System.out.println(result.getString());
latch.countDown();
}
@Override
public void onFailure(Throwable t) {
}
},
directExecutor());
}
同上前一种方式一样,获得Future,然后通过Futures方法在其他。
异步调用(asyncCall)
void asyncCall() {
HelloServiceGrpc.HelloServiceStub stub = HelloServiceGrpc.newStub(channel);
final CountDownLatch latch = new CountDownLatch(1);
StreamObserver<ProtoObj.Result> responseObserver = new StreamObserver<ProtoObj.Result>() {
@Override
public void onNext(ProtoObj.Result value) {
System.out.println(value.getString());
latch.countDown();
}
@Override
public void onError(Throwable t) {
}
@Override
public void onCompleted() {
}
};
stub.simpleHello(person, responseObserver);
if (!Uninterruptibles.awaitUninterruptibly(latch, 1, TimeUnit.SECONDS)) {
throw new RuntimeException("timeout!");
}
}
在之前四种服务类型中已经使用过newStub,当时是用在客户端流式服务上,其实newStub并不只限于流式服务,任何rpc调用都可以使用其来实现异步调用。
异步底层方式调用
void advancedAsyncCall() {
//使用方法的名字METHOD_SIMPLE_HELLO进行调用
ClientCall<ProtoObj.Person, ProtoObj.Result> call = channel.newCall(HelloServiceGrpc.METHOD_SIMPLE_HELLO, CallOptions.DEFAULT);
final CountDownLatch latch = new CountDownLatch(1);
call.start(new ClientCall.Listener<ProtoObj.Result>() {
@Override
public void onMessage(ProtoObj.Result message) {
System.out.println(Thread.currentThread().getName());
System.out.println(message.getString());
latch.countDown();
}
}, new Metadata());
call.request(1);
call.sendMessage(person);
call.halfClose();
if (!Uninterruptibles.awaitUninterruptibly(latch, 10, TimeUnit.SECONDS)) {
throw new RuntimeException("timeout!");
}
}
该种方式只是上面newStub的底层实现,没有特殊需求不会使用这种方式进行rpc。