探索分布式服务框架Dubbo开篇:牛逼哄哄的RPC-阿里云开发者社区

开发者社区> 黄小斜学Java> 正文

探索分布式服务框架Dubbo开篇:牛逼哄哄的RPC

简介: 版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/a724888/article/details/80752488 牛逼哄哄的RPC 原创: 简单的老王 SimpleMain 2016-08-21 这个周日的下午,老王想跟大家聊聊一个听起来牛逼的技术:RPC。
+关注继续查看
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/a724888/article/details/80752488

牛逼哄哄的RPC

原创: 简单的老王 SimpleMain 2016-08-21

这个周日的下午,老王想跟大家聊聊一个听起来牛逼的技术:RPC。

 

 

那是N年前的一天,老王在看一本讲java的技术书(可惜忘了叫啥名字了),突然看到有一章讲RMI的,立马就觉得很好奇。于是乎,就按书上所讲,写了demo程序。当时也就只知道怎么用,却不知道什么原理。直到多年以后,才知道,原来这个RMI和我们今天要聊的RPC几乎是差不多的东西。那他们到底是什么呢?

 

what:

 

先来聊聊RMI。这个玩意儿呢,是sun公司为java定义的一套分布式应用接口,全称:Remote MethodInvocation。他能让java开发者很轻松的实现分布式服务间数据访问。让这个访问就像是本地的方法访问一样。

 

那RPC又是一个什么东东呢?他的全称:Remote Procedure Call。为了实现分布式系统内,不同服务之间数据交换而产生的东东。他使得服务间的数据访问就像是函数调用一样简单和方便,方便写服务的人能聚焦到业务本身,而不用太关注网络交互、数据格式组织、跨平台等多个方面的问题。因此,RMI可以看成是RPC的java版。那为了简化,我们接下来就不细聊RMI,而着重聊聊这个RPC。

 

why:

 

上面已经提到了一些我们使用RPC的原因,那我们就顺着上面的脉络,具体的聊聊吧~

 

1、RPC存在的最重要的意义,就在于,他能简化分布式系统内,不同服务间的数据交换,使得这种交换看起来像本地函数调用一样。所以,我们用他最直接的目的:简化跨机器跨进程的服务调用!

 

2、因为这些东西被封装简化了,所以,他顺带带来的好处就是:代码极大的简化(一会儿我们讲原理的时候就知道了)。

 

3、另外,一般这种调用的封装还支持多语言、多操作系统,所以,他能帮我们极好的实现跨平台跨语言。比如,我们为了执行的高效率,用c语言写了一个加密算法,做成了一个通用服务。而我们用java或者python来实现了一个http的服务,他们若要调用那个加密算法服务,就可以用RPC轻松实现。所以,有了RPC,我们可以根据不同的应用场景,使用不同的语言,来更方便的实现需求。

 

4、更高效的数据传输。因为RPC封装了数据交换的协议,所以可以在里面极大的优化数据传输的算法,从而压缩数据传输的量(还记得老王之前讲过一个zigzag算法嘛)。

 

有了以上的这些好处,当开发分布式系统的时候,作为一个有志向的程序员,有什么理由不使用RPC呢?

 

how:

 

好了,有了上述的铺垫,我们终于可以讲如何来实现这一套东西了。

 

1、简单的模型:

 

为了讲清楚这个原理,我们先从一个最简单的模型开始,讲讲怎么样实现跨系统的数据交换。

 

比方说,我们现在有两个系统(可能不在同一台机器上的两个进程),要交换用户信息:一方是逻辑系统(比方叫blog-system),接收用户提交的user_id,这个系统想用user_id获取用户的详细信息,并展示给用户;另一方是用户系统(比方叫user-system),存储了用户所有的数据(比如:name、nickname、email等等),可以提供根据user_id获取用户详细信息的数据。那我们可以怎么做呢?很简单,我们可以有很多做法,最简单的一种:

 

A、user-system启动一个socket-server,监听某个端口,用json作为传输数据的协议;

 

B、blog-system则用socket去connect我们的server,并按要求发送一个json数据给server;

 

C、server收到请求以后,取出json数据中的user_id,从数据库中查出user,并打包成一个json,返回给client;

 

D、blog-system收到返回的json,包装成对应的格式,展示给用户。

 

 

 

