不灭的焱

革命尚未成功,同志仍须努力

作者:php-note.com  发布于:2012-12-02 22:39  分类:系统设计/架构  编辑

【第九阶段逻辑关联和层次划分】

在第七阶段的时候,我们提到了几个问题,其中有一个就是业务关联问题。当我们将业务拆分以后,多个业务之间没有了耦合(或者是极弱的耦合),能够独立的运转。这个看起来是多么美妙的事情。但是实际情况真是如此嘛?

这样的业务还真是存在的。比如我们有两个业务blog和image。blog可以上传和展示图片。那image.XXX.com就提供两个HTTP服务,一个是上传的,一个是显示的。这样,blog业务就可以通过简单的URL耦合来实现了图片的这些功能。

但真是所有的情况都是如此的嘛?

我们再看一个例子。比如blog和用户相关的业务。用户可以在blog登录、注销等,blog需要实时判断某一个用户是否登录等。登录和注销两个操作似乎可以通过类似account.XXX.com提供的login和logout这样的URL接口实现。但是每次页面浏览要判断用户是否已经登录了,出于安全性等多方面的考虑,就不好通过URL来提供这样的服务。

那看起来,我们在第七阶段提出的按业务切分的理想情况,在实施的时候,并不是那样的完美。在实际的运行中,耦合是不可避免的。

有了耦合,我的第一反应基本上就是看看是否能够借助设计模式来解决这些的问题。其实呢,设计模式早已经给我们比较好的解决方案(但绝对不是完美的解决方案。俗话说的:没有最好,只有更好!)。在这篇文章的最初已经提到过了,为了增强网站代码的可重用性,我们引入了一些框架,比如:struts、spring、hibernate等等。其实这些框架,基本上是围绕着MVC的原则来设计的。struts、webwork等框架,将视图和逻辑控制分离;spring负责组织业务逻辑的数据;hibernate很好的做了数据访问层的工作,实现了ORM。

那现在我们采用多机分布式的时候,是否可以借鉴这些思想呢?其实也是可以的。

我们来分析一下我们的业务。

其实我们的业务大多可以分为两类:

一、与实际的产品相关的业务,比如:blog、news等等。这些业务之间的耦合度不是很高,往往可以通过提供HTTP的接口即可实现业务需要的互通。因此,从这个层面上来看,是可以基本做到业务垂直拆分的。

二、基础服务,比如:用户帐号管理、消息通知等等。这些服务往往被多个业务所依赖。他们需要提供更通用的、更安全的、更稳定的接口和服务。但是,关于基础业务的理解和划分,是没有一个特定的规则的。比如,image图片服务,他有可能刚开始是一个业务服务,到一定阶段以后,多个系统需要对他有强的依赖,自然也就成为了一个基础服务。

所以,从上面的描述,我们可以发现服务的类型,并不是固定的。要很好的解决服务耦合的问题,也并没有一个十分完美的解决方案。我们能做的就是尽量降低耦合,通过某种方式,能够很好的达到耦合和可维护性的平衡。

总的来看,MVC模式其实给我们提供了一个比较好的方案。

我们把系统从两个维度上进行划分:垂直(业务)和水平(逻辑)。

蚂蚁变大象:浅谈常规网站是如何从小变大的(五)

我们做了这样的划分以后,似乎看起来没有实质性的改变。但是,我们可以明确了我们设计的原则,并强化了代码的可复用性。另外,最关键的是,服务之间的依赖和耦合关系,有了明确的地方来做。同时,我们还可以将业务内部的结构进行拆分,更好的增强复用。

数据访问和组织层、数据存储层,这两个位于下游的层次,应该是属于系统内部的层次,原则上是最好不要对外开放接口的,否则,系统间的耦合就会非常的大。并且可维护性会非常的难。而逻辑控制和视图层,实际上是提供对外(对用户或者是外系统)最好的访问的入口。当然,这个入口可以是HTTP协议的,也可以是非HTTP协议的。

比如,对于account服务,可以提供基于HTTPS对用户开放的login和logout服务,也提供基于XXX Protocol数据交换的协议的给内部的get_session服务。从简单的设计上来看,只是根据服务不同,提供不同的数据交换格式、以及不同的安全控制。这样也是秉承了一个高内聚低耦合的原则。

这里还有几个及其重要的问题没有详细的提及:系统内外的数据传输协议、接口API、服务访问定位。这几个问题实际上还跟运维问题紧密相关,都会放到后面来详细讨论。