架构设计:一种远程调用服务的设计构思(zookeeper的一种应用实践)

  在深刻学习zookeeper我想先给你们介绍一个和zookeeper相关的应用实例,我把这个实例命名为远程调用服务。经过对这种应用实例的描述,咱们会对zookeeper应用场景会有深刻的了解。前端

  远程调用是系统与系统之间的通讯机制,它的另外一种理解就是进程间的通讯。作分布式系统的开发,远程调用技术是其核心技术。远程调用技术能够将一组计算机系统造成一个网络系统,对外提供总体服务,那么这一群的计算机系统就构成了一个更大型,性能更高的计算机系统。java

  我在前面的博客里介绍了一种分布式网站的架构设计,其中就有一个使用netty技术编写的组件做为前端系统和服务端系统通讯的媒介。在一个大型的互联网公司里会有不少这样的网站系统,若是每个网站都像我博客里所论述的进行开发,那么对于系统通讯维护和管理,以及每一个系统网络资源的分配管理就会形成必定的问题,对于这样的问题,我举个例子可能你们会更明白些,好比一个互联网公司有数个对外提供服务的网站,有的网站访问量很大,有的相对较小,可是公司的宽带资源是有限的,那么咱们就但愿动态的管理和分配这些资源,若是咱们网站的通讯功能和网站都是紧耦合的,那么调配这些资源的工做就会比较复杂和繁琐,也很容易出问题。这样的问题还会还有不少,我这里不作细致分析了。作软件开发时候,有个原则,若是某个功能是能够通用的,该功能很须要统一管理时候,咱们就应该把这个功能抽取成一个独立的系统或组件,而且这个系统或组件赋予一些加强级的功能特性,这样一定对整个系统的健壮性、可用性以及效率上有所提高。linux

  而我在分布式网站里所描述的通讯技术,就是远程调用技术的一种,远程调用技术就是客户端和服务端的通讯技术,它能够当作cs架构技术的一种,在java里有不少优秀的框架实现远程调用,例如java自带的RMI,spring自带的Httpinvoker,webservice技术等等。可是现有的这些技术知足不了互联网公司的远程调用需求,今天我将讲述一套我本身构思的一套远程调用技术,这个是借鉴了一些咱们公司的相似软件的作法。web

  该框架主要是针对java的,其余语言目前不能支持。首先我要总结远程调用技术要包括那些技术,它们分别是:spring

  1. 通讯技术:远程调用就是经过网络技术将不一样系统构成一个总体,所以通讯技术是其重点,通讯技术我这里选择的是netty技术,Netty提供异步的、事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器和客户端程序。Netty会让咱们开发通讯程序变得简单,高效,其效率也是很是好的,同时它还支持多种不一样的网络协议。
  2. 序列化和反序列化技术:java的序列化技术是指将对象转换为byte数据,这些数据能够被还原为java对象,这种还原的过程就是反序列化了,该机制能够自动处理不一样操做系统之间的差别,例如window下序列化的对象,能够在linux上进行从新构建。Java的jdk里自带了一个序列化和反序列化机制,熟悉hadoop的人知道hadoop设计了一套序列化和反序列化机制,为何hadoop做者不选择使用java自带的序列化机制,这是由于java序列化机制很是复杂,复杂带来效率低下,java的序列化机制还有一个重要的缺点就是它序列化的二进制数据会很是大,由于java序列化时候会附带太多该对象的相关信息,过大的数据量就会影响网络传输的效率,所以hadoop本身设计了一套序列化和反序列化机制,hadoop不一样节点之间的通讯也是一种远程调用机制,所以咱们发现好的序列化和反序列化技术对于远程调用是至关重要的。咱们公司的远程调用框架序列化技术有两种一种就是java自带的序列化和反序列化机制,一种是hessian技术,它是一种更加高效的序列化和反序列化技术。
  3. 压缩技术:作网络编程,最稀缺的资源就是宽带资源,若是传输数据过大,那么对数据的压缩就会显得十分重要,这里我推荐一个压缩技术snappy,它是一种高效的压缩和解压缩包,google公司内部普遍使用的一种压缩技术。
  4. 高并发的技术:远程调用技术必定会是多线程,只有这样才能知足多个并发的处理请求,java在1.5的版本里提供了一个Executor框架,它在线程开发里引入了任务的概念,使得多线程的程序开发会更加合理和可控,关于executor的技术你们能够看看一本经典的书籍《java并发编程实践》。想让线程更加有效率,池技术也是并不可少的,apache的common-pool是一个很是好的池技术,咱们能够将线程都预先建立好,而后放入到common-pool池里进行管理。
  5. 非侵入式:这个也能够叫作松耦合,对于java的web开发,最好的解耦方式就是使用spring技术,当咱们系统里把远程调用框架引入后,配置好相关的参数,咱们能够把用于远程调用的方法定义在spring的配置文件里,那么在程序里调用的时候,利用spring直接获取这个bean,那么对于远程调用的开发就和咱们在action里调用server的方法没啥区别了。下面是一段实例代码:
<!-- 服务提供者配置 -->
<bean id="serverProvider" class="cn.com.sharpxiajun.RmifSpringProviderBean">
    <property name="interface" value="cn.com.ITest"></property><!-- 远程调用的接口 -->
    <property name="target" ref="clsTest"></property><!-- clsTest实现ITest的实现类,clsTest这里是一个bean的id值 -->
</bean>

<!-- 服务调用者配置 -->
<bean id="clientConsumer" class="cn.com.sharpxiajun.RmifSpringConsumerBean">
    <property name="interface" value="cn.com.clsTest"></property><!-- value就是Provider定义的target的接口实现类 -->
    <property name="seriaType" value="hessian"></property><!--序列化方式  -->
    <property name="compress" value="true"></property><!-- 压缩标记 -->
</bean>

 

  6.负载均衡:分布式系统都离不开负载均衡,好的负载均衡能够充分利用好不一样服务器的计算资源,提供系统的并发量和运算能力,对于网站而言(咱们公司如今网站服务器不是太多)少于10台服务器可使用两种策略:一种是简单轮询,好比有6台服务端,咱们会把第一个请求给第一台服务器,第二个请求给第二台,依次类推,等6台循环完毕,又从第一台开始;第二种是随机方式,即便用random函数,固然更多的服务器我就不知道有什么轮询机制比较好,但愿有知道的童鞋能够给我推荐下。apache

  我这里设计的远程调用框架,除了以上的功能外,我但愿它还能有心跳管理机制,超时管理机制,服务分级管理,就是根据服务的重要性或者系统的繁忙度能够调节网络资源。编程

  哈哈,讲了这么久估计有童鞋可能有点烦了,不是说应用zookeeper的实例吗?怎么还没见到zookeeper的影子。别着急,zookeeper立刻就要上场了。浏览器

  仍是以我前面博客里写分布式网站讲起,服务端系统咱们能够当作服务提供者,前端系统当作服务调用者,提供者能够类比商户,调用者能够类比客户,商户和客户能够直接进行交易,这种直接交易方式很是原始甚至还会有风险,现代社会商户和客户直接的交易十分高效,高效的缘由是由于有一个规范的大市场,商户和客户的交易在市场里进行的,这样交易会变得更加安全和高效,我设计的分布式框架最大的特色就是提供了一个相似市场的角色,它来管理服务提供者和服务调用者,我把这个功能模块称为远程调用管理组件。安全

  远程调用管理组件是本框架的核心,它的主要做用是接收服务端提供者的注册的通知,该通知通常是接口以及该接口的实现类还有服务器的ip地址,管理组件会将这些通知记录下来,而且根据配置对这些服务程序进行分组和标记,注册好的信息管理组件会将这些信息推送到服务调用者。远程调用管理组件还包含心跳机制,这个心跳机制是针对服务提供者,经过心跳机制检测服务提供者的健康情况,管理组件不会检测服务调用者的健康状态,由于这个不必,由于本框架的使用仍是调用者直接去请求提供者,逻辑上是不必关心调用者的状态,这和bs架构里浏览器同样,咱们不会去关心浏览器用户是否是存在。服务提供者、服务调用者和远程调用管理组件的关系以下图所示:服务器

  远程调用框架运行的过程是:当服务提供者启动时候,它会将本身的ip地址和注册的方法传输到远程调用管理组件,管理组件接收到注册信息会将这些信息存储下来,存储技术就是使用zookeeper,存储成功后,管理组件会将成功通知传回给服务提供者,同时管理组件还会经过心跳检测服务提供者是否健康;当服务调用者启动时候,它会向管理组件请求服务提供者信息,管理组件接收到请求后会将相关信息推送给服务调用者。在实际系统运行时候,服务调用者直接和服务提供者进行通讯交互了,通讯方式是netty,若是调用者和提供者有相关变化,都会先通知服务管理组件,服务管理组件会将相关变动信息推送给相应的系统。

 

  远程调用管理组件主要是经过zookeeper实现,zookeeper拥有一个层次的命名空间,它的模型是一个树状结构,树状结构是一个强大的数据类型,它几乎能存储全部不一样的数据类型,咱们经过zookeeper将这些信息保存起来,便于咱们管理整个远程调用框架,同时zookeeper仍是高可靠的,这个我在前面zookeeper文章里讲到了,这样就保证了整个远程调用框架的稳定性,实际应用中咱们会将组件编译成一个jar包,不一样的项目直接引用这个jar包,这样管理组件服务端和服务的提供者和调用者就联系起来。至于提供者和调用者的通讯机制是直接进行,由于咱们将通讯程序集成在jar包里,只不过相应的管理机制抽取到外部服务端进行统一管理。

 

  这就是我设计的远程调用框架,惋惜的是,这个构思我尚未真正实现过,今天拿出来是想体现zookeeper的实际应用,为我后面讲解zookeeper作铺垫,至因而否可行,看之后有没有机会开发个相似的系统,到时估计还有不少意想不到的问题要解决。

 

    (远程调用服务的设计我参考了技术友人马德鑫的设计,他曾是淘宝的技术架构师)

相关文章
相关标签/搜索