zoukankan      html  css  js  c++  java
  • 项目拆分与服务重构

    好的架构不是买来的,也不是最开始就被设计出来的,而是在业务发展中,逐步演化过来的。项目刚开始,应抱着最小可用产品的理念,尽快做出最小可用产品,给客户使用获取反馈,然后基于反馈快速的迭代开发。在没有交付使用前,再好的架构都是假设,产品越晚使用,失败的风险和成本越高。

    在开发的初期,我们对于服务的拆分,往往是根据产品或者是客户的需求,通过恰当的分层和包名来完成服务的拆分。

    这个也就是我们通常所说的单一应用,在这个阶段,我们通常会有如下几个准则:

    1、为了降低耦合,系统应进行恰当的分层,比如我们常说的MVC。

    2、用于增删改查的ORM框架是一个关键,一个好的ORM框架能大大提高我们的开发效率。

    3、一些基本的、通用的框架比如Spring应该被引入,为了考虑到以后新人的加入和持续的可维护性,我们不应该使用一些冷门的框架。

    4、我们会从需求中抽象出来一些关键名词、动词和属性,并对一些核心概念进行抽象,完成建模,并在团队内形成“通用语言”,我们在团队的日常交流中都应该使用这些“通用语言”。

    5、我们应该有数据库和持续集成服务器,便于快速发布应用,必要时要引入代码审查工具。

    在这个开发的过程中,一切都有条不紊的进行,产品经理的需求可以很快得到了满足,更多的新同事加入进来,更多的功能也加入进来,所有人都对现状和架构很满意,因为这个单一的项目架构是如此的清晰、简单、高效。团队不大,交流也非常高效,大家配合的很默契。

    可是好日子不长,产品经理有很多的想法,新的功能一个个被添加进去,代码变的非常臃肿,每次编译都需要花费很长时间。这时开始有人想到重构,在重构的过程中,会把一些通用的代码封装成common项目,也可能把不同的层,比如service层独立封装成一个项目。

    可是随着新加入的员工越来越多,并不是所有人都对所有的代码都很熟悉,构建时间越来越长,开发工具也慢了下来,代码变的越来越臃肿。开发速度也慢了下来,每次想增加一个新的功能,会发现代码之间纵横交错,不知道从哪里下手,为了快速实现需求, 无奈只能新增加一个接口,可能他并不知道已经有类似的接口存在,慢慢的增加了很多冗余代码。突然有一个程序员,想把某一个功能重构,但是他翻看一下代码,发现有很多看不懂的业务,无奈他放弃了。随着越来越多的类似事情发生,最终没有一个人能清楚的知道系统是怎么运行的。

    此时此刻,系统通常会面临如下几个问题:

    1、开发速度慢,编译速度慢,代码之间耦合严重,每次开发一个新功能,都可能会牵涉到很多模块,在开发的过程中有很多隐患很难排查。

    2、项目过大,发版困难,在发版时,甚至可能需要停机。

    3、业务复杂,新人接手困难,任何人都不敢轻易调整代码,随便调整一处,都可能影响到很多自己不知道的模块。

    4、技术升级困难,团队对于新技术越来越保守,不敢随意引入新技术,会增加技术风险。

    5、连接池之类的底层资源压力巨大,因为数据库是单点,在机器的横向扩展过程中,数据库连接数过大。

    假如你没有满足上述条件,博主并不建议去服务化,因为服务化有很多以前单点系统中没有遇见过的挑战,需要提前规划起来,比如通讯、分布式事务、服务如何拆分以及拆分的粒度等问题。

    如何进行服务拆分和重构

     

    从我最近接手的项目为例。

    这个项目的现状非常棘手,团队几乎都是新人,几乎没有一个人对系统是如何运行有清晰的认识,项目时间过长,开发过程中没有文档,只能依靠代码中零星的注释。数据库表有近百张,至于真正用到了哪些表,没有一个人能说的清除。和外部系统之间调用模糊,不清楚此系统和外部系统是如何交互的。

    在进行拆分和重构之前,我们通常要做如下几件事:

    1、需要先摸透所有的业务和数据库。

    2、到底有哪些真实在使用的接口,可以依靠访问日志进行排查。

    3、和之前参与过的同事进行充分的了解和沟通。

    4、排查清楚和外部系统的关系,明确服务的职责和边界,在此过程中需要结合业务进行划分。这个过程还需要协调对应的项目组,进行配合整改,外部协调可能会带来不确定性,需要考虑这些服务是否要先上线。

    5、确定数据迁移方案,和产品进行沟通,确定必须要迁移的数据,可能有一些数据并不需要迁移到新系统,或者可以通过其他方式进行解决。

    拆分的目标

    在重构时,我们应该将系统中的独立业务模块抽取出来,按照业务的独立性进行垂直划分,抽象出基础服务层,抽象的目标是,每一个基础服务层都是无状态的和去中心化的,可以弹性部署,可随着系统的负荷灵活伸缩来提供服务能力,这些基础服务都是通过底层中心系统发生关系的,比如配置中心、日志服务、消息服务、柔性事务服务等。这些基础服务会为上游业务系统提供支撑。

    在进行服务化拆分时,我们还需要考虑到的一个问题就是,组织沟通方式决定系统设计,这个主流的理论就是康威定律。我们期望拆分后的服务可以减少协同、减少环节、提升效率。说的通俗一点就是,如果某个应用,需要多个组织之间一起交流和修改,那么它的交流成本就大于组织机构了,出现了不匹配的情况,那么这个应用就很可能太粗而需要拆分。

    我们可以将业务的流转过程画成图,先找出其中的名词和动词,每个名词和动词都可能是一个服务。

    在服务数量上的划分时,并没有一个准则。服务过多,可能会导致划分过细,破坏业务系统之间的独立性,维护工作量变大,部署时占用内存多,而且定位问题困哪重重,还很难梳理服务之间的依赖关系,比如支付订单、退款订单,被划分成了两个服务。服务过少,可能没有实现很好的解耦,开发维护不好分工,升级影响面变大,比如一个服务要升级,会影响很多业务不可用。

    经过服务拆分后,每个服务通常都有自己独立的数据库,在数据库查询时,不要出现A服务中的SQL需要链接查询到B服务中的表等情况,这样在A服务与B服务进行数据的垂直拆库时就会出错。

    在服务调用时,服务子系统间应该避免出现环状的依赖调用(比如A服务依赖B服务,B服务依赖C服务,C服务依赖A服务)。

    在服务依赖上,服务子系统间的依赖关系链不要过长(不能超过3个)。

    在拆分时,应该尽量避免分布式事务,除非可以解决分布式事务,否则无法达到一致性。

    从经验上来说,初期应该根据业务划的比较大块,比如账户模块和用户模块合成一个服务,交易和订单作为一个服务,大概分到3至5个服务,根据业务的发展情况,需要细分时再去分。

    服务聚合

    在拆分后,每个服务都只对自己的业务负责,这些服务对外提供的接口粒度可能都比较细。但总会有一些复杂业务需要依赖多个服务才能实现业务需求。对于这个问题,以我此次重构的经验来说,我会对每一个业务系统(比如某一个App),都建一个对应的后台服务,复杂的需求、需要多个服务组合完成的需求会通过后台服务进行访问,依靠这个App Server完成服务聚合。

    https://mp.weixin.qq.com/s/7pQR1Q-z8uOQHOwx4I6n_Q

  • 相关阅读:
    12.2 ROS NavFn全局规划源码解读_2
    12.1 ROS NavFn全局规划源码_1
    12 ROS Movebase主体源码解读
    11 ROS 动态参数调节
    10. ROS costmap代价地图
    无人驾驶汽车1: 基于Frenet优化轨迹的无人车动作规划方法
    VC下加载JPG/GIF/PNG图片的两种方法
    vc++加载透明png图片方法-GDI+和CImage两种
    供CImage类显示的半透明PNG文件处理方法
    使用MFC CImage类绘制PNG图片时遇到的问题
  • 原文地址:https://www.cnblogs.com/doit8791/p/9248476.html
Copyright © 2011-2022 走看看