RPC框架基本原理(一):服务注册

什么是RPC框架

RPC整个过程涉及四类对象:客户端、客户端代理、服务端和服务端代理。RPC要求客户端和服务端之间约定好调用接口和传输格式(如JSON,Xml等),客户端在调用该接口时,由客户端的代理对象负责对调用的参数(包括调用的函数名和参数等信息)进行格式转换,使之符合约定的传输格式,并经过网络传送至服务端。数据传输至服务端后,交由服务端代理对象进行格式解码,获取调用的接口和参数,最后调用服务端对象相应的方法获取结果并返回客户端。服务端的服务地址发布到ConfigServer,并推送给客户端,各类配置和规则信息经过Diamond发布订阅,服务的基本信息采集到Redis中。java

基本的调用关系图以下

这张图是解释RPC注册中心经典的图,图中的ConfigServer能够看作是一个内存数据库,它主要有两个功能:linux

  1. 服务提供者的地址和服务信息
  2. 向服务订阅者推送所订阅的服务提供者的地址信息

这里须要注意的是:真正发起远程调用是在消费者端和服务端生产者端和ConfigServer没有直接关系,实际的RPC是一个点对点的过程,经过TCP进行通讯。spring

架构图以下:

服务注册的流程

  • 服务与spring容器绑定,监听容器的fresh,close等事件,进行服务的注册与关闭,
  • 第一个服务注册时,首先校验该服务是否已经注册,若是hsf依赖的netty服务未启动,启动netty服务,这里涉及nio的轮询线程池(hsfwork),以及后端具体hsf处理线程池(bizProcess),这些线程池是同步的,能够采用listenerFuture进行异步解构。
  • 启动好服务后,注册服务的基本信息到configserver中(注册流程分为注册前,注册,注册后)。

关键的技术

Netty服务

常见I/O模型数据库

  • 阻塞I/O(blocking I/O)
  • 非阻塞I/O (nonblocking I/O)
  • I/O复用(select,poll,epoll) (I/O multiplexing)
  • 信号驱动I/O (signal driven I/O (SIGIO))
  • 异步I/O (asynchronous I/O (the POSIX aio_functions))

阻塞I/O(blocking I/O)

非阻塞I/O (nonblocking I/O)


用户进程实际上是须要不断的主动询问kernel数据好了没有。由于须要不断地轮询,这消耗了大量的CPU的资源。编程

I/O复用(select,poll,epoll)

select:

select本质上是经过设置或者检查存放fd标志位的数据结构来进行下一步处理。这样所带来的缺点是:windows

  • 单个进程可监视的fd数量被限制,即能监听端口的大小有限。
  • 通常来讲这个数目和系统内存关系很大,具体数目能够cat /proc/sys/fs/file-max察看。32位机默认是1024个。64位机默认是2048.

对socket进行扫描时是线性扫描,即采用轮询的方法,效率较低:
当套接字比较多的时候,每次select()都要经过遍历FD_SETSIZE个Socket来完成调度,无论哪一个Socket是活跃的,都遍历一遍。这会浪费不少CPU时间。若是能给套接字注册某个回调函数,当他们活跃时,自动完成相关操做,那就避免了轮询,这正是epoll与kqueue作的。后端

须要维护一个用来存放大量fd的数据结构,这样会使得用户空间和内核空间在传递该结构时复制开销大数组

poll:

poll本质上和select没有区别,它将用户传入的数组拷贝到内核空间,而后查询每一个fd对应的设备状态,若是设备就绪则在设备等待队列中加入一项并继续遍历,若是遍历完全部fd后没有发现就绪设备,则挂起当前进程,直到设备就绪或者主动超时,被唤醒后它又要再次遍历fd。这个过程经历了屡次无谓的遍历。服务器

它没有最大链接数的限制,缘由是它是基于链表来存储的,可是一样有一个缺点:网络

大量的fd的数组被总体复制于用户态和内核地址空间之间,而无论这样的复制是否是有意义。 2. poll还有一个特色是“水平触发”,若是报告了fd后,没有被处理,那么下次poll时会再次报告该fd。

epoll:

epoll支持水平触发和边缘触发,最大的特色在于边缘触发,它只告诉进程哪些fd刚刚变为就需态,而且只会通知一次。还有一个特色是,epoll使用“事件”的就绪通知方式,经过epoll_ctl注册fd,一旦该fd就绪,内核就会采用相似callback的回调机制来激活该fd,epoll_wait即可以收到通知。

Java从1.4开始提供了NIO工具包,支持用 I/O复用模型来进行网络编程。其模式图:

信号驱动I/O (signal driven I/O (SIGIO))

异步I/O (asynchronous I/O (the POSIX aio_functions))


这种模型与信号驱动模型的主要区别是:信号驱动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也就够了。

相关文章
相关标签/搜索