热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

grpc在java中的使用2

     欢迎回来!2.请求流接口(客户端可以源源不断的给服务端传参数,服务端会源源不断的接受服务端的参数,最后在客户端完成请求的时候,服务端返回一个结果) 在.proto文件中新

 
 
 
 
 
欢迎回来!
2.请求流接口

(客户端可以源源不断的给服务端传参数,服务端会源源不断的接受服务端的参数,最后在客户端完成请求的时候,服务端返回一个结果)

 

在.proto文件中新加一个方法,这个方法的参数被 stream 关键字修饰

rpc methodRequestStream(stream Request) returns (Result) {}

  

然后用maven,清理一下缓存,重新编译一下

 


2.1.服务端

 重新编译之后,实现刚刚新加的方法

@Override
public StreamObserver methodRequestStream(StreamObserver responseObserver) {
return new StreamObserver() {
@Override
public void onNext(Request request) {
System.out.print("收到了请求 \n");
}
@Override
public void one rror(Throwable throwable) {
}
@Override
public void onCompleted() {
Result result = Result.newBuilder().setResult1("result1").setResult2("result2").build();
responseObserver.onNext(result);
responseObserver.onCompleted();
}
};
}

  

(友情提示,如果 StreamObserver  的的泛型是Result 我们就叫 返回流观察者,如果是 Request 就叫请求流观察者,这样好描述一些)

这个和普通的有点不一样,直接返回了一个 请求流观察者 的接口实现,而且方法的参数还是一个 返回流观察者 ,好像搞反了一样,至于为什么,一会在客户端那里 统一说

 


2.2.客户端

请求流式异步调用,普通的是同步调用,我们在普通的方法里创建的实例 也是同步的,所以我们要在 JavaGrpcClient 中新加一个 异步调用的方法,添加一个异步的实例

public Result runAsync(Functional functional)
{
TestServiceGrpc.TestServiceStub testServiceStub =
TestServiceGrpc.newStub(channel);
return functional.run(testServiceStub);
}

TestServiceGrpc.newStub 返回的是一个异步的实例

 

再加一个测试

 

@Test
public void contextLoads2() {
Request request = Request.newBuilder().setRequest1("test1").setRequest2("test2").build();
StreamObserver respOnseObserver= new StreamObserver() {
@Override
public void onNext(Result result) {
System.out.print("返回了结果 \n");
}
@Override
public void one rror(Throwable throwable) {
}
@Override
public void onCompleted() {
}
};
StreamObserver result = javaGrpcClient.runAsync(o -> o.methodRequestStream(responseObserver));
result.onNext(request);
result.onNext(request);
result.onNext(request);
result.onCompleted();
try {
Thread.sleep(600000);
}
catch (Exception ex){}
}

  

这里我们实现了一个 返回流观察者 

StreamObserver respOnseObserver= new StreamObserver() {
@Override
public void onNext(Result result) {
System.out.print("返回了结果 \n");
}
@Override
public void one rror(Throwable throwable) {
}
@Override
public void onCompleted() {
}
};

  

调用方法的时候,将我们实现的 返回流观察者 传进去,返回给我们一个 请求流观察者

StreamObserver result = javaGrpcClient.runAsync(o -> o.methodRequestStream(responseObserver));

  

其实这里返回的 请求流观察者 就是服务端那里返回给我们的内个实现,服务端那里 返回流观察者 是我们实现的 传给他的

 

由于是异步调用,最后暂停一下,要不测试跑完,程序结束 开没开始就结束了

try {
Thread.sleep(600000);
}
catch (Exception ex){}

  

 

运行起来看结果

服务端的打印

 

客户端的打印

 

这里我们发送了三次参数过去

result.onNext(request);
result.onNext(request);
result.onNext(request);

  

就相当于 服务端 那边返回的 请求流观察者 被调用了 三次 ,所以就打印了三句话

 

发送完参数结束请求

result.onCompleted();

  

服务端那里的结束请求中调用了一次我们传给他的 返回流观察者 中的 onNext 方法

所以客户端就打印了一次

 

这里会有人问 这里不能返回 多个吗

不能,虽然 这两个观察者 看上去一样 都是 StreamObserver 接口,但是,这个方法只是请求流调用,在grpc的内部 最后返回的时候 只返回第一个指定的返回只,不管返回了多少个,在客户端那边只会收到 第一个返回的结果

 

 


3.响应流接口

