程序员修神之路--设计一套RPC框架并非易事
菜菜哥,我最近终于把Socket通信调通了

这么底层的东西你现在都会了,恭喜你离涨薪又进一步呀

http协议不也是利用的Socket吗

可以这么说,http协议是基于TCP协议的,底层的数据传输可以说是利用的socket

既然Socket通信会了,那一个rpc的框架不就很容易就能实现了吗?

一个比较完备的rpc框架可能并非像你所想那样简单,要不然人人都可以出RPC框架了

有那么难吗?我觉得没有那么难呀

如果你能解决掉这些问题,我觉得你真的是大牛了

RPC是远程过程调用(Remote Procedure Call)的缩写形式,是在多任务操作系统或联网的计算机之间运行的程序和进程所用的通信技术
撸码的人都应该知道,现代编程中最常用的系统之间通信方式是:http调用和rpc调用。对于同一个网络或者说是互通的网络环境中,rpc调用方式是系统间通信交互最常用的方式,比基于http协议的通信方式性能高出数倍甚至数个量级。我司的平台rpc通信,每秒在几万甚至更高,每次调用的通信时间在一定程度上几乎可以忽略不计,再加上我们首席架构师深厚的系统设计功力,采用进程内缓存等等优化措施,一次rpc调用的整体平均时间也在一毫秒之下。这是http协议无法达到的速度,如果你在浏览器的F12的窗口观察过,一个http协议调用如果整体花费的时间在5毫秒甚至10毫秒,那么其实就可以认为这个http请求响应时间是很短的了。
所以绝大部分公司内部的系统之间通信都会采用rpc调用这种方式。这里不要抬杠,如果你的公司内部系统通信采用的是基于http协议的,那说明你们的系统很有可能没有性能的要求。
RPC调用虽然简化了撸码的难度,但是想要实现一套rpc框架,何止容易,一套优秀的rpc框架,更是难如登天。
多数rpc框架的服务端以service的方式来运行,为了避免和其他进程发生监听端口的冲突,一般会随机选择一个端口来进行监听。虽然这看上去很好,但是却给client端带来了麻烦,如果服务端监听固定端口,client连接服务端的时候,最少可以在代码中固定写死服务端的IP和端口。但是现在服务端监听的端口是随机的,而且更可怕的是服务器有可能会更换或者切换IP,那client怎么才能正确的去和服务端建立连接呢?
服务端之所以会采用这种随机方式来监听端口,其中很大一个原因是为了以后扩容。client如何正确的去连接服务器则采用了一个集中式的方案,服务端引入了一个服务注册中心的概念,有的系统可能会以别的名称来体现,但是作用是类似的。这个注册中心存储着所有的服务端信息,其中包括每个服务端的IP和端口,有的甚至还有版本信息,每个服务端进程启动的时候,都是采用主动连接注册中心,主动注册的方式。client端在发起连接服务的时候,首先去注册中心查找已经注册的服务端信息,然后进行连接。这样rpc调用在某种程度上在连接步骤就实现了“自动化”。
当client和服务端建立tcp连接之后(有的rpc框架会采用udp协议),下一个问题就是client和服务端怎么相认的问题了。举个栗子:客户端想要实现一个获取用户姓名的方法,方法名怎么定义才能让服务端正确识别出来呢?是传一个字符串“GetName”,还是传一个整数1来代表呢?服务端的返回结果,如果发生异常改如何返回呢?
当我们在本地调用一个函数,语法,语义,以及语法语义的分析,编译器已经帮我们做好了这些,但是rpc是远程过程调用,虽然表面上和本地类似,但是已经出现了跨网络的情况,语法语义等等这些分析需要client和服务端协商一致。
其实现代几乎大部分rpc通信都遵循一个标准:
当client发起一个远程调用的时候,它首先会先调用本地的Stub,它负责将调用的接口,函数以及参数按照约定好的协议格式进行编码,然后通过本地的Runtime进行传输,最后通过网卡将数据包发送到指定的服务器。
服务器Runtime接收到请求之后,会首先调用本地的Stub按照约定好的协议格式进行解码,最后调用服务端具体的函数。函数执行完毕,把结果利用本地的Stub编码之后通过runtime发送给客户端。客户端Runtime接收到消息利用本地Stub进行解码,然后进行其他处理。
由此可见,现代的rpc框架其实是把协议的封装和数据的发送分别抽象成了单独的层。Stub负责协议部分,Runtime处理数据发送以及网络相关部分。
数据通过网络传输过程中,每个数据包的完整性如何来识别,如果是一个简单int型数据很简单,但是如果是一个类或者一个数组,甚至是其他变长的类型,rpc的通信协议如何约束这些,如果能正确识别出来数据是协议部分最难处理的部分。更何况还有大头小头编码的问题。
凡是基于网络传输的形式,任何通信都是不可靠的,网络本质是不可靠的。包括网络抖动,错误等造成的丢包,粘包现象,如何正确的处理也是一个rpc通信中很重要的部分。一个rpc请求失败,是直接丢弃还是重试,这些策略都需要去规定。
1.一个rpc调用如果采用同步的方式,性能会大大打折扣,如何实现rpc的异步调用,这是一个rpc是否优秀的重要指标。
2.无论rpc的网络传输多么优秀,都会有性能损耗,能否把某些结果数据设置缓存?
3.无论是client还是服务端,处理请求的线程能否重用(线程池)?
4.能否支持多语言呢?
socket虽易,RPC却难
程序员修神之路--设计一套RPC框架并非易事的更多相关文章
- 程序员修神之路--用NOSql给高并发系统加速(送书)
随着互联网大潮的到来,越来越多网站,应用系统需要海量数据的支撑,高并发.低延迟.高可用.高扩展等要求在传统的关系型数据库中已经得不到满足,或者说关系型数据库应对这些需求已经显得力不从心了.关系型数据库 ...
- 程序员修神之路--kubernetes是微服务发展的必然产物
菜菜哥,我昨天又请假出去面试了 战况如何呀? 多数面试题回答的还行,但是最后让我介绍微服务和kubernetes的时候,挂了 话说微服务和kubernetes内容确实挺多的 那你给我大体介绍一下呗 可 ...
- 程序员修神之路--redis做分布式锁可能不那么简单
菜菜哥,复联四上映了,要不要一起去看看? 又想骗我电影票,对不对? 呵呵,想去看了叫我呀 看来你工作不饱和呀 哪有,这两天我刚基于redis写了一个分布式锁,很简单 不管你基于什么做分布式锁,你觉得很 ...
- 程序员修神之路--🤠分布式高并发下Actor模型如此优秀🤠
写在开始 一般来说有两种策略用来在并发线程中进行通信:共享数据和消息传递.使用共享数据方式的并发编程面临的最大的一个问题就是数据条件竞争.处理各种锁的问题是让人十分头痛的一件事. 传统多数流行的语言并 ...
- 程序员修神之路--为什么有了SOA,我们还用微服务?
菜菜哥,我最近需要做一个项目,老大让我用微服务的方式来做 那挺好呀,微服务现在的确很流行 我以前在别的公司都是以SOA的方式,SOA也是面向服务的方式呀 的确,微服务和SOA有相同之处 面向服务的架构 ...
- 程序员修神之路--打通Docker镜像发布容器运行流程
菜菜哥,我看了一下docker相关的内容,但是还是有点迷糊 还有哪不明白呢? 如果我想用docker实现所谓的云原生,我的项目该怎么发布呢? 这还是要详细介绍一下docker了 Docker 是一个开 ...
- 程序员修仙之路--优雅快速的统计千万级别uv(留言送书)
菜菜,咱们网站现在有多少PV和UV了? Y总,咱们没有统计pv和uv的系统,预估大约有一千万uv吧 写一个统计uv和pv的系统吧 网上有现成的,直接接入一个不行吗? 别人的不太放心,毕竟自己写的,自己 ...
- 程序员修仙之路- CXO让我做一个计算器!!
菜菜呀,个税最近改革了,我得重新计算你的工资呀,我需要个计算器,你开发一个吧 CEO,CTO,CFO于一身的CXO X总,咱不会买一个吗? 菜菜 那不得花钱吗,一块钱也是钱呀··这个计算器支持加减乘除 ...
- 程序员修仙之路--优雅快速的统计千万级别uv
菜菜,咱们网站现在有多少PV和UV了? Y总,咱们没有统计pv和uv的系统,预估大约有一千万uv吧 写一个统计uv和pv的系统吧 网上有现成的,直接接入一个不行吗? 别人的不太放心,毕竟自己写的,自己 ...
随机推荐
- cf--703--A-- Mishka and Game
题目链接:http://codeforces.com/problemset/problem/703/A Mishka is a little polar bear. As known, little ...
- SpringCloud Feign 之 Fallback初体验
SpringCloud Feign 之 Fallback初体验 在微服务框架SpringCloud中,Feign是其中非常重要且常用的组件.Feign是声明式,模板化的HTTP客户端,可以帮助我们更方 ...
- Day002_LInux基础_常用命令_001
1.创建用户useradd -m -g 加参数-m 会自动创建家目录 -g 指定group 加入什么群组 passwd 设置用户的密码 su 和su - 的区别 su - 切换用户switch use ...
- myslq5.7安装以及root密码找回
一.mysql安装 创建用户和用户组: groupadd mysqluseradd -g mysql mysql -s /sbin/nologin 解压压缩文件并创建软链接 tar -xvf mysq ...
- HBase工作中的一些优化方法
1.表的设计 Pre-creating Regions(预分区) 默认情况下,在创建Hbase表的时候会自动创建一个region分区,当导入数据的时候,所有的Hbase客户端都向这一个region写数 ...
- Java 创建/识别条形码、二维码
条形码(Barcode)是将宽度不等的多个黑条和空白,按照一定的编码规则排列,用以表达一组信息的图形标识符.常用于标示物品的生产国.制造厂家.商品名称.生产日期.图书分类号.邮件起止地点.类别.日期等 ...
- Redis集群增加节点和删除节点
本文主要是承接上一篇文章Redis集群的离线安装成功以后,我们如何进行给集群增加新的主从节点(集群扩容)以及如何从集群中删除节点(集群缩容),也就是集群的伸缩,集群伸缩的原理是控制虚拟槽和数据在节点之 ...
- kafka入门配置
问题导读: 1.zookeeper在kafka的作用是什么? 2.kafka中几乎不允许对消息进行“随机读写”的原因是什么? 3.kafka集群consumer和producer状态信息是如何保存的? ...
- 19 (OC)* RunLoop
面试题 1:讲讲RunLoop,项目中有用到吗? 2:RunLoop内部实现逻辑? 3:Runloop和线程的关系? 4:timer 与 Runloop 的关系? 5:程序中添加每3秒响应一次的NST ...
- [Code] 大蛇之数据工程
作为“所谓码农”的首篇,本章内容理应涵盖基本编程技法. Python这个东西.简洁,作为载体,是个不错的选择呦. 链接资源: Python文档:https://docs.python.org/3/ 教 ...