原文:http://blog.sina.com.cn/s/blog_6203dcd60100y1vi.html
【第十一阶段 :命名位置服务】
在前面我们不止一次提到了命名位置服务(Naming & Location Service)。在不同的架构或者公司里面,这个名字往往不一样,比如,在java里面叫JNDI(Java Naming & Directory Interface),在有些地方可能会叫做资源位置系统(Resource Location System)。
总之,不管叫什么名字,我们要知道的就是为什么要有这样的系统?他能做哪些事情?他有哪些实现方式?等等。
在我们之前的章节中,我们的服务从一台单机扩展到十台左右的多机,到成百上千台机器。我们的服务从单一的一个服务扩展到成百上千的服务。这么多的机器、服务,如果不好好管理,我们就崩溃了。比如,我们的服务A要连接服务B,如果现在采用配置IP的方式,可能需要配置几十台机器的IP,如果其中某些机器出现了变更,那所有服务A连接服务B的IP都要改变。如果所有的服务都是这样,这将是多么痛苦的一件事情 Orz。
如果我们只是简单的将我们的服务看成是一个个的资源(Resource),这些资源可以是数据库,可以是cache,可以是我们自己写的服务。他们都有一个共同的特点,就是在某一个IP上,打开一个PORT,遵循一定的协议,提供服务。
我们先简单的来构建这样一个模型。我们这里先抽象一个接口,叫做Interface Resource。这个接口下面有多个实现,比如:DBResource、CacheResource、ImageResource等等。具体类图如下:
有了这样的一个层次结构以后,我们为了得到某一个实例,有多种方式,比如:
1、直接生成的方式:
Resource r = new ImageResource();
2、间接生成的方式:
A、比如我们在设计模式中经常使用到的工厂模式:
Resource r = ResourceFactory.get(“Image”);
B、IoC(Inversion of Control)方式:
Resource r = (Resource)Container.getInstance(“ImageResource”);
我们打一个不是很完全匹配的比方。我们如果直接在服务中采用IP配置的方式,就类似于直接生成实例一样,如果实例发生变化,或者要调整生成的对象,就需要修改调用者的代码。也就是说,如果其他服务的IP发生变化,我们调用者就需要修改配置,重启程序等等。而且对于如果有很多很多这样的服务,我们就崩溃了。
那么,我们觉得更好的一种方式呢,就是,如果有一个工厂,或者一个容器,来帮我们管理这一堆的服务IP、端口、协议等等,我们要用的时候,就只需要叫一声:“给我XXX服务的实例”,那是多么美妙的事情啊!
其实呢,我们的命名位置服务要做的就是这样的事情。他类似于一个Meta Server,记录所有服务的IP、port、protocol等基础信息,以及检查这些服务的健康状态,提供给调用者最基础的信息服务。同时,再结合调用时的负载均衡策略,就可以帮我们提供很好的资源管理方式。
这个服务,提供注册、注销、获取列表等接口。他的存在,就将直接关联的两个服务给很好的解耦了。我们看看对比:
在没有Naming Location Service的时候,我们的服务相互直接依赖,到最后,关联关系及其复杂,可能完全没有办法维护。
如果我们增加Naming Location Service以后,这个状态就可以得到极大的改善。
这个时候,我们所有的服务都在NLS上注册,同时向NLS获取其他服务的信息,所有的信息都汇聚到NLS上管理。
有了这个服务,就好类比成我们生成一个类的时候,采用间接的方式生成。
Service s = (Service) NamingService.getService(“Image”);
好,有了这样一个架构以后,我们可能会关注这个NLS如何来实现。
实现这个服务有简单的方式,也有复杂的方式。关键是要考虑以下几个方面:
1、如何找到这个NLS。NLS是所有服务的入口,他应该是有一个不变的地址来保证我们的服务。因此,我们可以使用我们之前提到过的Virtual Server的方案,通过一个(或多个)固定的域名或者IP来绑定这个服务。
2、可用性(Availability)和数据一致性(Consistency)。因为这个服务是一个最基础的服务,如果这个服务挂掉了,其他服务就没有办法来定位了。那么这个服务的稳定和可靠性就是及其重要的。解决方案有如下几种:
A、单机实现服务,本地增加备份。我们用单机来实现这样一个服务,这样可以保证绝对的数据一致性。同时,每次请求数据后,每个服务本地保留一份备份数据。当这个服务挂掉了,就使用最近的一次备份。这个方案对于大多数情况是足以应付的,而且具备简单粗暴有效的特点。
B、多机服务,数据同步。采用多机提供服务,信息更新时进行数据同步。这种方式的优点就是服务可以保证7*24小时服务,服务稳定性高。但是,问题就是维护成败会比上面一种方式高。
3、功能。实现服务名称到IP、Port、Protocol等信息的一个对应。如果要设计的更通用,比如可以注册任何信息,就只需要实现Key-Value的通用数据格式。其中,Value部分需要支持更多更丰富的结构,比如List、Set等。
有了这样的一个系统,我们就可以很方便的扩展我们的服务,并且能很好的规范我们服务的获取、访问接口。