Java后端架构开荒实战(一)——基础设施

1,355 阅读3分钟

一、前言

之前的文章有讲过后端架构演进系列,这个系列文章还是以一个经典的电商系统为例子,来讲讲Robben是如何在实际开发中一步一步打造出一个大型的后端架构的。本系列文章更多的一些实践操作方面的操作和选型。

工欲善其事,必先利其器。在业务代码开发前,让我们先做好相关的基础设置建设。

二、云平台

云服务的选择有阿里云、腾讯云、华为云等等。阿里云是老牌云服务商了,产品配套齐全,文档丰富,价格也是相应的贵一点。腾讯云算是后起之秀,有腾讯背书,价格比阿里云便宜点。华为云没用过就不评价。

运行环境可以选择jar包直接运行在Linux环境上,也可以选择使用Kubernets进行部署。

我们这里云服务商选择腾讯云,然后平台选择Kubernetes去管理我们整个后端应用周期。

image.png

三、代码管理

关于Git和Svn现在基本都是选择Git了吧。可以使用私有的GitLab,或者使用云服务的Git仓库也是一个不错的选择。大部分公司为了代码安全考虑会选择自建仓库。

本系列文章使用coding的代码仓库来管理。

四、文件服务

这里把文件服务单独拎出来,因为文件存储的安全和维护是比较重要和独立的。

  • 自建分布式文件服务fastdfs
    fastdfs是开源的分布式文件系统,充分考虑了冗余备份、负载均衡、线性扩容等机制,并注重高可用、高性能等指标。一般用在图片和音频这种中小文件存储,有自建需求的团队可以考虑。

  • 使用云服务商提供的文件服务
    这种就没什么好说的,像阿里云OSS,七牛云等等都可以。

综合成本使用考虑本系列文章使用七牛云的文件服务。

五、统一依赖管理Maven

随着依赖的不断增多,内部服务的不断产生。统一的版本管理就显得十分重要。

Maven私服

用来统一管理依赖和内部二方库。可以选择自建,也可以用云服务的。
自建Nexus: 省略了,网上一搜以大把。
云服务:Coding的制品库管理。

image.png

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私服呢? 以本项目为例业内有一下常见方案

  1. gitlab-ci 如果使用的gitlab仓库的话可以考虑这个方案。
  • 自建jenkins 如果有自己的运维团队,可以考虑使用自建的运维平台。
  • 使用云服务

这里简单介绍下笔者使用的coding持续继承,这个也是完全兼容jenkins的。 基本上也是在控制台配置好:

image.png

可以使用流程配置,也可以使用仓库中的Jenkinsfile

...
stage('编译') {
    steps {
        sh 'mvn clean package'
    }
}
stage('推送到 CODING Maven 制品库') {
    steps {
        echo '发布中...'
        sh 'mvn deploy -DskipTests'
        echo '发布完成.'
    }
}
}

打包机器由于要配置maven的setting文件,所以选择自定义节点构建。

选择适合自己的触发方式,现在提交代码就可以看到触发了自动集成和部署:

image.png

服务的发布

以一个最基础的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