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

本文涉及的产品
数据传输服务 DTS,数据迁移 small 3个月
推荐场景:
MySQL数据库上云
简介: 版权声明:本文为博主原创文章,未经博主允许不得转载。 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==


相关实践学习
RocketMQ一站式入门使用
从源码编译、部署broker、部署namesrv,使用java客户端首发消息等一站式入门RocketMQ。
Sqoop 企业级大数据迁移方案实战
Sqoop是一个用于在Hadoop和关系数据库服务器之间传输数据的工具。它用于从关系数据库(如MySQL,Oracle)导入数据到Hadoop HDFS,并从Hadoop文件系统导出到关系数据库。 本课程主要讲解了Sqoop的设计思想及原理、部署安装及配置、详细具体的使用方法技巧与实操案例、企业级任务管理等。结合日常工作实践,培养解决实际问题的能力。本课程由黑马程序员提供。
相关文章
|
11天前
|
监控 负载均衡 Cloud Native
ZooKeeper分布式协调服务详解:面试经验与必备知识点解析
【4月更文挑战第9天】本文深入剖析ZooKeeper分布式协调服务原理,涵盖核心概念如Server、Client、ZNode、ACL、Watcher,以及ZAB协议在一致性、会话管理、Leader选举中的作用。讨论ZooKeeper数据模型、操作、会话管理、集群部署与管理、性能调优和监控。同时,文章探讨了ZooKeeper在分布式锁、队列、服务注册与发现等场景的应用,并在面试方面分析了与其它服务的区别、实战挑战及解决方案。附带Java客户端实现分布式锁的代码示例,助力提升面试表现。
30 2
|
12天前
|
存储 人工智能 PyTorch
基于PyTorch/XLA的高效分布式训练框架
基于PyTorch/XLA的高效分布式训练框架
21 2
|
25天前
|
XML Dubbo Java
【Dubbo3高级特性】「框架与服务」服务的异步调用实践以及开发模式
【Dubbo3高级特性】「框架与服务」服务的异步调用实践以及开发模式
25 0
|
29天前
|
人工智能 算法 PyTorch
TorchAcc:基于 TorchXLA 的分布式训练框架
阿里云研究员、阿里云人工智能平台 PAI 技术负责人--林伟在GTC 2024 大会 China AI Day 线上中文演讲专场上介绍了TorchAcc,这是一个基于 PyTorch/XLA 的大模型分布式训练框架。
|
1月前
|
SQL 弹性计算 分布式计算
TiDB计算层详解:分布式计算框架与查询优化机制
【2月更文挑战第26天】本文将深入剖析TiDB的计算层,详细解析其分布式计算框架和查询优化机制。通过了解计算层的核心组件和工作原理,我们可以更好地理解TiDB如何高效处理SQL查询和计算任务。本文将从计算层的架构、任务分发、查询优化等方面展开介绍,帮助读者全面掌握TiDB计算层的关键技术和优势。
|
2月前
|
监控 负载均衡 Dubbo
|
25天前
|
消息中间件 算法 Java
【亿级数据专题】「分布式服务框架」 盘点本年度我们探索服务的保障容量的三大关键方案实现
【亿级数据专题】「分布式服务框架」 盘点本年度我们探索服务的保障容量的三大关键方案实现
182 0
|
1月前
|
NoSQL Java Redis
分布式锁框架Lock4j简单使用
最近项目中使用到了Lock4j的分布式锁组件,小编今天就带大家学习一下该框架,以及如何在我们项目中进行集成使用。
|
1月前
|
SpringCloudAlibaba Dubbo Java
SpringCloud Alibaba集成Dubbo实现远程服务间调用
SpringCloud Alibaba集成Dubbo实现远程服务间调用
|
1月前
|
运维 监控 Java
推荐一款好用的Java分布式任务调度框架!
推荐一款好用的Java分布式任务调度框架!
168 0