「javarpc调用服务」java实现rpc调用
今天给各位分享javarpc调用服务的知识,其中也会对java实现rpc调用进行解释,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!
本文目录一览:
- 1、java为什么要用远程调用
- 2、RPC 调用和 HTTP 调用的区别
- 3、java protobuf 定义rpc服务怎么调用
- 4、java怎么远程调用webservice接口
- 5、RPC框架(1 - 实现服务端注册一个服务)
- 6、rpc的实现机制是什么
java为什么要用远程调用
因为提供服务的机器和需要服务的机器一般都不是一台。两台机器需要进行数据传输,所以需要远程过程调用,简称RPC
RPC 调用和 HTTP 调用的区别
在说RPC和HTTP的区别之前,我觉的有必要了解一下OSI的七层网络结构模型。
实际应用过程中,五层协议结构里面是没有表示层和会话层的。应该说它们和应用层合并了。
我们应该将重点放在 应用层 和 传输层 这两个层面。
RPC需要从三个角度来介绍RPC:
先说说RPC服务的基本架构吧,见下图:
一个完整的RPC架构里面包含了四个核心的组件,分别是Client , Server, Client Stub以及Server Stub。
这个Stub大家可以理解为存根。
什么是同步调用?什么是异步调用?
同步调用就是客户端等待调用执行完成并返回结果。
异步调用就是客户端不等待调用执行完成返回结果,不过依然可以通过回调函数等接收到返回结果的通知。如果客户端并不关心结果,则可以变成一个单向的调用。
这个过程有点类似于Java中的callable和runnable接口,我们进行异步执行的时候,如果需要知道执行的结果,就可以使用callable接口,并且可以通过Future类获取到异步执行的结果信息。如果不关心执行的结果,直接使用runnable接口就可以了,因为它不返回结果,当然啦,callable也是可以的,我们不去获取Future就可以了。
目前流行的开源RPC框架还是比较多的。下面重点介绍三种:
大部分企业开发的模式一直为HTTP接口开发,也就是我们常说的RESTful风格的服务接口。
的确,对于在接口不多、系统与系统交互较少的情况下,解决信息孤岛初期常使用的一种通信手段;
优点就是简单、直接、开发方便。
利用现成的http协议进行传输。
比如下面这个例子:
POST
接口可能返回一个JSON字符串或者是XML文档。然后客户端再去处理这个返回的信息,从而可以比较快速地进行开发。
对于大型企业来说,内部子系统较多、接口非常多的情况下,RPC框架的好处就显示出来了
RPC服务和HTTP服务还是存在很多的不同点的。
一般来说,RPC服务主要是针对大型企业的
HTTP服务主要是针对小企业的,因为RPC效率更高,而HTTP服务开发迭代会更快。
总之,选用什么样的框架不是按照市场上流行什么而决定的,而是要对整个项目进行完整地评估,
从而在仔细比较两种开发框架对于整个项目的影响,最后再决定什么才是最适合这个项目的。
一定不要为了使用RPC而每个项目都用RPC,而是要因地制宜,具体情况具体分析。
java protobuf 定义rpc服务怎么调用
1.,选择其中的win版本下载,我选择的是protoc-2.4.1-win32.zip
2.下载一个protobuf-java-2.4.1.jar文件(注意,要与你刚才下的proto.exe版本相同)
然后就开始开发了。
步骤:
1.用记事本编写一个.proto文件:
}如:编写的是test.proto
package protobuf;
option java_package = "com.sq.protobuf";
option java_outer_classname = "FirstProtobuf";
message testBuf {
required int32 ID = 1;
required string Url = 2;
}
将其放在与刚解压的protoc.exe同级目录中。
2.在cmd中,到protoc-2.4.1-win32文件夹下,
执行
E:\protoc-2.4.1-win32 protoc.exe --java_out=./ test.proto
则可以找到的一个生成的FirstProtobuf.java文件。
3.在MyEclipse中新建一个java project,建立包com.sq.protobuf,然后将刚才生成的FirstProtobuf.java文件放在其下面。
此时会报错,因为没有引入jar包,在package视图下,将protobuf-java-2.4.1.jar引入,即可解决问题。
java怎么远程调用webservice接口
Java通过WSDL文件来调用webservice:
注意,以下的代码并没有经过真正的测试,只是说明这些情况,不同版本的Axis相差很大,大家最好以apache网站上的例子为准,这里仅仅用于说明其基本用法。
1,直接AXIS调用远程的web service
这种方法比较适合那些高手,他们能直接看懂XML格式的WSDL文件,我自己是看不懂的,尤其我不是专门搞这行的,即使一段时间看懂,后来也就忘记了。直接调用模式如下:
import java.util.Date;
import java.text.DateFormat;
import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import javax.xml.namespace.QName;
import java.lang.Integer;
import javax.xml.rpc.ParameterMode;
public class caClient {
public static void main(String[] args) {
try {
String endpoint = "";
//直接引用远程的wsdl文件
//以下都是套路
Service service = new Service();
Call call = (Call) service.createCall();
call.setTargetEndpointAddress(endpoint);
call.setOperationName("addUser");//WSDL里面描述的接口名称
call.addParameter("userName", org.apache.axis.encoding.XMLType.XSD_DATE,
javax.xml.rpc.ParameterMode.IN);//接口的参数
call.setReturnType(org.apache.axis.encoding.XMLType.XSD_STRING);//设置返回类型
String temp = "测试人员";
String result = (String)call.invoke(new Object[]{temp});
//给方法传递参数,并且调用方法
System.out.println("result is "+result);
}
catch (Exception e) {
System.err.println(e.toString());
}
}
}
2,直接SOAP调用远程的webservice
这种模式我从来没有见过,也没有试过,但是网络上有人贴出来,我也转过来
import org.apache.soap.util.xml.*;
import org.apache.soap.*;
import org.apache.soap.rpc.*;
import java.io.*;
import java.net.*;
import java.util.Vector;
public class caService{
public static String getService(String user) {
URL url = null;
try {
url=new URL("");
} catch (MalformedURLException mue) {
return mue.getMessage();
}
// This is the main SOAP object
Call soapCall = new Call();
// Use SOAP encoding
soapCall.setEncodingStyleURI(Constants.NS_URI_SOAP_ENC);
// This is the remote object we're asking for the price
soapCall.setTargetObjectURI("urn:xmethods-caSynrochnized");
// This is the name of the method on the above object
soapCall.setMethodName("getUser");
// We need to send the ISBN number as an input parameter to the method
Vector soapParams = new Vector();
// name, type, value, encoding style
Parameter isbnParam = new Parameter("userName", String.class, user, null);
soapParams.addElement(isbnParam);
soapCall.setParams(soapParams);
try {
// Invoke the remote method on the object
Response soapResponse = soapCall.invoke(url,"");
// Check to see if there is an error, return "N/A"
if (soapResponse.generatedFault()) {
Fault fault = soapResponse.getFault();
String f = fault.getFaultString();
return f;
} else {
// read result
Parameter soapResult = soapResponse.getReturnValue ();
// get a string from the result
return soapResult.getValue().toString();
}
} catch (SOAPException se) {
return se.getMessage();
}
}
}
3,使用wsdl2java把WSDL文件转成本地类,然后像本地类一样使用,即可。
这是像我这种懒人最喜欢的方式,仍然以前面的global weather report为例。
首先 java org.apache.axis.wsdl.WSDL2Java
原本的网址是,中间个各问号,但是Linux下面它不能解析,所以去掉问号,改为点号。
那么就会出现4个文件:
GlobalWeather.java GlobalWeatherLocator.java GlobalWeatherSoap.java GlobalWeatherSoapStub.java
其中GlobalWeatherSoap.java是我们最为关心的接口文件,如果你对RMI等SOAP实现的具体细节不感兴趣,那么你只需要看接口文件即可,在使用的时候,引入这个接口即可,就好像使用本地类一样。
RPC框架(1 - 实现服务端注册一个服务)
基于这样一个假设,那就是客户端已经知道了服务端的地址,这部分会由后续的服务发现机制完善。通用接口
hello方法需要传递一个对象,HelloObject对象,定义如下:
注意这个对象需要实现 Serializable 接口,因为它需要在调用过程中从客户端传递给服务端。
接着我们在服务端对这个接口进行实现,实现的方式也很简单,返回一个字符串就行:
服务端需要哪些信息,才能唯一确定服务端需要调用的接口的方法呢?
那么服务端知道以上四个条件,就可以找到这个方法并且调用了。我们把这四个条件写到一个对象里,到时候传输时传输这个对象就行了。即 RpcRequest 对象:
那么服务器调用完这个方法后,需要给客户端返回哪些信息呢?
如果调用成功的话,显然需要返回值,如果调用失败了,就需要失败的信息,这里封装成一个 RpcResponse 对象:
这里还多写了两个静态方法,用于快速生成成功与失败的响应对象。其中,statusCode属性可以自行定义,客户端服务端一致即可。
客户端方面,由于在 客户端这一侧我们并没有接口的具体实现类,就没有办法直接生成实例对象 。这时,我们可以 通过动态代理的方式生成实例,并且调用方法时生成需要的RpcRequest对象并且发送给服务端 。
这里我们采用JDK动态代理,代理类是需要实现 InvocationHandler 接口的。
我们需要传递host和port来指明服务端的位置。并且使用getProxy()方法来生成代理对象。
InvocationHandler 接口需要实现invoke()方法,来指明代理对象的方法被调用时的动作。 在这里,我们显然就需要生成一个RpcRequest对象,发送出去,然后返回从服务端接收到的结果即可:
生成RpcRequest很简单,我 使用Builder模式来生成这个对象 。发送的逻辑我使用了一个RpcClient对象来实现,这个对象的作用, 就是将一个对象发过去,并且接收返回的对象。
我的实现很简单,直接使用Java的序列化方式,通过Socket传输。 创建一个Socket,获取ObjectOutputStream对象,然后把需要发送的对象传进去即可,接收时获取ObjectInputStream对象,readObject()方法就可以获得一个返回的对象。
服务端的实现就简单多了, 使用一个ServerSocket监听某个端口,循环接收连接请求,如果发来了请求就创建一个线程,在新线程中处理调用。 这里创建线程采用线程池:
这里简化了一下, RpcServer暂时只能注册一个接口,即对外提供一个接口的调用服务,添加register方法,在注册完一个服务后立刻开始监听:
这里向工作线程WorkerThread传入了socket和用于服务端实例service。
WorkerThread实现了Runnable接口,用于接收RpcRequest对象,解析并且调用,生成RpcResponse对象并传输回去。 run方法如下:
其中,通过class.getMethod方法,传入方法名和方法参数类型即可获得Method对象。如果你上面RpcRequest中使用String数组来存储方法参数类型的话,这里你就需要通过反射生成对应的Class数组了。通过method.invoke方法,传入对象实例和参数,即可调用并且获得返回值。
服务端侧,我们已经在上面实现了一个HelloService的实现类HelloServiceImpl,我们只需要创建一个RpcServer并且把这个实现类注册进去就行了:
服务端开放在9000端口。
客户端方面,我们需要通过动态代理,生成代理对象,并且调用,动态代理会自动帮我们向服务端发送请求的:
我们这里生成了一个HelloObject对象作为方法的参数。
首先启动服务端,再启动客户端,测试结果:
rpc的实现机制是什么
RPC 的全称是 Remote Procedure Call 是一种进程间通信方式。它允许程序调用另一个地址空间(通常是共享网络的另一台机器上)的过程或函数,而不用程序员显式编码这个远程调用的细节。即无论是调用本地接口/服务的还是远程的接口/服务,本质上编写的调用代码基本相同。
比如两台服务器A,B,一个应用部署在A服务器上,想要调用B服务器上应用提供的函数或者方法,由于不在一个内存空间,不能直接调用,这时候需要通过就可以应用RPC框架的实现来解决。
RPC 会隐藏底层的通讯细节(不需要直接处理Socket通讯或Http通讯)
RPC 是一个请求响应模型。客户端发起请求,服务器返回响应(类似于Http的工作方式)
RPC 在使用形式上像调用本地函数(或方法)一样去调用远程的函数(或方法)。
二、常见RPC框架
几种比较典型的RPC的实现和调用框架。
(1)RMI实现,利用java.rmi包实现,基于Java远程方法协议(Java Remote Method Protocol)
和java的原生序列化。
(2)Hessian,是一个轻量级的remoting onhttp工具,使用简单的方法提供了RMI的功能。 基于HTTP协议,采用二进制编解码。
(3)THRIFT是一种可伸缩的跨语言服务的软件框架。thrift允许你定义一个描述文件,描述数据类型和服务接口。依据该文件,编译器方便地生成RPC客户端和服务器通信代码。
二、RPC框架实现原理
在RPC框架中主要有三个角色:Provider、Consumer和Registry。如下图所示:
RPC框架面试总结-RPC原理及实现
节点角色说明:
* Server: 暴露服务的服务提供方。
* Client: 调用远程服务的服务消费方。
* Registry: 服务注册与发现的注册中心。
三、RPC调用流程
RPC基本流程图:
RPC框架面试总结-RPC原理及实现
一次完整的RPC调用流程(同步调用,异步另说)如下:
1)服务消费方(client)调用以本地调用方式调用服务;
2)client stub接收到调用后负责将方法、参数等组装成能够进行网络传输的消息体;
3)client stub找到服务地址,并将消息发送到服务端;
4)server stub收到消息后进行解码;
5)server stub根据解码结果调用本地的服务;
6)本地服务执行并将结果返回给server stub;
7)server stub将返回结果打包成消息并发送至消费方;
8)client stub接收到消息,并进行解码;
9)服务消费方得到最终结果。
RPC框架的目标就是要2~8这些步骤都封装起来,让用户对这些细节透明。
四、服务注册发现
RPC框架面试总结-RPC原理及实现
服务提供者启动后主动向注册中心注册机器ip、port以及提供的服务列表;
服务消费者启动时向注册中心获取服务提供方地址列表,可实现软负载均衡和Failover;
五、使用到的技术
1、动态代理
生成 client stub和server stub需要用到 Java 动态代理技术 ,我们可以使用JDK原生的动态代理机制,可以使用一些开源字节码工具框架 如:CgLib、Javassist等。
2、序列化
为了能在网络上传输和接收 Java对象,我们需要对它进行 序列化和反序列化操作。
* 序列化:将Java对象转换成byte[]的过程,也就是编码的过程;
* 反序列化:将byte[]转换成Java对象的过程;
可以使用Java原生的序列化机制,但是效率非常低,推荐使用一些开源的、成熟的序列化技术,例如:protobuf、Thrift、hessian、Kryo、Msgpack
关于序列化工具性能比较可以参考:jvm-serializers
3、NIO
当前很多RPC框架都直接基于netty这一IO通信框架,比如阿里巴巴的HSF、dubbo,Hadoop Avro,推荐使用Netty 作为底层通信框架。
4、服务注册中心
可选技术:
* Redis
* Zookeeper
* Consul
* Etcd
关于javarpc调用服务和java实现rpc调用的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。
发布于:2022-11-25,除非注明,否则均为
原创文章,转载请注明出处。