SLP 系列第 1 部分:基本介绍和对比分析

来源:互联网 发布:大数据是如何产生的 编辑:程序博客网 时间:2024/06/11 05:04

SLP(Service Location Protocol, 服务位置协议)是一个基于 internet 标准的 RFC 规范,主要用于在网络上服务的动态发现。本文简要介绍了 SLP 的基本内容,把它和现在其它主要的类似协议(uddi, ssdp)进行比较,分析其优缺点和应用场景。然后,本文通过一个开源包 OpenSLP 展示该协议在编程时的用法。

牛 刚 (minos_sjtu@hotmail.com), IBM CSTL实习生, 上海交通大学

杜 晓东 (duxiaod@cn.ibm.com), IBM CSTL软件工程师 , IBM

2008 年 9 月 08 日

  • +内容

SLP 基本介绍

SLP 是一个 IETF 标准协议,用于在互联网内动态的服务发现。该协议支持通过服务的类型,属性来在网络中查寻服务。同时,服务的提供者可以在网络中广播自己或者向集中式服务目录注册自己所提供的服务。

SLP 的结构与运作方式

在 SLP 中有三种角色:UA(User Agent, 用户代理 ),SA(Service Agent, 服务代理 ),DA(Directory Agent, 目录代理 )。UA 是 SLP 中的客户端,它可以根据服务的类型和属性,在网络中查找符合条件的服务。SA 是 SLP 中的服务器端,它提供了它所代理的服务的基本信息,并与 UA 与 DA 交互。DA 是一个可选的角色,它提供了一种集中式目录服务,SA 可以在上面注册服务,并由 UA 来查询,这样 UA 与 SA 可以不必直接通信,在大型网络中可以有效降低网络流量。SLP 结构如图 1 所示。

图 1:SLP 架构示意图
图 1:SLP 架构示意图

DA 的存在与否可以把 SLP 的运作分为两种模式。当网络中没有 DA 时,UA 直接向整个网络发送多播或广播的查询请求,网络中的 SA 收到请求之后,根据查询条件判断自己是否符合要求,如果不符合则简单的不予回应,否则单播 UA 说明自己符合该查询要求,并把服务的访问地址告诉 UA,这样 UA 端的应用系统就可以使用该服务了。该模式运作如图 2 所示。

图 2 无 DA 时 SLP 运作模式示意图
图 2 无 DA 时 SLP 运作模式示意图

当 DA 存在时,SA 单播 DA,在上面注册自己的信息,注册内容包括服务的地址,类型和属性。当注册成功后,DA 回复一条信息确认。如果服务发生变化,SA 需要通知 DA 修改自己的注册信息,或者取消注册。而当 UA 查询服务时,它不用再广播整个网络,而是直接单播 DA,把查询要求告诉 DA,DA 根据要求对在自身注册的 SA 进行匹配,并把匹配的结果回复给 UA,如果匹配成功,DA 把访问的服务地址也告知 UA,使客户端应用系统可以使用服务。当 DA 存在时,SLP 运作模式如图 3 所示。

图 3:有 DA 时 SLP 运作模式示意图
图 3:有 DA 时 SLP 运作模式示意图

SLP 的应用

正是由于 SLP 拥有强大的动态服务发现功能,它在网络中有着广泛的应用。它可以自动对网络中计算机进行配置。比如给计算机配置打印机,某台计算机需要彩色打印机,运行于该计算机之上的 UA 只需查询类型是打印机且属性中包含彩色的服务即可,它就能得到网络中可用的彩色打印机并自动配置,整个过程不需要人工干预,可以给网络管理带来极大的便利性。

除了查询服务,我们利用 SLP 还可以得到服务的各种属性,通过这点可以对 SLP 的应用场景进一步扩展,比如一台服务器可以作为一个服务,它当前的运行状态和各种参数可以作为服务的属性。可以在客户端得到这些数据,对服务器的状态进行监控,甚至可以通过负载等属性对整个服务器群进行负载平衡的管理。对于 SLP 的进一步详细介绍,可以查阅文后参考资料的相关内容。

SLP 与其它类似协议比较与优劣分析

在服务的发现与注册领域,并不只有 SLP 一项技术,SLP 也不是全能的,在某些场合下,它的发挥将受到限制,使用它未必是最佳的解决方案。下面,本文把它与类似功能的两大协议 UDDI 和 SSDP 做一对比,分析其优势劣势与合适的应用场景,并给出作者自己的使用建议。

SLP vs UDDI

谈到服务的发现与注册,最鼎鼎大名的可能就是 web service 的 UDDI(Universal Description, Discovery, and Integration, 统一描述,发现与集成 ) 了。在当今 SOA 的浪潮中,web service 凭借其松耦合,异构通信,自包含语义等优势成为业界最主要的标准。而 UDDI 则提供了一个平台供服务提供者发布自己的服务,以及服务消费者来查询自己需要的服务。因此,从用途上来说,UDDI 与 SLP 基本上是一致的。

