`

浅谈系统拆分

阅读更多
今晚好冷啊,回去的路上,我突然想到一件关于系统拆分的事情。举的例子很极端,仅供参考,不一定有实际的意义

我感觉拆分系统,和拆分代码,本质上是一样的。小到一个方法,大到几个系统,都是一个从输入到输出的序列

Level 1:
public void doSomething(){
    System.out.println("111");
    System.out.println("222");
    System.out.println("333");
}

这种情况是最简单的,所有的代码都在一个方法里,没有任何拆分

Level2:
public void m2(){
    System.out.println("222");
}

public void doSomething(){
    System.out.println("111");
    m2();
    System.out.println("333");
}

效果和Level 1是一样的,只是中间多了一次方法的调用,实际上是内存指针偏移。但比起将所有代码写在一个方法里,这里已经做了最简单的拆分

Level3:
public class Class2{
    
    public static void m2(){
        System.out.println("222");
    }

}

public class Class1{

    public void doSomething(){

        System.out.println("111");
        Class2.m2();
        System.out.println("333");
    }

}

还是很简单,但是比Level2又多了一层,将部分代码拆分到了另一个类里

直到目前为止,无论拆分与否,所有的代码都在同一个进程里,所以都是本地调用(仅需要偏移内存指针即可),过程类似下图:



这里要补充一点,就JAVA平台来说,凡是要调用的代码在同一个JVM里,且classloader可见,都可以认为是本地调用。不管它是打包在.jar文件里,还是直接存放在classpath里,也不管其源码是否来自一个地方

Level4:



现在,输出222这段逻辑,被拆分到了另外一个系统里

所以,只有通过远程调用(RPC),才能111->222->333了,但是本质并没有改变,还是从输入到输出的一串序列,只是本地调用,和远程调用的区别

事实上,这种区别对调用者来说,常常是透明的
public void doSomething(){
    System.out.println("111");
    Proxy proxy = getProxy();// Proxy是一个interface
    proxy.print222ForMe();
    System.out.println("333");
}

对这个调用者来说,它并不需要知道proxy的实现来自哪里。这是一次本地调用还是一次远程调用,对调用者来说是透明的。只有在上面的部署图里,才能看出区别

通过这个例子,我想说明的是:核心的问题是逻辑,而不是怎么拆分系统。逻辑不会因为放在一个方法里,或者放在10个不同的系统里,就发生变化。最终的结果都是一样的。同时,当需要思考“为什么要拆分系统”的时候,某种程度上和“为什么要拆分代码”是类似的

实际的设计中,拆分系统一般都是必要的,我认为至少有以下3个方面的好处:

1、复用服务

前面举的例子过于简单了,可能有点无法说明问题。但是想象中间那行
System.out.println("222");

是一段非常重要的代码,其他很多逻辑都需要它。那么如果它是混杂在一个方法中,应用的其他部分就无法重复地调用它了(复用);而把它抽取出来之后,就可以实现复用

系统拆分也是一样,比如我画的这两张示意图,是用QQ截图功能截成JPG的。为了截这2张图,我只好把QQ给打开了。如果QQ截图被抽取为单独的模块,我就可以单独打开截图功能了;如果腾讯其他的应用也需要实现截图,就可以复用这部分功能了

当然,系统之所以被称为“系统”,而不是“应用”、“模块”、“方法”,是因为它比较大(我认为除此之外,完全是一回事,有输入、输出、逻辑的都是系统)

所以,作为系统,复用的往往不是截图这么小的功能,一般希望能够复用一个完整的服务。比如独立出“用户权限管理系统”,就可以在多个业务系统中,复用“用户校验和鉴权”的服务了。我想这就类似几年前比较流行的一个大词SAAS

2、性能考虑

一个大的系统,往往其中的某个部分,承担了很大的并发压力,或者逻辑运算特别复杂,因此成为系统的性能瓶颈

这时就可以考虑将这部分独立出来,从而实现单独部署,再通过负载均衡等手段,来解决性能的问题

3、逻辑清晰

根据业务上、流程上的不同环节,将整个系统拆分为不同的子系统,在逻辑上会更加清晰,从而更容易在架构上说清楚,或者进一步做优化

暂时想到这3点,欢迎补充

PS:至于源码工程的管理,完全是另一回事了。一个工程可以构建出N个系统;N个工程也可以构建出一个系统。是架构的2个不同角度的视图
  • 大小: 12 KB
  • 大小: 18 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics