赞
踩
一,消息队列服务一般用于设计多系统之间的信息传输,一般这种传输不需要对方对数据做出回应。它最常见的方式是构建异步的生产者-消费者模式。我们在系统开发中,有些业务并不需要及时返回结果,我们可以把这些操作放到队列中,然后另起一个消费者去处理它。比如日志,数据库异步更新。
二,rpc一般是用于服务器与服务器进程之间通信,这种通信有请求和应答。它是建立在底层的socket通信之上的。封装为rpc之后,更加方便建立通信。就像在同一个进程中调用对方的方法一样。它本地的方法名一般和请求到达的服务器的方法名一一对应。这样可以更好的把模块划分。所以它是应对分布式而生的。比如一个网站,一开始可能所有的服务在一个进程中,但是随着业务的增长,一个进程处理不过来,这时就需要把业务拆分成多个,分部到不同的机器上去。
https://zhidao.baidu.com/question/1642201290435943100.html
至于RPC框架,无非就是序列化与反序列化+网络通信,你要愿意的话自己设计都行。懒得设计的话用框架无可厚非,但没你想的差别那么大。
Spring RMI Dubbo Netty grpc protobufthriftRabbitMQ Kafka选型
https://www.zhihu.com/question/52445645
目前,Spring支持四种远程技术:
http://www.cnblogs.com/whatlonelytear/p/5841152.html
Spring除了使用基于HTTP协议的远程调用方案,还为开发者提供了基于RMI机制的远程调用方法,RMI远程调用网络通信实现是基于TCP/IP协议完成的,而不是通过HTTP协议。
在Spring RMI实现中,集成了标准的RMI-JRIM解决方案,该方案是java虚拟机实现的一部分,它使用java序列化来完成对象的传输,是一个java到java环境的分布式处理技术,不涉及异构平台的处理。
http://blog.csdn.net/chjttony/article/details/6567802
前言:之前对于RPC方面的学习多限于对RMI原理的学习,直到今天在看陈康贤前辈的《大型分布式网站架构-设计与实践》这本书的时候,才发现原来RPC可以基于TCP协议也可以基于HTTP协议
在Java中,可以利用Socket API实现基于TCP协议的RPC调用,由服务的调用方与服务的提供方建立Socket连接,并由服务的调用方通过Socket将需要调用的接口名称、方法名称和参数序列化后传递给服务的提供方,服务的提供方反序列化后再利用反射调用相关的方法,最后将结果返回给服务的调用方。整个基于TCP协议的PRC调用大致如此,但是在实例应用中则会进行一系列的封装,譬如RMI便是在TCP协议上传递可序列化的java对象。
而基于HTTP协议的RPC调用则更像是我们访问网页一样,只是它的返回结果更加单一简单。其大致流程为:由服务的调用者向服务的提供者发送请求,这种请求的方式可能是GET、POST、PUT、DELETE等中的一种(服务的提供者可能会根据不同的请求方式做出不同的处理,或者某个方法只允许某种请求方式),而调用的具体方法则根据URL进行方法调用,而方法所需参数则可能是对服务调用方传输过去的XML数据或JSON数据解析后的结果,最后返回JOSN或XML的数据结果(这需要根据实际应用定义相关的协议)。由于目前有很多开源的WEB服务器,如Tomcat,JBoss等,所以其实现起来更加容易(就跟做Web项目一样)。
而基于TCP协议实现的RPC调用,由于TCP协议处于协议栈的下层,能够更加灵活地对协议字段进行定制,减少网络开销,提高性能,实现更大的吞吐量和并发数。但是需要更多地关注底层复杂的细节,实现的代价更高。同时对于不同平台(如安卓、IOS等),需要重新开发出不同的工具包来进行请求发送和响应解析,工作量大,难以快速响应和满足 用户需求。
基于HTTP协议实现的RPC则可以使用JSON和XML格式的请求或响应数据,而JSON和XML作为通用的格式标准,开源的解析工具已经相当成熟,在其上进行二次开发会非常便捷和简单。但是由于HTTP协议是上层协议,发送包含同等内容的信息,使用HTTP协议传输所占用的字节数会比使用TCP协议传输所占用的字节数更高。因此,同等网络环境下,通过HTTP协议传输相同内容,效率会比基于TCP协议的数据效率要低,信息传输所占的时间也会更长
http://blog.csdn.net/t894690230/article/details/50634855
随着系统业务的不断发展增长,对服务的压力逐渐增大,一方面可以通过硬件的方式提高系统的性能;另一方面,可以通过软件的方式来实现系统整体的性能。主流的解决方案,就是讲一个比较大的系统不断进行拆分,拆分为独立的服务系统,不同服务系统之间通过HTTP请求进行通信,或者其他协议进行通信。RPC就是不同系统之间相互通信交换数据服务的有利工具;
(1)序列化 (Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。
(2)之所以要进行序列化,是因为在网络上进行传输的话,无论任何类型的数据,最终都需要转化为二进制流在网络上传输。
(3)数据的发送方需要将传输的对象转化为二进制流才能在网络上进行传输,这也就是序列化的过程;数据的接收方则需要将接受到的二进制流在恢复为对象,这个过程就是对象的反序列化的过程。
序列化和反序列化的方式有很多,常见的有使用Java本身内置的序列化方式、Hession、JSON、XML等。Java内置的可以直接使用Java提供的类不需要引用其他jar包,但是效率不是很高,下边是一张各种序列化空间和性能对比:
解析性能:
序列化之空间开销:
基于Java内置的序列化和反序列化关键代码实现:
首先,远程控制调用RPC的本质还是底层的Scoket通信。对于简单的设计实现来说,其基本思路是:
- 1、服务的调用方Consumer通过Socket建立起与服务的提供方Provider的连接;
- 2、Consumer将需要调用的方法名称和参数通过Socket发送给Provider;(序列化)
- 3、Provider获取Consumer请求的数据并进行解析(反序列化),执行具体的某一个方法,构造返回数据,返回给Consumer;
- 4、Consumer获得Provider返回的数据进行相应的处理;(反序列化+展示)
http://blog.csdn.net/xlgen157387/article/details/53543009 有demo
一般通信分为同步的和异步的。异步的基本都是用消息队列完成,
对于了消息的序列化有很多种方式,最终传的基本都是二进制,不管是使用什么协议序列化的。具体的序列化案例就不说了,因为太多了,如json,protobuf。
对于同步的通信,本质上都是基于socket的RPC,例如Thrift,gRPC,JsonRPC,RESTful API(webservice)等
http://blog.csdn.net/xlgen157387/article/details/53543009
至于传输层上,运用的是TCP协议、UDP协议、亦或是HTTP协议,一概不关心。
衡量一个RPC框架性能的好坏与否,RPC的网络I/O模型的选择,至关重要。在此基础上,设计出来的RPC服务器,可以考虑支持阻塞式同步IO、非阻塞式同步IO、当然还有所谓的多路复用IO模型、异步IO模型。支持不同的网络IO模型,在高并发的状态下,处理性能上会有很大的差别。还有一个衡量的标准,就是选择的传输协议。是基于TCP协议、还是HTTP协议、还是UDP协议?对性能也有一定的影响。但是从我目前了解的情况来看,大多数RPC开源实现框架都是基于TCP、或者HTTP的,目测没有采用UDP协议做为主要的传输协议的。(tomcat底层阻塞io)
明白了RPC的使用原理和性能要求。现在,我们能不能撇开那些RPC开源框架,自己动手开发一个高性能的RPC服务器呢?我想,还是可以的。现在本人就使用Java,基于Netty,开发实现一个高性能的RPC服务器。
为了提高单个节点的通信吞吐量,提高通信性能。如果是基于Java后端的,一般首选的是NIO框架(No-block IO)。但是问题也来了,Java的NIO掌握起来要相当的技术功底,和足够的技术积累,使用起来才能得心应手。一般的开发人员,如果要使用NIO开发一个后端的TCP/HTTP服务器,附带考虑TCP粘包、网络通信异常、消息链接处理等等网络通信细节,开发门槛太高,所以比较明智的选择是,采用业界主流的NIO框架进行服务器后端开发。主流的NIO框架主要有Netty、Mina。它们主要都是基于TCP通信,非阻塞的IO、灵活的IO线程池而设计的,应对高并发请求也是绰绰有余。随着Netty、Mina这样优秀的NIO框架,设计上日趋完善,Java后端高性能服务器开发,在技术上提供了有力的支持保障,从而打破了C++在服务器后端,一统天下的局面。因为在此之前,Java的NIO一直受人诟病,让人敬而远之!
技术原理:
1、定义RPC请求消息、应答消息结构,里面要包括RPC的接口定义模块、包括远程调用的类名、方法名称、参数结构、参数值等信息。
2、服务端初始化的时候通过容器加载RPC接口定义和RPC接口实现类对象的映射关系,然后等待客户端发起调用请求。
3、客户端发起的RPC消息里面包含,远程调用的类名、方法名称、参数结构、参数值等信息,通过网络,以字节流的方式送给RPC服务端,RPC服务端接收到字节流的请求之后,去对应的容器里面,查找客户端接口映射的具体实现对象。
4、RPC服务端找到实现对象的参数信息,通过反射机制创建该对象的实例,并返回调用处理结果,最后封装成RPC应答消息通知到客户端。
5、客户端通过网络,收到字节流形式的RPC应答消息,进行拆包、解析之后,显示远程调用结果。
上面说的是很简单,但是实现的时候,我们还要考虑如下的问题:
1、RPC服务器的传输层是基于TCP协议的,出现粘包咋办?这样客户端的请求,服务端不是会解析失败?好在Netty里面已经提供了解决TCP粘包问题的解码器:LengthFieldBasedFrameDecoder,可以靠它轻松搞定TCP粘包问题。
2、Netty服务端的线程模型是单线程、多线程(一个线程负责客户端连接,连接成功之后,丢给后端IO的线程池处理)、还是主从模式(客户端连接、后端IO处理都是基于线程池的实现)。当然在这里,我出于性能考虑,使用了Netty主从线程池模型。
3、Netty的IO处理线程池,如果遇到非常耗时的业务,出现阻塞了咋办?这样不是很容易把后端的NIO线程给挂死、阻塞?本文的处理方式是,对于复杂的后端业务,分派到专门的业务线程池里面,进行异步回调处理。
4、RPC消息的传输是通过字节流在NIO的通道(Channel)之间传输,那具体如何实现呢?本文,是通过基于Java原生对象序列化机制的编码、解码器(ObjectEncoder、ObjectDecoder)进行实现的。当然出于性能考虑,这个可能不是最优的方案。更优的方案是把消息的编码、解码器,搞成可以配置实现的。具体比如可以通过:protobuf、JBoss Marshalling方式进行解码和编码,以提高网络消息的传输效率。
5、RPC服务器要考虑多线程、高并发的使用场景,所以线程安全是必须的。此外尽量不要使用synchronized进行加锁,改用轻量级的ReentrantLock方式进行代码块的条件加锁。比如本文中的RPC消息处理回调,就有这方面的使用。
6、RPC服务端的服务接口对象和服务接口实现对象要能轻易的配置,轻松进行加载、卸载。在这里,本文是通过Spring容器进行统一的对象管理。
谈谈如何使用Netty开发实现高性能的RPC服务器、Netty实现高性能RPC服务器优化篇之消息序列化。这两篇文章主要设计的思路是,基于Netty构建了一个高性能的RPC服务器,
http://www.cnblogs.com/jietang/p/5615681.html 有demo *******
为什么说要搞定微服务架构,先搞定RPC框架?
http://www.jianshu.com/p/70391a203667 通篇图文并茂,非常好的解释了rpc
###RPC: HTTP vs. TCP
Protocol | 优点 | 缺点 |
---|---|---|
TCP | 处于协议栈的下层,可以对协议字段进行定制,减少网络开销字节数,降低网络开销,提高性能,实现更大的吞吐量和并发数 | 实现成本高(需要考虑多线程并发、锁、I/O etc 复杂的底层细节),难以跨平台 |
HTTP | 很多成熟的容器已经很好处理, like. Tomcat, Apache, Jboss; 成熟的响应格式,like. JSON, XML | 处于协议栈的上层,同等内容信息比 TCP的字节数多,效率相对要低 => gzip 改善 |
https://my.oschina.net/u/2890903/blog/736059
主要参考书:大型分布式网站架构-设计与实践 深入分布式缓存
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。