一、前言
之前的文章有讲过后端架构演进系列,这个系列文章还是以一个经典的电商系统为例子,来讲讲Robben是如何在实际开发中一步一步打造出一个大型的后端架构的。本系列文章更多的一些实践操作方面的操作和选型。
工欲善其事,必先利其器。在业务代码开发前,让我们先做好相关的基础设置建设。
二、云平台
云服务的选择有阿里云、腾讯云、华为云等等。阿里云是老牌云服务商了,产品配套齐全,文档丰富,价格也是相应的贵一点。腾讯云算是后起之秀,有腾讯背书,价格比阿里云便宜点。华为云没用过就不评价。
运行环境可以选择jar包直接运行在Linux环境上,也可以选择使用Kubernets进行部署。
我们这里云服务商选择腾讯云,然后平台选择Kubernetes去管理我们整个后端应用周期。
三、代码管理
关于Git和Svn现在基本都是选择Git了吧。可以使用私有的GitLab,或者使用云服务的Git仓库也是一个不错的选择。大部分公司为了代码安全考虑会选择自建仓库。
- 自建GitLab参考:TKE容器集群中部署GitLab服务器
- 云服务腾讯云coding:
本系列文章使用coding的代码仓库来管理。
四、文件服务
这里把文件服务单独拎出来,因为文件存储的安全和维护是比较重要和独立的。
-
自建分布式文件服务fastdfs
fastdfs是开源的分布式文件系统,充分考虑了冗余备份、负载均衡、线性扩容等机制,并注重高可用、高性能等指标。一般用在图片和音频这种中小文件存储,有自建需求的团队可以考虑。 -
使用云服务商提供的文件服务
这种就没什么好说的,像阿里云OSS,七牛云等等都可以。
综合成本使用考虑本系列文章使用七牛云的文件服务。
五、统一依赖管理Maven
随着依赖的不断增多,内部服务的不断产生。统一的版本管理就显得十分重要。
Maven私服
用来统一管理依赖和内部二方库。可以选择自建,也可以用云服务的。
自建Nexus: 省略了,网上一搜以大把。
云服务:Coding的制品库管理。
maven setting中指定
<profile>
<id>robbendev-robbendev-robbendev</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<repositories>
<repository>
<id>robbendev-robbendev-robbendev</id>
<name>robbendev</name>
<url>https://robbendev-maven.pkg.coding.net/repository/robbendev/robbendev/</url>
<releases>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
</releases>
<snapshots>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
</snapshots>
</repository>
</repositories>
</profile>
统一依赖项目
统一依赖项目结构
robbendev-maven
├── pom.xml
├── robbendev-bom
│ ├── pom.xml
├── robbendev-dependencies
│ ├── pom.xml
└── robbendev-parent
├── pom.xml
看下具体代码
robbendev.maven/pom.xml主要是配置私服的地址
<groupId>com.robbendev</groupId>
<artifactId>robbendev-maven</artifactId>
<version>1.0-SNAPSHOT</version>
<modules>
<module>robbendev-bom</module>
<module>robbendev-dependencies</module>
<module>robbendev-parent</module>
</modules>
<packaging>pom</packaging>
<name>robbendev-maven</name>
<description>robbendev maven nexus 基础配置</description>
<!-- omitted xml -->
<distributionManagement>
<repository>
<!--必须与 settings.xml 的 id 一致-->
<id>robbendev-robbendev-robbendev</id>
<name>robbendev</name>
<url>https://robbendev-maven.pkg.coding.net/repository/robbendev/robbendev/</url>
</repository>
</distributionManagement>
robbendev-maven/robbendev-bom/pom.xml主要是统一内部二方库的依赖版本
<parent>
<artifactId>robbendev-maven</artifactId>
<groupId>com.robbendev</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>robbendev-bom</artifactId>
<name>robbendev-bom</name>
<description>robbendev二方库依赖配置</description>
<packaging>pom</packaging>
<properties>
<robbendev-common.version>1.0-SNAPSHOT</robbendev-common.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.robbendev</groupId>
<artifactId>robbdendev-common</artifactId>
<version>${robbendev-common.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
robbendev-maven/robbendev-dependencies/pom.xml主要是统一外部三方库的依赖版本
<parent>
<artifactId>robbendev-maven</artifactId>
<groupId>com.robbendev</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>robbendev-dependencies</artifactId>
<name>robbendev-dependencies</name>
<description>robbendev三方库依赖配置</description>
<packaging>pom</packaging>
<properties>
<spring-cloud.version>Hoxton.SR7</spring-cloud.version>
<spring-boot.version>2.3.3.RELEASE</spring-boot.version>
...
</properties>
<dependencyManagement>
<dependencies>
<!--spring cloud-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--spring boot-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
...
</dependencies>
</dependencyManagement>
robbendev-maven/robbendev-parent/pom.xml聚合二方库和三方库依赖配置的pom作为所有项目的父pom文件
<properties>
<robbendev-bom.version>1.0-SNAPSHOT</robbendev-bom.version>
<robbendev-dependencies.version>1.0-SNAPSHOT</robbendev-dependencies.version>
</properties>
<dependencyManagement>
<dependencies>
<!--二方库依赖管理-->
<dependency>
<groupId>com.robbendev</groupId>
<artifactId>robbendev-bom</artifactId>
<version>${robbendev-bom.version}</version>
<scope>import</scope>
<type>pom</type>
</dependency>
<!--一方库依赖管理-->
<dependency>
<groupId>com.robbendev</groupId>
<artifactId>robbendev-dependencies</artifactId>
<version>${robbendev-dependencies.version}</version>
<scope>import</scope>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>
这样我们的依赖管理就完成了,新的项目只用继承
<parent>
<groupId>com.robbendev</groupId>
<artifactId>robbendev-parent</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
六、自动集成CI/CD
自定集成将开发人员从繁杂的打包发布过程解脱出来,能专注于业务代码的开发。是团队提效的有效方法。
二方库的发布
以robbendev-maven项目为例子,我们在每次依赖版本有变更的时候,如何快速推送Maven私服呢? 以本项目为例业内有一下常见方案
- gitlab-ci 如果使用的gitlab仓库的话可以考虑这个方案。
- 自建jenkins 如果有自己的运维团队,可以考虑使用自建的运维平台。
- 使用云服务
这里简单介绍下笔者使用的coding持续继承,这个也是完全兼容jenkins的。 基本上也是在控制台配置好:
可以使用流程配置,也可以使用仓库中的Jenkinsfile
...
stage('编译') {
steps {
sh 'mvn clean package'
}
}
stage('推送到 CODING Maven 制品库') {
steps {
echo '发布中...'
sh 'mvn deploy -DskipTests'
echo '发布完成.'
}
}
}
打包机器由于要配置maven的setting文件,所以选择自定义节点构建。
选择适合自己的触发方式,现在提交代码就可以看到触发了自动集成和部署:
服务的发布
以一个最基础的SpringBoot的程序为例子 在腾讯云镜像仓库获取账号密码后 在maven setting中配置
<server>
<id>robbendev-docker</id>
<username>100000000000</username>
<password>xxxxxxxxxx</password>
<configuration>
<email>xxxxxxx</email>
</configuration>
</server>
应用代码结构
├── pom.xml
├── src
│ ├── main
│ │ ├── docker
│ │ │ └── Dockerfile
│ │ ├── java
│ └── test
pom.xml使用docker插件,注意这里的serveId对应setting.xml中的配置,maven.build.timestamp.format属性一定要指定。imageName的含义是使用时间戳作为版本号。
<properties>
<maven.build.timestamp.format>yyyyMMddHHmm</maven.build.timestamp.format>
...
</properties>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>1.0.0</version>
<configuration>
<skipDockerBuild>false</skipDockerBuild>
<imageName>ccr.ccs.tencentyun.com/robbendev.hello-docker/robbendev-hello-docker:${maven.build.timestamp}
</imageName>
<dockerDirectory>src/main/docker</dockerDirectory>
<resources>
<resource>
<targetPath>/</targetPath>
<directory>${project.build.directory}</directory>
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
<serverId>my-docker</serverId>
</configuration>
</plugin>
看一下jenkins关键代码
stage('编译打包部署') {
steps {
sh '''
git checkout master
git pull
mvn clean package docker:build -DpushImage'''
}
}
这样在提交代码的时候就可以自动打包镜像推送到腾讯云镜像仓库,然后通过镜像触发器可以实现自动发布。
七、小结
这样一套组合拳下来,Robben终于可以开始好好开发了。接下来会介绍Robben是如何从单体应用到集群再到微服务进行开发的。
觉得有帮助的同学帮忙点个赞。 有问题拍砖robbendev@gmail.com