RPC与Netty是什么鬼

作者:刘鹏
链接: http://www.zhihu.com/question/25536695/answer/54052580
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

[Mr.Snail注] :很通俗易懂的一篇文章。现在想想去年开发过程中遇到了大端小端问题,也挺有意思。
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

RPC, 远程过程调用直观说法就是A通过网络调用B的过程方法。

通信中的协议是你自己规定的,比如你可以规定说当A向B发送数字1, B就打印hello world, 并返回数字1给A, 如果发送数字2,B就打印hello, guy.并发送数字2给A.

这就是一个简单的RPC示例,实际上natty就是干这个的,只不过它提供一套框架给你,让你可以定义自己的规则,实现B里面的函数。

我们来想一想,当A要把数字1发送给B要怎么办呢,你需要用socket,B是server, A是client, B执行完以后再把1通过socket写回即可。你可以用AUPE书中的例子很容易就构建出来。

问题到这里,应该就结束了,事实上就是这么简单,那为什么需要RPC框架呢?

当你给B发送1或者2就可以区分函数方法,但是你不可能写100个函数打印100个字符,你需要在发送1的时候,再接着发送一个字符串,这样B只要实现一个通用的print函数就够了。

我们继续思考,当你想发送一个数字比如65534给B的时候,我们知道socket是按照字节接受数据的,一个字节最大为255也就是0xff, 如果要发送65534你有两种方法,第一把65534当作5个字符6,5,5,3,4然后让socket接受5个字符。第二,你可以把65534变成二进制0xfffe, 这样你可以先发送一个0xff再发送一个0xfe,也就是先发一个255再发一个254再拼装。

另外在拼装这255和254的时候,我们知道不同体系结构的CPU字节序是不一样的,因此,你需要解决大端小端字节序的问题。否则对于一个32位机器上,65534作为一个int型可能会是0xfffe0000,或者0x0000feff,这取决于你如何发送和打包它。

对于相对复杂的RPC, 我们发送的一个数据包往往既包含字符串又包含数字,这样我们就需要把他们切割开来然后分别解码编码。

这个部分就叫做序列化反序列化,在高级一点的RPC框架中,甚至可以做到把
一个类从A扔给B.用到的还是这个方法,只是把类这个类型也放进去了。

对于脚本语言比如Lua,你甚至可以把编译过后的字节码发给远程,然后在B用Lua虚拟机执行。

所以对于一个完整的RPC框架底层往往是socket搭配序列化反序列化的工作。

问题到这里,一个RPC分析应该也结束了, 实际上要想把一个RPC做稳定了,还有几个问题。

首先,要想让一个RPC能够更高效,往往做到让A可以连续向B发送请求,这就要求在协议解析的时候区分两个包,在TCP分包的时候这里有个问题叫做半包和粘包。

另外B也无需在返回完函数1以后再返回函数2,这就要求在返回的时候,A能够区分开来,这就要求在协议里面加入session.

高效的写法不但在编解码和协议设计理念,还需要在编写socket server时候,尽可能降低阻塞调用,用异步来做,这有一大推开源方案,比如libev.

netty就是一个这样异步的RPC通信框架。

当然,在实际项目中,我们只是需要解决实际问题,完全没必要从头构建,你可以选一个通信协议比如protobuf/JSON/msgpack/thrift等等再找他相关的RPC库使用即可。

当然完全可以自己定制。

一个好的框架不只是解决最基本的问题,它更像是一个生态系统,比如我看到netty还有SSL的部分,DNS部分。

Have Fun.

你可能感兴趣的:(RPC与Netty是什么鬼)