菜菜哥,我最近终于把Socket通讯调通了web
这么底层的东西你如今都会了,恭喜你离涨薪又进一步呀编程
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却难