一起学习微服务和容器7-项目结构树准备

简述

前情回顾

在前面的章节中,我们陆续介绍了环境准备的各个工具的安装,这就好比我们古语常言的“磨刀不误砍柴工”。那接下来的这个章节,我们将开始介绍项目结构的搭建以及其中应该注意的一些事项。

常见的构建工具介绍

由于本系列是基于Java生态来构建的体系结构,构建的工具也以介绍Java生态的为主。
在Java生态里面,构建项目一般有Ant, Maven, Gradle.

Ant

相信有10年以上工作经验的同学对Ant会比较了解。
在使用Ant开始一个新的项目时,首先应该编写Ant构建文件。构建文件定义了构建过程,并被团队开发中每个人使用。Ant构建文件默认名为build.xml,也可以取其他的名字。只不过在运行的时候 把这个命名当作参数传给Ant。构建文件可以放在任何的位置。一般做法是放在项目顶层目录中。 这样可以保持项目的简洁和清晰。下面是一个典型的项目层次结构。
(1) src存放文件。
(2) class存放编译后的文件。
(3) lib存放第三方JAR包。
(4) dist存放打包,发布以后的代码。

Ant需要自行在网上查找项目所用到的Jar包,并下载放置在lib目录下,这个是其最大的弊端吧。
本人也有将近八、九年没有再用过Ant了,所以在本系列中不再推荐了。

Maven

提起Maven,Java生态圈的各位同学应该比较了解了。引用官方的解释,Maven项目对象模型(POM),可以通过一小段描述信息来管理项目的构建,报告和文档的项目管理工具软件。
Maven 除了以程序构建能力为特色之外,还提供高级项目管理工具。由于 Maven 的缺省构建规则有较高的可重用性,所以常常用两三行 Maven 构建脚本就可以构建简单的项目。由于 Maven 的面向项目的方法,许多 Apache Jakarta 项目发文时使用 Maven,而且公司项目采用 Maven 的比例在持续增长。
说到这里,我们再回头看看Ant,来品品两者之间的些许区别。
Ant 可以说主要是为了 Java 技术开发项目提供跨平台的构建任务。而Maven从 Ant 借用了绝大多数构建任务,但Maven又不仅仅只是构建,更多的是描述项目的高级方面的一些管控。它包含了一个项目对象模型 (Project Object Model),一组标准集合,一个项目生命周期(Project Lifecycle),一个依赖管理系统(Dependency Management System),和用来运行定义在生命周期阶段(phase)中插件(plugin)目标(goal)的逻辑。当我们在使用Maven的时候,会用一个明确定义的项目对象模型来描述我们的项目,然后Maven可以应用横切的逻辑,这些逻辑来自一组共享的(或者自定义的)插件。

Gradle

当当当当,随着时间的推移,这几年又出了一个工具大神Gradle。继续沿用官方的说法,Gradle是一个基于Apache Ant和Apache Maven概念的项目自动化构建开源工具。它使用一种基于Groovy的特定领域语言(DSL)来声明项目设置,抛弃了基于XML的各种繁琐配置。
面向Java应用为主。当前其支持的语言限于Java、Groovy、Kotlin和Scala,计划未来将支持更多的语言。

总体来说,各个工具算是迭代更新吧,不过对于本人来说三种工具都用过,现在的应用主要还是以Maven为主,新起的项目可能会用Gradle,Ant已基本不用了。在本系列中将以Maven为主来介绍。

常见结构树介绍

说起项目的结构,刨除传统的巨石结构,现在的不论SOA还是微服务,基本都是由多个子项目(子服务)构成。

  • 情况1:如果一个比较大的项目,下分多个子项目,每个项目由不同的团队来完成,项目之间除了定义接口之外,并不关注彼此的实现,对于这种情况,项目之间一般没有太多的关联(接口除外),每个项目组可以自由选择自己所负责项目的技术栈(可以是Java,Go,Python等等), 每个子项目可以定义自己内部的项目结构,可以由一个或者多个子服务组成,子项目内部建议使用统一的项目结构树。
  • 情况2:如果一个项目,即使下分了多个子项目或者子服务,但是这些都是由一个团队来完成,技术栈是同一套,这种情况一般情况下会构建统一的项目结构树。
  • 情况3:如果一个项目是由一个团队来完成,技术栈也是一套,考虑到技术选型,也会有每个服务来维护自己服务的情况,但是这种情况不太推荐,会凭白增加后续维护的工作量,大家开发的过程中也可能会遇到各种无谓的一些问题。