两者最大的区别还是在适用范围上。UDDI 面对的是全球整个 internet,而 SLP 基本上都是在局域网内部使用的。造成这个区别的原因很大程度上是因为 UDDI 是基于 xml 技术,而 xml 这门语言的强大之处在于它是语义自包含的,因此在对服务的语义描述上有着先天的优势。另外,UDDI 是作为 web service 三角架构(服务提供者,服务调用者,服务目录,对应于 SLP 中的 SA,UA,DA)协议的一部分,和 wsdl 及 soap 协议协同工作的。SLP 则不得不孤军奋战,它既不能像 wsdl 那样去描述一个服务,又不能像 soap 那样去定义服务的调用,所有这些都是定义在 SLP 之外,又必须在使用前三方都协商好的。因此,这个大大限制了 SLP 的适用范围,把其用武之地框定于局域网之内。毕竟在广域网中,语义协商的代价往往是巨大的,其管理也是非常困难的。

即便在局域网内,SLP 也并非没有挑战。SLP 的一大特点是异构平台的通信,(在同构平台中,我们经常能发现一些更适用的平台专属策略),但遗憾的是,这恰恰又是 web service 的长处。不过在语义问题并不占主要因素的局域网环境中,其巨大而笨重的架构劣势就显露了出来。UDDI 分为白页,黄页和绿页,其包含的信息很丰富,但要维护这些信息的工作量也很大。不少服务提供者经常懒得去维护那些注册信息,也使得 UDDI 上渐渐充斥着越来越多的垃圾信息,最终大家都不愿去用它而废弃。这个缺点甚至在全球互联网的环境中都难以被接受,比如微软,IBM 等大型企业 5 年前建立的 UDDI 注册中心,现在已渐渐无人问津。另外,xml 解析的开销在现阶段也是比较大的,在网络传输延时可以忽略的局域网中,处理 xml 的时间开销会成为效率瓶颈。因此,在局域网中,用户往往偏向更轻量级的解决方案,SLP 轻盈的身姿将导致用户的青睐。使用 SLP 你不用担心建立和维护庞大的注册中心(即使使用 DA,其有效注册信息时间最长也只有 18.2 个小时,如果没有得到 SA 的通知,DA 就会把注册信息丢弃),不必只为了传输少量数据就用大量的 xml 去包装它们,同时又有着跨平台的优点,是更为理想的选择。

SLP vs SSDP

如果说 SLP 与 UDDI 由于侧重应用范围不同而没有直接竞争的话,来自于 SSDP 的竞争威胁是更为直接的。SSDP(Simple Service Discovery Protocol, 简单服务发现协议 ) 同样也是一个在局域网内服务动态发现的协议,连名字都和 SLP 接近。正如其名,SSDP 非常简单,它只定义了服务调用者和服务提供者两个角色,没有集中目录服务,类似于没有 DA 的 SLP。而且,SSDP 中的服务只有 4 项数据,唯一服务名,服务类型,生存周期和服务地址,并没有详细的服务属性。也就是说,客户端只能通过服务类型去查找服务,这无疑使得查找的灵活性和便利性大打折扣。

表面上来看,SLP 似乎完胜 SSDP,但是,SSDP 同样不是孤军奋战,它是 UPnP(Universal Plug and Play, 通用即插即用 ) 协议框架中的一部分。在框架中与 SSDP 协同工作的还有用于服务描述的 UPnP 模版(可以类比 wsdl)和用于服务调用的 soap 协议(没错,还是 soap)。另外,UPnP 中还有一个通用事件通知结构 GENA,客户端可以在服务端进行注册,当服务端的状态发生变化时,它会主动通知所有在自己这里注册的客户端变化情况,从而使客户端可以始终保持服务端的最新信息,从根本上消除了过时信息给客户端带来的不便。这点无论是 SLP 还是 UDDI 都不具备的。

SLP 再一次因为面对整个协议框架而受到挑战,不过 SSDP 自身仍然有值得注意的闪光点,再看 SSDP 的四项数据,其中三项在 SLP 中都有,不过唯一服务名确是 SLP 中不具备的。这里有一个可以讨论的话题,我们是不是需要唯一辨识某一个服务,也许在 SLP 适用的大部分场合,我们不需要这么一个辨识符,但是在有些场合下,有这么一个辨识符可以使应用更加方便。还有一点,SSDP 是基于 HTTP 传输的,它可以利用很多现成的底层架构的功能,而 HTTP 在网络上的地位和通用性是无可争议的。SLP 完全是自己定义的传输格式,开发的代价会比较大些。最后,UPnP 的背后有微软的大力推动,而 SLP 似乎缺少这方面的支持,毕竟,对于标准和协议的竞争,其背后的大型企业的支持作用是巨大的。

对于这两者的使用建议是,如果你的应用只是侧重于服务的发现,那就用 SLP 吧,毕竟它比 SSDP 强大的多。但如果你想要建立一个完整的服务发布和调用体系,UPnP 也许更为合适。SSDP 虽然现阶段还比较简单,但是有着 UPnP 框架的支持和微软的推动,其发展潜力不容小觑。

SLP 应用实例与开源包 OpenSLP 介绍

