常用的RPC框架(rpc框架是什么意思)
ccwgpt 2024-09-17 12:49 140 浏览 0 评论
1. 为什么要使用RPC?
RPC(remote procedure call)是指远程过程调用,比如两台服务器A和B,A服务器上部署一个应用,B服务器上部署一个应用,A服务器上的应用想调用B服务器上的应用提供的接口,由于不在一个内存空间,不能直接调用,所以需要通过网络来表达调用的语义和传达调用的数据。
RPC(remote procedure call,远程过程调用):
首先,要解决通讯的问题,主要是通过客户端和服务器端之间建立TCP连接,远程过程调用的所有交换的数据都在这个连接里传输。连接可以是按需连接,调用结束后就断掉,也可以是长连接,多个远程过程调用共享一个连接。
第二,要解决寻址的问题,A服务器上的应用要调用B服务器上的应用,A服务器上的应用需要通过底层RPC框架得知:如何连接到B服务器(主机或IP地址)以及特定的端口,方法的名称等信息,这样才能完成调用。
第三,A服务器上的应用发起远程调用时,方法的参数需要通过底层的网络协议如TCP传递到B服务器,由于网络协议是基于二进制的,内存中的参数需要序列化成二进制形式,然后再通过寻址和传输将序列化的二进制发送给B服务器。
第四:B服务器收到请求后,需要进行反序列化,恢复为内存中的表达方式,然后找到对应的方法进行本地调用并返回,序列化返回值并发送给A服务器。
第五:A服务器收到B服务器的返回值后,进行反序列化,恢复为内存中的表达方式,然后交给A服务器上的应用进行处理。
RPC的协议有很多,比如Java RMI、WebService的RPC风格、Hession、Thrift、REST API
2. RPC、RMI、SOAP、REST的区别RMI(remote method invocation,面向对象的远程方法调用)
RPC(remote procedure call,远程过程调用)
SOAP(simple object access protoal,简单对象访问协议)
REST(representational state transfer,表达性状态转移)可以都理解为调用远程方法的一些通信技术“风格”:
· RMI就好比它是本地工作,采用tcp/ip协议,客户端直接调用服务端上的一些方法。优点是强类型,编译期可检查错误,缺点是只能基于JAVA语言,客户机与服务器紧耦合。
· RPC是一个泛化的概念,严格来说一切远程过程调用手段都属于rpc范畴,包括rmi、hessian、soap、thrift、protobuf等等。
· SOAP是在XML-RPC基础上,使用标准的XML描述了RPC的请求信息(URI/类/方法/参数/返回值)。因为XML-RPC只能使用有限的数据类型种类和一些简单的数据结构,SOAP能支持更多的类型和数据结构。优点是跨语言,非常适合异步通信和针对松耦合的C/S,缺点是必须做很多运行时检查。
比较,它采用简单的URL方式来代替一个对象,优点是轻量,可读性较好,不需要其他类库支持,缺点是URL可能会很长,不容易解析。
3. Java RMI
Java RMI(Romote Method Invocation)是一种基于Java的远程方法调用技术,是Java特有的一种RPC实现。它能够部署在不同主机上的Java对象之间进行透明的通信与方法调用。
RMI工作原理:
首先,在一个JVM中启动rmiregistry服务,启动时可以指定服务监听的端口,也可以使用默认的端口。
其次,RMIServer在本地先实例化一个提供服务的实现类,然后通过RMI提供的Naming,Context,Registry等类的bind或rebind方法将刚才实例化好的实现类注册到RMIService上并对外暴露一个名称。
最后,RMIClient通过本地的接口和一个已知的名称(即RMIServer暴露出的名称)再使用RMI提供的Naming,Context,Registry等类的lookup方法从RMIService那拿到实现类。这样虽然本地没有这个类的实现类,但所有的方法都在接口里了,想怎么调就怎么调。
RMI 采用stubs 和 skeletons 来进行远程对象(remote object)的通讯。stub 充当远程对象的客户端代理,有着和远程对象相同的远程接口,远程对象的调用实际是通过调用该对象的客户端代理对象stub来完成的,通过该机制RMI就好比它是本地工作,采用tcp/ip协议,客户端直接调用服务端上的一些方法。优点是强类型,编译期可检查错误,缺点是只能基于Java语言,客户机与服务器紧耦合。
RMI使用Demo:
定义RMI对外服务接口:RMI接口方法定义必须显示声明抛出RemoteException异常。
package com.yyy.RMIDemo.java.server;
import java.rmi.Remote;
import java.rmi.RemoteException;
/**
* RMI对外服务接口
*
*/
public interface HelloService extends Remote{
public String sayHello(String someone) throws RemoteException;
}
服务端接口实现:服务端方法实现必须继承UnicastRemoteObject类,该类定义了服务调用方与服务提供方对象实例,并建立一对一的连接。
package com.yyy.RMIDemo.java.server;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
/**
* 服务器端接口实现
*
*/
public class HelloServiceImpl extends UnicastRemoteObject implements HelloService {
private static final long serialVersionUID = 4176511759435216154L;
protected HelloServiceImpl() throws RemoteException {
super();
// TODO Auto-generated constructor stub
}
@Override
public String sayHello(String someone) throws RemoteException {
// TODO Auto- generated method stub
return "Hello" + someone;
}
}
RMI的通信端口是随机产生的,因此有可能被防火墙拦截,为了防止被防火墙拦截,需要强制指定RMI的通信端口。一般通过自定义一个RMISocketFactory类来实现,代码如下:
package com.yyy.RMIDemo.java.server;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.rmi.server.RMISocketFactory;
public class CustomerSocketFactory extends RMISocketFactory{
@Override
public ServerSocket createServerSocket(int port) throws IOException {
// TODO Auto-generated method stub
if (port == 0) {
port = 8051;
}
System.out.println("rmi notify port : " + port);
return new ServerSocket(port);
}
//指定通信端口,防止被防火墙拦截
@Override
public Socket createSocket(String host, int port) throws IOException {
// TODO Auto-generated method stub
return new Socket(host, port);
}
}
RMI的通信端口是随机产生的,因此有可能被防火墙拦截,为了防止被防火墙拦截,需要强制指定RMI的通信端口。一般通过自定义一个RMISocketFactory类来实现,代码如下:
package com.yyy.RMIDemo.java.server;
import java.rmi.Naming;
import java.rmi.registry.LocateRegistry;
import java.rmi.server.RMISocketFactory;
public class ServerMain {
public static void main(String[] args) throws Exception {
//创建服务
HelloService helloService = new HelloServiceImpl();
//注册服务
LocateRegistry.createRegistry(8801);
//指定通信端口,防止被防火墙拦截
RMISocketFactory.setSocketFactory(new CustomerSocketFactory());
Naming.bind("rmi://localhost:8801/helloService", helloService);
System.out.println("ServceMain provide service now");
}
}
客户端远程调用RMI服务代码:
package com.yyy.RMIDemo.java.client;
import java.rmi.Naming;
import com.yyy.RMIDemo.java.server.HelloService;
public class ClientMain {
public static void main(String[] args) throws Exception {
HelloService helloService =
(HelloService)Naming.lookup("rmi://localhost:8801/helloService");
System.out.println("RMI 客户端接收到的结果是:" + helloService.sayHello("RMI"));
}
}
服务端RMI服务启动:
package com.yyy.RMIDemo.java.server;
import java.rmi.Naming;
import java.rmi.registry.LocateRegistry;
import java.rmi.server.RMISocketFactory;
public class ServerMain {
public static void main(String[] args) throws Exception {
//创建服务
HelloService helloService = new HelloServiceImpl();
//注册服务
LocateRegistry.createRegistry(8801);
//指定通信端口,防止被防火墙拦截
RMISocketFactory.setSocketFactory(new CustomerSocketFactory());
Naming.bind("rmi://localhost:8801/helloService", helloService);
System.out.println("ServceMain provide service now");
}
}
客户端远程调用RMI服务代码:
package com.yyy.RMIDemo.java.client;
import java.rmi.Naming;
import com.yyy.RMIDemo.java.server.HelloService;
public class ClientMain {
public static void main(String[] args) throws Exception {
HelloService helloService =
(HelloService)Naming.lookup("rmi://localhost:8801/helloService");
System.out.println("RMI 客户端接收到的结果是:" + helloService.sayHello("RMI"));
}
}
先运行服务器端程序ServerMain,然后运行ClinetMain,运行结果如下:
RMI 客户端接收到的结果是:HelloRMI
4. Hessian
Hessian 是由 caucho 提供的一个基于 binary-RPC 实现的远程通讯 library 。Hessian基于Http协议进行传输。
Binary-RPC 是一种和 RMI 类似的远程调用的协议,它和 RMI 的不同之处在于它以标准的二进制格式来定义请求的信息 ( 请求的对象、方法、参数等 ) ,这样的好处是什么呢,就是在跨语言通讯的时候也可以使用。传输协议基于TCP。
Hessian可通过Servlet提供远程服务,需要将匹配某个模式的请求映射到Hessian服务。也可Spring框架整合,通过它的DispatcherServlet可以完成该功能,DispatcherServlet可将匹配模式的请求转发到Hessian服务。Hessian的server端提供一个servlet基类, 用来处理发送的请求,而Hessian的这个远程过程调用,完全使用动态代理来实现的,,建议采用面向接口编程,Hessian服务通过接口暴露。
Hessian处理过程示意图:客户端——>序列化写到输出流——>远程方法(服务器端)——>序列化写到输出流 ——>客户端读取输入流——>输出结果
Spring + Hessian实现服务器端的demo:
在工程中导入hessian的jar包在web.xml中,我们配置SpringMVC的DispatcherServlet:
<!-- Spring hessian servlet -->
<servlet>
<servlet-name>hessian</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-hessian.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
<async-supported>true</async-supported>
</servlet>
<servlet-mapping>
<servlet-name>hessian</servlet-name>
<url-pattern>/pubservice/*</url-pattern>
</servlet-mapping>
spring-hessian.xml的配置:
<bean id="/testService" class="com.example.platform.hession.MyHessianServiceExporter">
<property name="service" ref="testServiceImpl" />
<property name="serviceInterface" value="com.xinwei.platform.pubservice.TestService" />
</bean>
使用了org.springframework.remoting.caucho.HessianServiceExporter来发布服务。将程序部署在tomcat中。如果我们想从HessianServiceExporter的handleRequest方法中可以获得客户端request,那我们就会有很多种方法得到此request;Aop方式或重写方法,我们采用重写的方式:
/**
*
*/
package com.example.platform.hession;
import javax.servlet.ServletRequest;
/**
* Hession service线程上下文,用以线程安全地保存客户端request
*
*/
public class HessionContext {
private ServletRequest request;
private static final ThreadLocal<HessionContext> localContext
= new ThreadLocal<HessionContext>(){
@Override
public HessionContext initialValue(){
return new HessionContext();
}
};
private HessionContext(){
}
public static ServletRequest getRequest() {
return localContext.get().request;
}
public static void setRequest(ServletRequest request) {
localContext.get().request = request;
}
public static void clear() {
localContext.get().request = null;
}
}
自定义类:
/**
*
*/
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.remoting.caucho.HessianExporter;
import org.springframework.web.HttpRequestHandler;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.util.NestedServletException;
/**
*
*/
public class MyHessianServiceExporter extends HessianExporter implements HttpRequestHandler {
private static final Logger logger = LoggerFactory.getLogger(InmpServiceExporter.class);
@Override
public void handleRequest(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
// TODO Auto-generated method stub
if (!"POST".equals(request.getMethod())){
throw new HttpRequestMethodNotSupportedException(
request.getMethod(), new String[]{"POST"},
"HessionSeriviceExporter only supports POST requests");
}
response.setContentType(CONTENT_TYPE_HESSIAN);
try {
//保存request到Hession线程上下文
HessionContext.setRequest(request);
invoke(request.getInputStream(), response.getOutputStream());
} catch (Throwable ex) {
// TODO: handle exception
logger.error("Hession skeleton invocation failed");
throw new NestedServletException("Hession skeleton invocation failed", ex);
} finally{
HessionContext.clear();
}
}
}
Service开发中就可以直接使用 HessianContext.getRequest(); 来获得客户端的request了,所有的客户端信息随你所用了,而且是线程安全的。
服务器端服务接口:
package com.example.platform.pubservice;
public interface TestService {
public String sayHello(String datas);
}
接口实现类:
package com.example.platform.pubservice.impl;
import com.example.platform.pubservice.TestService;
public class TestServiceImpl extends InmpHessianHandle implements TestService{
@Override
public String sayHello(String datas) {
// TODO Auto-generated method stub
return "Hello " + datas;
}
}
client调用:
public class TestClient {
public static void main(String[] args) {
try {
String url = "http://localhost:8080/HessianDemo/pubservice/testService";
HessianProxyFactory factory = new HessianProxyFactory();
factory.setOverloadEnabled(true);
TestService testService = (TestService) factory.create(TestService.class, url);
System.out.println(basic.sayHello("SW"));
}catch (Exception e){
e.printStackTrace();
}
}
}
5. WebService
WebService是一种跨平台的RPC技术协议。
WebService技术栈由SOAP(简单对象访问协议)、UDDI(统一描述、发现与集成)、WSDL(网络服务描述语言:用来描述Service、以及如何访问WebService)组成。SOAP是一种使用XML进行数据编码的通信协议。独立于平台、独立于语言,简单可扩展。
WebService常用的两种实现:CXF和Axis2
详解见 从零开始写分布式服务框架 1.3小节
目前三种主流的web服务实现方法:
REST(新型):表象化状态转变 (软件架构风格)RESTEasy、Wink、CXF、Axis2…….
SOAP(比较成熟):简单对象访问协议 Xfire、Axis2、CXF、Axis1X
ML-RPC(淘汰):远程过程调用协议(慢慢被soap 所取代)
1、Java开发WebService最重要的两个规范:
JSR-224 (JAX-WS:Java API for XML-Based Web Services ) ,主要使用soap协议,使用wsdl来描述;
JSR-311 (JAX-RS:The Java API for RESTful Web Services),简化了 web service 的设计,它不再需要 wsdl ,也不再需要 soap 协议,而是通过最简单的 http 协议传输数据 ( 包括 xml 或 json) 。既简化了设计,也减少了网络传输量(因为只传输代表数据的 xml 或 json ,没有额外的 xml 包装)。
JAX-WS是针对WebService。而JAX-RS是针对RESTful HTTP Service。RESTful HTTP Service相关介绍可以参考:RESTful Service API 设计最佳工程实践和常见问题解决方案JAX-WS与JAX-RS两者是不同风格的SOA架构。前者以动词为中心,指定的是每次执行函数。而后者以名词为中心,每次执行的时候指的是资源。
JAX-RS是JAVA EE6 引入的一个新技术。是一个Java 编程语言的应用程序接口,支持按照表述性状态转移(REST)架构风格创建Web服务。
JAX-RS使用了Java SE5引入的Java标注来简化Web服务的客户端和服务端的开发和部署。
JAX-WS规范是一组XML web services的JAVA API,JAX-WS允许开发者可以选择RPC-oriented或者message-oriented 来实现自己的web services。
支持JAX-WS服务规范的框架有:CXF,Axis,Xfire。结合java语言均可可实现JAX-WS
支持JAX-RS服务规范的框架有:
1.CXF——XFire和Celtix的合并
2.Jersey——Sun公司的JAX-RS参考实现。
3.RESTEasy——JBoss的JAX-RS项目。
4.Restlet——也许是最早的REST框架了,它JAX-RS之前就有了。
在分布式服务框架中,除了实现RPC的特性以外,还包括负载均衡策略以及实现,服务的注册、发布与引入。服务的高可用策略以及服务治理等特性。
JAVA进阶架构程序员福利:我这里还总结整理了比较全面的JAVA相关的面试资料,都已经整理成了
PDF版,这些都可以分享给大家,关注私信我:【806】,免费领取!
相关推荐
- 2025南通中考作文解读之四:结构框架
-
文题《继续走,迈向远方》结构框架:清晰叙事,层层递进示例结构:1.开头(点题):用环境描写或比喻引出“走”与“远方”,如“人生如一条长路,每一次驻足后,都需要继续走,才能看见更美的风景”。2.中间...
- 高中数学的知识框架(高中数学知识框架图第三章)
-
高中数学的知识框架可以划分为多个核心板块,每个板块包含具体的知识点与内容,以下为详细的知识框架结构:基础知识1.集合与逻辑用语:涵盖集合的概念、表示方式、性质、运算,以及命题、四种命题关系、充分条件...
- 决定人生的六大框架(决定人生的要素)
-
45岁的自己混到今天,其实是失败的,要是早点意识到影响人生的六大框架,也不至于今天的模样啊!排第一的是环境,不是有句话叫人是环境的产物,身边的环境包括身边的人和事,这些都会对一个人产生深远的影响。其次...
- 2023年想考过一级造价师土建计量,看这30个知识点(三)
-
第二章工程构造考点一:工业建筑分类[考频分析]★★★1.按厂房层数分:(1)单层厂房;(2)多层厂房;(3)混合层数厂房。2.按工业建筑用途分:(1)生产厂房;(2)生产辅助厂房;(3)动力用厂房;(...
- 一级建造师习题集-建筑工程实务(第一章-第二节-2)
-
建筑工程管理与实务题库(章节练习)第一章建筑工程技术第二节结构设计与构造二、结构设计1.常见建筑结构体系中,适用建筑高度最小的是()。A.框架结构体系B.剪力墙结构体系C.框架-剪力墙结构体系D...
- 冷眼读书丨多塔斜拉桥,这么美又这么牛
-
”重大交通基础设施的建设是国民经济和社会发展的先导,是交通运输行业新技术集中应用与创新的综合体现。多塔斜拉桥因跨越能力强、地形适应性强、造型优美等特点,备受桥梁设计者的青睐,在未来跨越海峡工程中将得...
- 2021一级造价师土建计量知识点:民用建筑分类
-
2021造价考试备考开始了,学霸君为大家整理了一级造价师备考所用的知识点,希望对大家的备考道路上有所帮助。 民用建筑分类 一、按层数和高度分 1.住宅建筑按层数分类:1~3层为低层住宅,4~6层...
- 6个建筑结构常见类型,你都知道吗?
-
建筑结构是建筑物中支承荷载(作用)起骨架作用的体系。结构是由构件组成的。构件有拉(压)杆、梁、板、柱、拱、壳、薄膜、索、基础等。常见的建筑结构类型有6种:砖混结构、砖木结构、框架结构、钢筋混凝土结构、...
- 框架结构设计经验总结(框架结构设计应注意哪些问题)
-
1.结构设计说明主要是设计依据,抗震等级,人防等级,地基情况及承载力,防潮抗渗做法,活荷载值,材料等级,施工中的注意事项,选用详图,通用详图或节点,以及在施工图中未画出而通过说明来表达的信息。2.各...
- 浅谈混凝土框架结构设计(混凝土框架结构设计主要内容)
-
浅谈混凝土框架结构设计 摘要:结构设计是个系统的全面的工作,需要扎实的理论知识功底,灵活创新的思维和严肃认真负责的工作态度。钢筋混凝土框架结构虽然相对简单,但设计中仍有很多需要注意的问题。本文针...
- 2022一级建造师《建筑实务》1A412020 结构设计 精细考点整理
-
历年真题分布统计1A412021常用建筑结构体系和应用一、混合结构体系【2012-3】指楼盖和屋盖采用钢筋混凝土或钢木结构,而墙和柱采用砌体结构建造的房屋,大多用在住宅、办公楼、教学楼建筑中。优点:...
- 破土动工!这个故宫“分院”科技含量有点儿高
-
故宫“分院”设计图。受访者供图近日,位于北京海淀区西北旺镇的故宫北院区项目已开始破土动工,该项目也被称作故宫“分院”,筹备近十年之久。据悉,故宫本院每年展览文物的数量不到1万件,但是“分院”建成后,预...
- 装配式结构体系介绍(上)(装配式结构如何设计)
-
PC构件深化、构件之间连接节点做法等与相应装配式结构体系密切相关。本节列举目前常见的几种装配式结构体系:装配整体式混凝土剪力墙结构体系、装配整体式混凝土框架结构体系、装配整体式混凝土空腔结构体系(S...
- 这些不是双向抗侧结构体系(这些不是双向抗侧结构体系的特点)
-
双向抗侧土木吧规范对双向抗恻力结构有何规定?为何不应采用单向有墙的结构?双向抗侧土木吧1.规范对双向抗侧力结构体系的要求抗侧力体系是指抵抗水平地震作用及风荷载的结构体系。对于结构体系的布置,规范针对...
- 2022一级建造师《建筑实务》1A412020 结构设计 精细化考点整理
-
1A412021常用建筑结构体系和应用一、混合结构体系【2012-3】指楼盖和屋盖采用钢筋混凝土或钢木结构,而墙和柱采用砌体结构建造的房屋,大多用在住宅、办公楼、教学楼建筑中。优点:抗压强度高,造价...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- MVC框架 (46)
- spring框架 (46)
- 框架图 (58)
- flask框架 (53)
- quartz框架 (51)
- abp框架 (47)
- jpa框架 (47)
- laravel框架 (46)
- springmvc框架 (49)
- 分布式事务框架 (65)
- scrapy框架 (56)
- shiro框架 (61)
- 定时任务框架 (56)
- java日志框架 (61)
- JAVA集合框架 (47)
- grpc框架 (55)
- ppt框架 (48)
- 内联框架 (52)
- winform框架 (46)
- gui框架 (44)
- cad怎么画框架 (58)
- ps怎么画框架 (47)
- ssm框架实现登录注册 (49)
- oracle字符串长度 (48)
- oracle提交事务 (47)