RPC整个过程涉及四类对象:客户端、客户端代理、服务端和服务端代理。RPC要求客户端和服务端之间约定好调用接口和传输格式(如JSON,Xml等),客户端在调用该接口时,由客户端的代理对象负责对调用的参数(包括调用的函数名和参数等信息)进行格式转换,使之符合约定的传输格式,并经过网络传送至服务端。数据传输至服务端后,交由服务端代理对象进行格式解码,获取调用的接口和参数,最后调用服务端对象相应的方法获取结果并返回客户端。服务端的服务地址发布到ConfigServer,并推送给客户端,各类配置和规则信息经过Diamond发布订阅,服务的基本信息采集到Redis中。java
这张图是解释RPC注册中心经典的图,图中的ConfigServer能够看作是一个内存数据库,它主要有两个功能:linux
这里须要注意的是:真正发起远程调用是在消费者端和服务端生产者端和ConfigServer没有直接关系,实际的RPC是一个点对点的过程,经过TCP进行通讯。spring
常见I/O模型数据库
用户进程实际上是须要不断的主动询问kernel数据好了没有。由于须要不断地轮询,这消耗了大量的CPU的资源。编程
select本质上是经过设置或者检查存放fd标志位的数据结构来进行下一步处理。这样所带来的缺点是:windows
对socket进行扫描时是线性扫描,即采用轮询的方法,效率较低:
当套接字比较多的时候,每次select()都要经过遍历FD_SETSIZE个Socket来完成调度,无论哪一个Socket是活跃的,都遍历一遍。这会浪费不少CPU时间。若是能给套接字注册某个回调函数,当他们活跃时,自动完成相关操做,那就避免了轮询,这正是epoll与kqueue作的。后端
须要维护一个用来存放大量fd的数据结构,这样会使得用户空间和内核空间在传递该结构时复制开销大数组
poll本质上和select没有区别,它将用户传入的数组拷贝到内核空间,而后查询每一个fd对应的设备状态,若是设备就绪则在设备等待队列中加入一项并继续遍历,若是遍历完全部fd后没有发现就绪设备,则挂起当前进程,直到设备就绪或者主动超时,被唤醒后它又要再次遍历fd。这个过程经历了屡次无谓的遍历。服务器
它没有最大链接数的限制,缘由是它是基于链表来存储的,可是一样有一个缺点:网络
大量的fd的数组被总体复制于用户态和内核地址空间之间,而无论这样的复制是否是有意义。 2. poll还有一个特色是“水平触发”,若是报告了fd后,没有被处理,那么下次poll时会再次报告该fd。
epoll支持水平触发和边缘触发,最大的特色在于边缘触发,它只告诉进程哪些fd刚刚变为就需态,而且只会通知一次。还有一个特色是,epoll使用“事件”的就绪通知方式,经过epoll_ctl注册fd,一旦该fd就绪,内核就会采用相似callback的回调机制来激活该fd,epoll_wait即可以收到通知。
Java从1.4开始提供了NIO工具包,支持用 I/O复用模型来进行网络编程。其模式图:
这种模型与信号驱动模型的主要区别是:信号驱动I/O由内核通知咱们什么时候能够开始一个I/O操做,而异步I/O模型由内核通知咱们I/O操做什么时候已经完成.
JDK1.7 升级了NIO 类库,升级后的NIO类库被称为NIO2.0。java也正是提供了异步文件I/O操做,同时提供了与UNIX网络编程事件驱动I/O对应的AIO。
Netty4的beta3加了AIO了,可是到beta9又被去了,做者的意思是测试下来AIO性能不如NIO,因此不必用,在Linux上NIO的实现自己就是epoll,使用jdk的AIO没有意义,在windows上jdk的AIO实现是IOCP,这种状况下使用AIO是比poll的性能高的,可是netty的服务器通常是在linux上,因此抛弃windows没啥大不了,windows最多作个客户端,用nio也就够了。