下面我们来举一个具体的例子说明 SLP 的使用方法,假如我们要编写一个程序,其中需要使用某个打印机进行打印操作。但是我们并不知道打印机的具体配置情况,比如服务地址,这时我们就能使用 SLP 来自动发现这些打印机的信息,把它们的地址返回给应用程序。我们还可以指定符合条件的打印机,比如在 4 楼的打印机来为我们服务。

当我们想使用 SLP 时,不必自己开发,已有不少开源项目实现了 SLP 协议,而 OpenSLP 可能是其中最著名的一个。OpenSLP 有 C 和 Java 两个版本,C 版本相对比较成熟,已经有不少文章对其进行了介绍,我这里就不多说了。下面我简单介绍一下其 Java 版本的使用方法。

在 SLP 中,UA,SA,DA 的实现是相互独立的,它们都遵照规范进行通信,因此我们并不要求三者使用同一种实现,也不用在同种语言,同种平台实现。遗憾的是 OpenSLP 的 Java 版本中目前还没有 DA 的实现,SA 中也不支持向 DA 修改已注册属性方面的功能,但 UA 还是做的比较全的。如果你的应用系统是 Java 的,你完全可以只使用 OpenSLP 的 Java 版本的 UA 端程序包,它完全不妨碍你与网络中其它版本(比如 OpenSLP 的 C 版本)实现的 SA,DA 通信。OpenSLP 的 C 版本实现示例可以参考我列出的《使用 Service Location Protocol 自动化客户机的管理》一文,也可以访问 OpenSLP 的官方网站 http://www.openslp.org 寻求帮助。

SLP 不但由 RFC2608 定义了其内容,RFC2614 还对其实现中的数据结构,调用接口等做了规范定义。OpenSLP 的 Java 也是完全符合该 RFC 的,代码中一些属性语义,默认值和常量定义都可以参照该规范了解。

在使用 SLP 时,首先要对其配置属性初始化。有三种方法初始化配置属性,一是使用配置文件:

File f = new File(“prop.txt”);ServiceLocationManager.init(f);

或者使用 JavaProperties 类来初始化:

Properties p = new Properties();p.put("net.slp.traceDATraffic", "true");p.put("net.slp.traceMsg", "true");ServiceLocationManager.init(p);

也可以使用默认的配置:

ServiceLocationManager.init();

如果某项属性在前两种方法中没有被定义,则按照默认值来配置。

第二步我们需要得到 Locator,通过它才能进行服务发现。其中 getLocator 的参数是一个 Java 的 Locale 对象,定义了我们希望得到的服务的语言。

Locator loc = ServiceLocationManager.getLocator(java.util.Locale.US);

有了 Locator 之后我们就可以进行查询了,查询服务要提供以下三个参数:服务类型,范围和查询条件。范围是指我们为了便于管理,人为的把网络分为几个不同的域,可以在几个不同的域中查找服务。下面我们要在默认的域中查找在 4 楼的打印机。注意这里 location = 4F 表示 4 楼,service:printer 表示打印机,这些语义要事先在 SLP 协议之外约定。

Vector scopes = new Vector();scopes.add("default");String selector = "(location = 4F)";ServiceType type = new ServiceType("service:printer");ServiceLocationEnumeration enumVar = loc.findServices(type, scopes, selector);

在查询之时,UA 会先试图在网络中多播消息寻找 DA,如果找到则向 DA 发送查询请求,如果超时没有收到 DA 回复则说明当前网络中没有 DA 的存在,UA 再直接多播该查询寻找 SA。当查询请求发出以后,程序会立即返回,不用阻塞以等待 SA/DA 的回复消息。方法返回的 enumVar 是一个迭代器,通过它可以得到查询的结果。

ServiceURL sUrl = null;while(enumVar.hasMoreElements()) { sUrl = (com.solers.slp.ServiceURL)enumVar.next(); if(sUrl != null) { System.out.println("Found URL: " + sUrl.toString()); }}

如代码所示,像使用普通迭代器一样,先判断容器中是否还有元素,如果有的话就把它取出。这里要注意一点,在执行 hasMoreElements() 时,程序才会去接收 DA/SA 的回复消息,这时有可能会产生阻塞。查询服务得到的结果是 ServiceURL 对象,其中包含服务地址 url 和生存期,这样我们就找到那些在 4 楼的打印机的服务地址了。在这个示例中,只是简单的把找到的所有这些 url 打印出来,在实际应用中你可以自由处理这些得到的信息,比如给某个打印的程序配置打印机位置信息。

总结

本文介绍了 SLP 的概念和应用,并把它与一些其他服务发现的协议比较,可以看到,SLP 在该领域功能十分强大,但是它在某些场合也有着一些不足之处。本系列专题的第二篇将讨论协议的扩展与改进,在与当前协议兼容的情况下,扩展协议进一步丰富其功能。

免责声明:

1, 本文所提出的方式方法仅代表作者个人观点。

2, 本文属于原创作品,资料来源不超出参考文献所列范畴,其中任何部分都不会侵犯任何第三方的知识产权。