(和请求流接口完全相反,请求流是异步,响应流是同步,请求流是接受多个请求返回一个结果,响应流是接受一个请求返回多个结果)

 

 我们在.proto文件中再增加一个方法,这回这个方法的返回值被 stream 关键字修饰

rpc methodResultStream(Request) returns (stream Result){}

  

清缓存,重新编译


3.1.服务端

 实现刚刚新加的方法

@Override
public void methodResultStream(Request request, StreamObserver responseObserver) {
System.out.print("收到了请求 \n");
Result result = Result.newBuilder().setResult1("result1").setResult2("result2").build();
responseObserver.onNext(result);
responseObserver.onNext(result);
try {
Thread.sleep(2000);
}
catch (Exception ex){}
responseObserver.onNext(result);
responseObserver.onCompleted();
}

  

 

这里跟普通的差不多,只是我们返回了三次结果

responseObserver.onNext(result);
responseObserver.onNext(result);
try {
Thread.sleep(2000);
}
catch (Exception ex){}
responseObserver.onNext(result);

  

 


3.2.客户端

没啥好加的了,直接上测试

@Test
public void contextLoads3() {
Request request = Request.newBuilder().setRequest1("test1").setRequest2("test2").build();
Iterator result = javaGrpcClient.run(o -> o.methodResultStream(request));
result.forEachRemaining(o ->
{
System.out.print("返回了结果 \n");
});
System.out.print("结束 \n");
}

  

 

返回流请求是同步的,所以要调同步的方法,返回了一个迭代器

Iterator result = javaGrpcClient.run(o -> o.methodResultStream(request));

  

迭代器中有服务端的所有返回结果

result.forEachRemaining(o ->
{
System.out.print("返回了结果 \n");
});

  

运行结果

服务端结果

 

客户端结果

由于是同步调用,在forEach中会等待服务端的每一个返回结果

 

 


4.双向流接口

 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

歇会,抽根烟!

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

在.proto文件中再加一个方法

rpc methodDoubleStream(stream Request) returns (stream Result){}

  

实现

 

双向流的服务端和请求流的没啥区别,只是在接收到请求的时候没有立刻结束请求

@Override
public StreamObserver methodDoubleStream(StreamObserver responseObserver) {
return new StreamObserver() {
@Override
public void onNext(Request value) {
System.out.print("收到了请求 \n");
Result result = Result.newBuilder().setResult1("result1").setResult2("result2").build();
responseObserver.onNext(result);
}
@Override
public void one rror(Throwable t) {
}
@Override
public void onCompleted() {
responseObserver.onCompleted();
}
};
}

  

客户端也没啥区别

@Test
public void contextLoads4() {
Request request = Request.newBuilder().setRequest1("test1").setRequest2("test2").build();
StreamObserver respOnseObserver= new StreamObserver() {
@Override
public void onNext(Result result) {
System.out.print("返回了结果 \n");
}
@Override
public void one rror(Throwable throwable) {
}
@Override
public void onCompleted() {
}
};
StreamObserver result = javaGrpcClient.runAsync(o -> o.methodDoubleStream(responseObserver));
result.onNext(request);
result.onNext(request);
result.onNext(request);
result.onCompleted();
try {
Thread.sleep(600000);
}
catch (Exception ex){}
}

  

双向流也是异步的,所以要等待

try {
Thread.sleep(600000);
}
catch (Exception ex){}

  

 服务端结果

 

客户端结果

 

完结!撒花!