整个过程如上图所示。是不是觉得就是我们在计算机网络里学的那些最基本的东西?

 

2、变复杂的模型:

 

从上面的过程,我们其实可以将这个架构做一下拆分:

 

A、服务端-客户端通讯协议。

 

在我们之前的实例中,我们用的是tcp-socket来作为这样一个协议:server端建立一个server-socket,用来接收客户端的请求;客户端发起一个socket请求;

 

其实,我们也可以用Http、Https等协议作为通讯协议,甚至可以自定义应用层协议。

 

B、数据传输协议。

 

在上面的例子里,我们用json来封装的数据,在server和client之间进行传递。其实,我们也可以用结构体(c语言的struct)、xml等方式来作为数据传输协议来封装数据。更可以用自己定义的协议来传输。

 

有了上述两个东西,我们就可以把他们封装到一个函数中,让他们对外看起来就像是一个函数的访问一样,是不是就达到我们想要的效果呢?

 

3、更完美的模型:

 

A、IDL(Interface Description Language):接口定义语言。

 

如果,我们能将远程调用函数的定义,用一种通用的、跨平台的语言来编写,然后,再用编译器生成不同语言的代码(比如:java、c、c++、php等),这样,我们是否就可以轻松的做到跨平台、跨语言的支持了呢?

 

比如,以下就是facebook开源的rpc框架thrift的idl定义方式:

 

service TUserService

{

    struct.TUser getUser (1: required i32 uid);

}

 

看起来是不是跟我们平时写的语言代码很相似呢?

 

有了这个东东,我们就可以用一个编译工具,生成不同语言的代码了。

 

B、高承载能力的server模型。

 

当我们要启动一个server的时候,最简单的就是按我们之前的那种方式,启动一个server-socket。但是这个模型太简单,以至于只要轻轻的给一些压力,服务就可能崩塌。因此,我们需要一个高承载能力的server模型。

 

现在在linux平台上,大家基本都使用epoll模型。这个是非阻塞的事件驱动模型,能够根据请求事件来触动业务逻辑。所以具有很强的负载能力。现在主流的服务器,比如:nginx、mina、netty等等,都基本采用这种底层模型。

 

有了这个server做基础,我们才能保证服务的压力能抗的住,才能使得rpc具有相对稳定的调用。

 

C、简单准确的通讯协议。

 

这个协议就跟我们tcp、http协议一样,能够描述整个包有多大,哪个地方是协议头、哪个地方是数据包、哪个地方是结束符等等。这个协议越简单越好,使得我们传输的数据量越小。

 

 

 

比如上图就是tcp协议,他定义了数据的大小、数据的校验、序列号等,就是为了保证数据能准确传输到对端。我们也可以仿照这样的协议,来定制我们的协议,比如我们协议包含:版本号、数据包的大小、数据包的校验、数据包等这样的数据。

 

D、高压缩比 && 快速序列化与反序列化的数据协议。

 

这个就是我们的数据包的定义。我们可以用文本的json、xml作为数据协议,当然也可以用结构体、java序列化对象等二进制协议作为数据协议。更可以我们定义自己的数据协议。但是这个协议要尽量的小:以保证我们每次传输的数据量尽可能的少;也要保证序列化和反序列化尽量的快:以保证我们的调用时间尽可能的短。

 

所以,在thrift中,定义TBinaryProtocol、TCompactProtocol等这样的二进制压缩协议,来保证我们的数据传输的速度、打包和解包的速度。

 

好了,讲了这么多空虚的概念。我们就来看看现有的这些rpc工具是怎么做的吧。

 

google的protobuf:

 

这个是一个非常牛逼的rpc工具。不过他只提供了IDL和数据协议。就是只管生成不同语言的实现代码、将一个对象打包成二进制的数据;数据到达对端,他负责解包。然而具体怎么样提供服务、怎么样传输数据,他并不负责。

 

如果我们要使用这个东东,就需要再弄一个server来接收服务,还要弄一个传输协议来传递数据。常见的,在java下,大家喜欢用netty+protobuf来实现RPC的功能。四要素:

 

IDL:protobuf

Server: netty

传输协议:TCP

数据协议:protobuf

 

facebook的thrift:

 

