2.1.8 工人计算的服务化模式

在分布式应用中,非常基础也非常广泛的一项应用就是服务化,服务是SOA架构中最核心的单元,可以说所有的SOA都是服务的组成和上层运用。

什么是服务,大家了解到WebService是服务,MQ也可以看做一个服务,Http可以看做服务,Socket服务端也可以看做服务,Ftp也可以做服务,等等。

我们听说过这么多的技术被叫做服务,那么如何来归纳服务的概念呢?

最简陋的理解:服务是一个监听程序,它说白了就是提供服务器在某个端口监听,并提供根据业务定义的输入输出数据格式交换接口。

因此,我们写一个Socket服务程序,它一直监听等待,它只接受某种格式的消息头,并返回某种格式的数据,那么这就是一个原始简陋的服务。

当然有更标准的服务WebService,它提供一个基于XML的WSDL服务定义,无论什么样的程序语言平台,我们都遵循这个XML输入输出标准,如何查看这个服务标准呢,访问它的WSDL文件,然后各自的程序语言平台去实现各自语言数据格式到XML数据格式的转换,分布式通信交互都是通过XML的消息方式进行,WSDL严格定义了服务的内容和数据格式,而且形成标准。

不过,我发现很多公司并不喜欢WebService的标准服务(我怀疑可能开发有点繁琐,因此工程师难上手而回避它,好像更喜欢restful方式的简单服务),而更多是自己实现一个类似上面说的Socket原始简陋的服务,当然他们的实现技术千差万别,一般不会基于底层写TCP通信,而会借助MINA、NETTY这样的通信组件解决通信交互问题,然后再自己做点序列化的工作,再集成到Spring等Bean管理容器中。最后完成的这个服务产品肯定没有WSDL的标准定义,在其之上也比较难做ESB等标准服务编排等SOA架构,它更多的是用在公司内部的服务化需求中,而很少用在公司对外的服务集成中。

实际上在金融行业,银行保险公司对外提供的服务交换接口中,银监会有着严格的服务标准定义,比如银保通定义了银行和保险公司数据交换的详细格式和内容,体现在他们系统对外的服务接口上,必须严格遵循该项标准。否则金融行业对外的系统交互需求特别多,如果各个公司都遵循自己的服务标准,几乎建立不了公共标准的集成应用。

我们理解了一些服务的概念,再回头来看看Fourinone做为一个分布式框架,对服务性质的功能的支持,那么可以肯定的是提供不了WebService的标准跨平台服务,因为框架的侧重点不是在服务化的深入和标准上,但是由于分布式技术与服务的相似性,可以实现上面理解的最原始简陋的服务。

2.1.8 工人计算的服务化模式 - 图1提示

实际上工人都是一个个的服务,doTask是一个通用的服务接口。只不过通常在并行计算中工人只对一个工头提供服务,默认不允许多个工头对它调用,它们默认并不是一个广泛意义的服务,但是我们可以通过修改配置文件将工人改成一个广泛的服务。

在config.xml配置文件的工人模块:

  1. <PROPSROW DESC="WORKER">
  2. <SERVICE>false</SERVICE>
  3. </PROPSROW>

我们可以看到SERVICE项的默认配置是FALSE,将它改为TRUE,那么工人变成一个服务概念,由于服务需要支持多个客户端同时访问,每个工人服务可以接受多个工头调用,工头在这里变成一个服务客户端概念,WareHouse在这里变成了一个输入输出的格式定义,因为WareHouse是一个通用的MAP,它什么都可以装,也什么都可以返回。最后我们的通用服务接口看上去像这样:

  1. Map outputdata doService(Map inputdata)

只不过这里名字不叫doService,而叫doTask。

2.1.8 工人计算的服务化模式 - 图2

图2-9 工人计算服务化模式

但是我们面向用户的时候多半不是上面通用服务接口的样子,而是有业务含义的特定服务接口,比如像下面这个样子:

  1. String sayHello(String name)

这个特定服务输入一个字符串参数name,根据逻辑返回另外一个字符串结果。按照我们设计软件的通常做法,一般会将背后原始基础的通用服务隐藏起来,把面向用户的接口暴露给它们,而在用户接口的实现里面调用原始的通用基础服务doTask。在下面2.5.1节的例子里我们就可以看到。

另外还有个地方要注意,使用工头获取线上工人服务需要输入一个类型然后得到一个集合,这实际上意味着我们可以让工人指定提供某种类型的服务,并且可以有多个工人提供这种类型的服务,换句话说,提供某种服务的地址可以有多个,比如3个服务器都可以提供hello服务,我们可以负载均衡的访问他们其中一个,这恰恰是大型分布式服务系统所需要的。

根据之前我们了解的doTask的调用,在并行计算环境下需要轮询结果,如果是服务化运用,包工头实际上是在提供客户端的功能,doTask实际上是服务调用,那么我们可以异步方式调用,轮询结果;也可以同步调用,使用前面讲的doTaskBatch,等待结果完成后再返回。

工人服务化详细实践和示例请参见2.5.16节。