推荐阅读
  • 怎么在PHP项目中实现一个HTTP断点续传功能发布时间:2021-01-1916:26:06来源:亿速云阅读:96作者:Le ... [详细]
  • Java序列化对象传给PHP的方法及原理解析
    本文介绍了Java序列化对象传给PHP的方法及原理,包括Java对象传递的方式、序列化的方式、PHP中的序列化用法介绍、Java是否能反序列化PHP的数据、Java序列化的原理以及解决Java序列化中的问题。同时还解释了序列化的概念和作用,以及代码执行序列化所需要的权限。最后指出,序列化会将对象实例的所有字段都进行序列化,使得数据能够被表示为实例的序列化数据,但只有能够解释该格式的代码才能够确定数据的内容。 ... [详细]
  • t-io 2.0.0发布-法网天眼第一版的回顾和更新说明
    本文回顾了t-io 1.x版本的工程结构和性能数据,并介绍了t-io在码云上的成绩和用户反馈。同时,还提到了@openSeLi同学发布的t-io 30W长连接并发压力测试报告。最后,详细介绍了t-io 2.0.0版本的更新内容,包括更简洁的使用方式和内置的httpsession功能。 ... [详细]
  • Java中包装类的设计原因以及操作方法
    本文主要介绍了Java中设计包装类的原因以及操作方法。在Java中,除了对象类型,还有八大基本类型,为了将基本类型转换成对象,Java引入了包装类。文章通过介绍包装类的定义和实现,解答了为什么需要包装类的问题,并提供了简单易用的操作方法。通过本文的学习,读者可以更好地理解和应用Java中的包装类。 ... [详细]
  • PHP图片截取方法及应用实例
    本文介绍了使用PHP动态切割JPEG图片的方法,并提供了应用实例,包括截取视频图、提取文章内容中的图片地址、裁切图片等问题。详细介绍了相关的PHP函数和参数的使用,以及图片切割的具体步骤。同时,还提供了一些注意事项和优化建议。通过本文的学习,读者可以掌握PHP图片截取的技巧,实现自己的需求。 ... [详细]
  • 如何使用Java获取服务器硬件信息和磁盘负载率
    本文介绍了使用Java编程语言获取服务器硬件信息和磁盘负载率的方法。首先在远程服务器上搭建一个支持服务端语言的HTTP服务,并获取服务器的磁盘信息,并将结果输出。然后在本地使用JS编写一个AJAX脚本,远程请求服务端的程序,得到结果并展示给用户。其中还介绍了如何提取硬盘序列号的方法。 ... [详细]
  • eclipse学习(第三章:ssh中的Hibernate)——11.Hibernate的缓存(2级缓存,get和load)
    本文介绍了eclipse学习中的第三章内容,主要讲解了ssh中的Hibernate的缓存,包括2级缓存和get方法、load方法的区别。文章还涉及了项目实践和相关知识点的讲解。 ... [详细]
  • 本文介绍了Hyperledger Fabric外部链码构建与运行的相关知识,包括在Hyperledger Fabric 2.0版本之前链码构建和运行的困难性,外部构建模式的实现原理以及外部构建和运行API的使用方法。通过本文的介绍,读者可以了解到如何利用外部构建和运行的方式来实现链码的构建和运行,并且不再受限于特定的语言和部署环境。 ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • 本文介绍了RPC框架Thrift的安装环境变量配置与第一个实例,讲解了RPC的概念以及如何解决跨语言、c++客户端、web服务端、远程调用等需求。Thrift开发方便上手快,性能和稳定性也不错,适合初学者学习和使用。 ... [详细]
  • 本文介绍了计算机网络的定义和通信流程,包括客户端编译文件、二进制转换、三层路由设备等。同时,还介绍了计算机网络中常用的关键词,如MAC地址和IP地址。 ... [详细]
  • Android源码深入理解JNI技术的概述和应用
    本文介绍了Android源码中的JNI技术,包括概述和应用。JNI是Java Native Interface的缩写,是一种技术,可以实现Java程序调用Native语言写的函数,以及Native程序调用Java层的函数。在Android平台上,JNI充当了连接Java世界和Native世界的桥梁。本文通过分析Android源码中的相关文件和位置,深入探讨了JNI技术在Android开发中的重要性和应用场景。 ... [详细]
  • C++字符字符串处理及字符集编码方案
    本文介绍了C++中字符字符串处理的问题,并详细解释了字符集编码方案,包括UNICODE、Windows apps采用的UTF-16编码、ASCII、SBCS和DBCS编码方案。同时说明了ANSI C标准和Windows中的字符/字符串数据类型实现。文章还提到了在编译时需要定义UNICODE宏以支持unicode编码,否则将使用windows code page编译。最后,给出了相关的头文件和数据类型定义。 ... [详细]
  • 开发笔记:实验7的文件读写操作
    本文介绍了使用C++的ofstream和ifstream类进行文件读写操作的方法,包括创建文件、写入文件和读取文件的过程。同时还介绍了如何判断文件是否成功打开和关闭文件的方法。通过本文的学习,读者可以了解如何在C++中进行文件读写操作。 ... [详细]
  • 解决nginx启动报错epoll_wait() reported that client prematurely closed connection的方法
    本文介绍了解决nginx启动报错epoll_wait() reported that client prematurely closed connection的方法,包括检查location配置是否正确、pass_proxy是否需要加“/”等。同时,还介绍了修改nginx的error.log日志级别为debug,以便查看详细日志信息。 ... [详细]
author-avatar
liu100897
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有