这个相比于protobuf,提供了server和传输协议的支持。比如,java的实现代码中,就有TThreadPoolServer、TThreadedSelectorServer等多个server模型,便于我们根据业务规模选择不同的模型。

 

同时,他还提供了TSocket、TSaslTransport、THttpClient等多种传输协议,来实现数据的传输功能。

 

所以,他集成RPC的四个要素,用起来更简单方便一些。

 

其他的,诸如以前的CORBA、RMI、Web-Service等等,都是类似的原理。所以,听起来高大上的RPC,实际上都是我们常规的技术,然后进行了组合和封装,让使用者更方便易用(也可以在面试的时候去吓唬人,哈哈哈~)。

 

好了,关于RPC理论的技术,大体就讲这么多。如果大家想深入的去了解,建议去阅读thrift源代码,很不错的实践代码。老王之前也总结过thrift的代码架构,后面找时间整理出来,分享给大家。、

微信公众号【Java技术江湖】一位阿里 Java 工程师的技术小站。(关注公众号后回复”Java“即可领取 Java基础、进阶、项目和架构师等免费学习资料,更有数据库、分布式、微服务等热门技术学习视频,内容丰富,兼顾原理和实践,另外也将赠送作者原创的Java学习指南、Java程序员面试指南等干货资源)


wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==


版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
Gin 框架:实现分布式日志追踪
通过一个完整例子,在基于 Gin 框架中实现分布式日志追踪。
31 0
从Netflix的Hystrix框架理解服务熔断和服务降级
本文讲的是从Netflix的Hystrix框架理解服务熔断和服务降级,伴随着微服务架构被宣传得如火如荼,一些概念也被推到了我们面前,其实大多数概念以前就有,但很少被提的这么频繁。想起有人总结的一句话,微服务架构的特点就是:“一解释就懂,一问就不知,一讨论就吵架”。
3506 0
(四):C++分布式实时应用框架——状态中心模块
C++分布式实时应用框架——状态中心模块   上篇:(三):C++分布式实时应用框架——系统管理模块     技术交流合作QQ群:436466587 欢迎讨论交流     版权声明:本文版权及所用技术归属smartguys团队所有,对于抄袭,非经同意转载等行为保留法律追究的权利!     状态中心是分布式系统中不可或缺的部分。
1130 0
python模块介绍- SocketServer 网络服务框架
来源:https://my.oschina.net/u/1433482/blog/190612 摘要: SocketServer简化了网络服务器的编写。它有4个类:TCPServer,UDPServer,UnixStreamServer,UnixDatagramServer。
849 0
Ali-Perseus(擎天):统一深度学习分布式通信框架 [弹性人工智能]
【作者】  驭策(龚志刚) 笋江(林立翔)蜚廉(王志明) 昀龙(游亮) 近些年来,深度学习在图像识别,自然语言处理等领域快速发展。各种网络模型,需要越来越多的计算力来进行训练。以典型的中等规模的图像分类网络Resnet50为例,基准的训练精度为Top-1 76%, Top-5 为 93%,为达到此.
4977 0
RPC框架Dubbo深入分析
1,背景 随着互联网的发展,网站应用的规模不断扩大,常规的垂直应用架构已无法应对,分布式服务架构以及流动计算架构势在必行,亟需一个治理系统确保架构有条不紊的演进 单一应用架构 当网站流量很小时,只需一个应用,将所有功能都部署在一起,以减少部署节点和成本 此时,用于简化增删改查工作量的 ...
2176 0
Mars——基于张量的统一分布式计算框架
很高兴在这里宣布我们的新项目:Mars,一个基于张量的统一分布式计算框架。我们已经在 Github 开源:https://github.com/mars-project/mars 。 背景 Python Python 是一门相当古老的语言了,如今,在数据科学计算、机器学习、以及深度学习领域,Python 越来越受欢迎。
9337 0
+关注
黄小斜学Java
欢迎关注我的微信公众号【黄小斜学Java】 目前专注分享Java领域干货,不限于BAT面试,算法、计算机基础、数据库、分布式、spring全家桶、微服务、高并发、JVM、Docker容器,ELK、大数据等相关知识,希望我们可以一起进步。
246
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
文娱运维技术
立即下载
《SaaS模式云原生数据仓库应用场景实践》
立即下载
《看见新力量:二》电子书
立即下载