我们在本文中,主要阐述的是单个Team内的一个项目的结构树,对于跨Team的项目,其实每个Team维护自己的即可,统一了反而会出现一些问题。

单个Team内的一个项目的项目结构一般会有两种形式来组织:一个是扁平结构,一个是树状结构。

扁平结构

扁平的项目结构,一般常见于业务模块的服务之间相互直接依赖(或Restful接口或者RPC)。其结构树一般如下:


image.png

其实目前,无论哪种微服务体系结构,此种方式的项目结构都不是很常见。

树状结构

树状结构的定义一般会遵循下面的几个不成文的规则:

  • POM一般分为层级节点和项目(服务)节点。
  • 层级节点一般有:根POM,以及根下面每个项目子项目的子根POM。如果需要还可以再加一层。一般推荐3层即可,太深的话不太容易管理。
  • 服务节点一般是单个微服务的节点,或者单个lib包的节点。

而树状结构,由于微服务的技术实现不同,树状结构的构成也会有所不同,其中以Dubbo的RPC框架和Spring Cloud的Restful框架最为典型。

Dubbo型结构树

由于现在所在的公司采用的是Dubbo,并且最初始的架构据说是阿里当时搞Dubbo的核心架构师来指导搭建的,在这里也给大家稍微分享下该树形结构的做法。

  • 根POM一般用来定义子项目(服务)的Module。有些公司或者项目也会在跟POM对该项目所引用的包进行统一版本约束和管控。
  • 子一层为单个业务服务模块的根POM。该层的主要作用也是用来定义该项目(服务)下的Java项目的子模块(亦即Module)。
  • 子二层即为服务的实际项目代码层。

对于子二层的划分,一般又会遵循:

  • 单个Facade项目。一般用来封装本服务的RPC接口,以及接口中所用到的本服务的Java Bean。该项目会被编译为lib包供其它调用本本服务的服务使用。
  • 单个Core项目。一般用来实现Facade所定义的接口以及本服务的业务逻辑,包括Service以及Dao层。
  • 一个或者多个Distribution项目。Distribution即是来打包Facade和Core的发布包,一般该服务的Controller会定义在本项目中。讲到这里大家可能会有疑惑了,那为什么会有多个Distribution。其实多个Distribution,你可以为你的Controller也好或者RPC也好,按照实际业务需求进行拆分,例如:读写分离就可以通过这样来实现(读写分离其中一种哈,还有中间件的模式等)。

额外说一点个人的看法,这个结构其实只是阿里Dubbo团队比较推荐的一种方式,大家可以在自己的项目中灵活运用,如果该项目都是由一个团队来完成的,大家都在一个技术栈里面,其实我更多的是建议把Facade这一层给统一合并了,如果不需要多Distribution的话,也把Core直接和Distribution合并了,这样就变成扁平结构了,oh MGD,忽然觉得扁平结构是不是就是这么来的,嘿嘿,开个玩笑。
总之,公说公有理婆说婆有理,各自不同的看法而已,没有绝对的对与错,适合自己的才是正确的,仅供参考。

image.png

Spring Cloud型结构树

说完了Dubbo的结构树,那我们再来看看Spring Cloud体系结构比较推荐的结构树。
一方面来说,Spring Cloud的通讯协议采用基于HTTP的Restful风格的数据传输,这就决定了,在Spring Cloud微服务体系结构里面,我们不需要定义类似于Dubbo里面的RPC的Facade,我们这是定义好Restful所运用的接口的Java Bean即可。
另一方面来说,Spring Cloud有着自己丰富的组件支持(Dubbo现在也有了部分组件了哈,具体可以参考Dubbo的Apache官网),这些项目我们也要在Spring Cloud运行期间跑起来,所以我们在规划基于Spring Cloud的项目结构树的时候,要把这块儿也统一考虑起来。

综合起来说:

  • 根POM还是需要滴。
  • Spring Cloud组件服务层子POM。
  • 公共组件层子POM。
  • API层子POM。
  • Composite组合层子POM。
  • Core层子POM。
    抛开SpringCloud的组件层,我们先说说,划分API,Composite和Core的用意。


    image.png

这个图是我两年前绘制的,其实下面还跟着两段英文。在这里就不跟大家献丑了,直接中文描述了。
层次划分的因由,主要有下文描述。

Edge Server

在Spring Cloud1.0中,由Zuul来充当,在Spring Cloud2.0中,Spring Cloud团队自己搞了一个基于Netty的非阻塞机制的OpenGateway,性能据说彪悍的一笔,推荐大家试试看,在本系列中,我们两个Gateway都将带大家一起尝试下。
Edge Server,其实按照我个人的项目实践,我更多的是把它用作:

  • 服务路由。
  • 服务限流。
  • 比较土的灰度的支持(灰度支持用这种方法其实不太建议的哈)。+ 还有很重要的一环,就是鉴权认证中的认证,说白了,就是看你请求的资源是否受保护,如果受保护的话,你的账户是否已登录,如果没登录就直接401.
  • 其它的无须累述的用途。
API层

API层,其实说白了,就是把后端的服务依据前端不同的消费需求给封装管理。

  • API层,理论上来说并不进行太多的业务处理,基本就是透传。
  • 如果单个业务请求需要多个组合层的服务来支撑的话,也可以对多个组合层服务进行汇聚(一般情况下很少会出现)。
  • 通常也会在这一层需要加上鉴权,也就是说,所有的鉴权在这一层做,检验你的请求是否有权利访问所需的资源。
Composite组合层

组合层,一般情况下是非必须的。
我们在设计微服务的时候,有一个很重要的原则,一般情况下Core的服务是不允许互相调用形成依赖的,最大的原因在于,随着业务的增多,服务的增多,最后依赖会形成蜘蛛网,可维护性会大大降低。
那Core层不允许互相访问,只是单个业务请求有时候需要多个服务协作完成,这种情况下,组合层就应运而生。

  • 在单个业务请求,需要多个Core服务来协作融合支撑的时候,我们就需要组合层服务。
  • 组合层还有一个比较大的作用就是在分布式事务处理上,如果没有采用分布式事务处理框架,而是自己来实现补偿式事务,则组合层可充当裁判性协调者的作用(具体后续章节会有描述)。
  • 另外需要额外多说一下,牵涉到资金流转的服务,一般需要全程鉴权。说白了,就是钱的处理还慎重。
Core层

Core层是我们前面章节所讲述的核心独立域的服务实现。说白了,就是一个小的完整的独立域,就会映射为单个的Core服务。该服务提供该小域之内的服务能力。
Core层的服务,可以直接透过API层对外直接提供服务,亦可以根据业务需求和其它的Core层服务汇聚成组合层服务,然后对外提供服务的能力。

Common公共组件层

公共组件层,顾名思义主要用来存放公共的一些工具和实体类。

  • Common Utils。主要用来存放一些工具类,比如:类反射工具,文本处理工具,Bean处理工具,二维码生成工具,图片处理工具等等。
  • Common Data。主要用来存放一些公共的Bean。其中主要有:结果集定义Bean,全局常量,全局结果码,以及每个Core服务对外开放服务所用到的Bean(有的同学可能会对此有所顾虑,其实一样的,如果不想放在Common里面,也可以为每个服务,类似于Dubbo一样,定义一个Facade包,专门存放该项目的Bean,个人认为,意义不大)。
  • Common Security。主要用来存放系统的一些安全处理相关的包,可以是自定的AuthClient注解,亦可以是Feign的一些Token传递拦截控制工具等。
BasePlatform基础平台层

该层主要用来存放Spring Cloud自身的一些组件,如:

  • Gateway。可以是Zuul,也可以是OpenGateway。
  • Discovery。可以是Eureka,也可以是Consul的Server,也可以是Zookeeper(Consul和Zookeeper的话需要独立部署,无须再构建项目)。
  • ConfigServer。也就是配置中心,可以是Config Server,也可以使阿里NacOS,也可以是携程的Apollo等(如果是NacOS或者Apollo需要独立部署,无须再构建项目)。
  • oAuth Server。也就是鉴权认证中心,可以是SpringCloud的AuthServer(基于oAuth2),也可以自己用Shiro构建。

综合上述,可以得出Spring Cloud为基础的体系结构的POM树,参考如下:


image.png

讲到这里,我们后面章节所要搭建的项目结构树基本给大家阐述了一下,总体的思想是,参考已成熟的实践,但无须生搬硬套,记住一句话,适合自己的才是最好的。
后面的章节,我们还要对每个工程包进行阐述,然后就开始我们正式的Spring Cloud之旅,期待。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335

推荐阅读更多精彩内容