亲历的企业级微服务的完整构建过程-系列文章目录
本人参与了这次的企业级微服务的完整构建,想要记录下来以便以后复习,同时也想分享给小伙伴们,抛砖引玉,欢迎大家提出自己的意见和建议,大家一起探讨一起成长。以下为该系列所有文章的链接:
- 搭建和使用Maven私有仓库(Nexus)(更新中。。。)
- API网关(待发布)
- 认证中心(待发布)
- Redis框架(待发布)
- RabbitMQ(待发布)
- MyBatis(待发布)
- Web模块(待发布)
- 低代码(待发布)
- Core
- 监控和告警(待发布)
- MongoDB(待发布)
搭建和使用Maven私有仓库(Nexus)-系列文章目录
说明:
- 以下部分模块,绝大多数人,在日常工作中都是用不到的,所以我就没有介绍,毕竟时间是最重要的成本,没必要花大量时间在我们用不到的内容上。
- 下面的“1 通用”章节,系列文章中的每一篇内容都相同,介绍一些背景、约定和官网链接等,大家只要知道这些内容了,就不用每篇文章都去看了。
- 安装步骤
- 登录和界面
- 备份和恢复
- 管理:讲述了Nexus的管理功能,包括用户管理、权限管理、任务管理等
- 使用Nexus仓库:讲述了使用(而非管理) Nexus Repository 的方方面面的知识
- 仓库管理器概念:使用 Nexus 需要先理解一些概念,该节内容提供了必要的背景和知识
- 用户界面概述
- 搜索组件(暂时用不到,略)
- 浏览仓库和仓库组
- 管理当前登录用户的资料
- 上传组件
- 查看标签(仅可用于Pro版本,略)
- 集成(主要讲述了如何使用 APIs 和 集成外部工具)(暂时用不到,略)
- Maven中配置和使用Nexus
正文
1 通用
1.1 前言
在构建微服务之前,需要先做一些准备工作,比如Maven私有仓库的管理。因为有些微服务模块是作为公共组件被其他微服务引用的,这些公共的微服务,就要设置为依赖,并用Maven仓库管理起来,将自定义的依赖上传到Maven中央仓库并不是一个明智的选择。原因有3个:
- 最重要的是隐私和安全问题,我们不可能把企业内部开发的组件上传到公共网络,让所有人能够随便下载;
- 上传很麻烦,上传方法详见 https://blog.csdn.net/agonie201218/article/details/124800163;
- 可能不允许上外网,则无法上传;
- 可能会有网络延迟、上传缓慢的问题。
- 降低了中央仓库的负担。
综上,我们最好是搭建自己的私有Maven仓库,而当前最流行的就是 Sonatype Nexus Repository Manager
,以下简称 Nexus
。
1.2 约定
- 我使用的版本是
OSS 3.40.1-01
,整个系列的文章都是在该版本上展开介绍,你们可能使用的是 Pro 版,少数模块是我的 OSS 版上没有的。不过一般使用的话,OSS 版已经够用了 - 文中出现的
Repository
,中文称之为“仓库” - 文中出现的变量
$install-dir
,值为/opt/sonatype/nexus
- 文中出现的变量
$data-dir
,值为/opt/sonatype/sonatype-work/nexus3
,或/nexus-data
,两者都是在docker容器nexus中的路径,一个是软链接,一个是实际路径 - 文中出现的变量
${jetty.etc}
,值为/opt/sonatype/nexus/etc/jetty
- NXRM:Nexus Repository Manager,即 Nexus 仓库管理器
- RBAC:Role-Based Access Control,即 基于角色的访问控制
1.3 官方文档
提供Nexus的官方文档:https://help.sonatype.com/repomanager3/
官方文档包含了系统要求、搭建方法,以及各种操作方法等,内容已经非常全面了。
2 Maven中配置和使用Nexus
2.1 概述
Maven中主要配置这几种类型的仓库:
- 本地仓库:在本地存储组件的位置,Maven 总是第一个在这里查找依赖,找不到再去其他地方找;
- 中央仓库:Maven 自带的远程仓库,包含了绝大部分的开源组件;
- 私有远程仓库:又称为“私服”,是一种私有的远程仓库,是在局域网内部架设的一个私有仓库服务器(如 Nexus),用其代理所有的远程仓库服务器。我们还可以上传自己开发的项目,作为组件上传到私有远程仓库,作为其他项目的依赖。
- 其他公开的远程仓库:这个一般用不到,我们不讨论这个。
默认配置下,项目需要某个依赖,则 Maven 会先到本地仓库查找,找到了就直接使用;找不到,则到远程仓库查找,可能是中央仓库或私服等;如果还是找不到,则报错,如果能找到,则下载该目标依赖到本地仓库,作为本地缓存。
2.2 Maven配置文件
Maven 有默认配置,其都在配置文件 settings.xml 中。在 Windows 中,该配置文件路径为:C:\Users\Username\.m2\settings.xml
;在 Linux 中,该配置文件路径为:/home/Username/.m2/settings.xml
;其中 Username
为你的登录系统的用户名。
该 settings.xml 文件的路径也是可以自定义的,比如在Idea中:
- 点击“Maven Settings”按钮
- 在设置对话框的“Maven”菜单中,在右侧将“Override”复选框打勾,然后可以分别配置自定义的 settings.xml 文件路径,和 本地仓库的路径
下面是一个配置文件的例子:
<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
<!-- 本地存储路径 默认路径${user.home}/.m2/repository -->
<localRepository>/develop/mvnrepo_micro</localRepository>
<!-- 表示Maven是否需要在离线模式下运行。
| 如果构建系统需要在离线模式下运行,则为true。
| 当由于网络设置原因或者安全因素,构建服务器不能连接远程仓库的时候,该配置就十分有用。
| 默认为false。
-->
<offline>false</offline>
<!-- Maven是否需要使用plugin-registry.xml文件来管理插件版本。
| 如果需要让Maven使用文件${user.home}/.m2/plugin-registry.xml来管理插件版本,则设为true。默认为false。
-->
<usePluginRegistry>false</usePluginRegistry>
<!-- 当插件的组织Id(groupId)没有显式提供时,供搜寻插件组织Id(groupId)的列表。
| 该元素包含一个pluginGroup元素列表,每个子元素包含了一个组织Id(groupId)。
| 当我们使用某个插件,并且没有在命令行为其提供组织Id(groupId)的时候,Maven就会使用该列表。
| 默认情况下该列表包含了org.apache.maven.plugins和org.codehaus.mojo
<pluginGroups>
plugin的组织Id(groupId)
<pluginGroup>com.your.plugins</pluginGroup>
</pluginGroups>
-->
<!-- 配置服务端的一些设置
| 一些设置如安全证书不应该和pom.xml一起分发。
| 这种类型的信息应该存在于构建服务器上的settings.xml文件中。
| settings.xml中server元素下id的值必须与POM中repository或snapshotRepository下id的值完全一致。将认证信息放到settings下而非POM中,是因为POM往往是它人可见的,而settings.xml是本地的 -->
<servers>
<server>
<id>maven-releases</id>
<username>dev-admin</username>
<password>AAAaaa1234</password>
</server>
<!-- <server>
<id>public</id>
<username>zhangwei</username>
<password>{Wyin38Z38KIHbqxejWPrS33oBlm01jGAMW4DpGzuLwA=}</password>
</server>
<server>
<id>release</id>
<username>zhangwei</username>
<password>{Wyin38Z38KIHbqxejWPrS33oBlm01jGAMW4DpGzuLwA=}</password>
</server>
<server>
<id>central</id>
<username>zhangwei</username>
<password>{Wyin38Z38KIHbqxejWPrS33oBlm01jGAMW4DpGzuLwA=}</password>
</server> -->
</servers>
<mirrors>
<!-- <mirror>
<id>aliyun</id>
<name>aliyun Maven</name>
<mirrorOf>*</mirrorOf>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
</mirror> -->
</mirrors>
<profiles>
<profile>
<id>env-dev</id>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
</properties>
<repositories>
<repository>
<id>public</id>
<!-- <url>http://101.34.35.96:8081/repository/maven-public/</url> -->
<url>http://nexus.ciicsh.com/repository/maven-public/</url>
<releases>
<!--支持从此仓库下载release版本-->
<enabled>true</enabled>
<!--从远程仓库检查更新的频率,默认daily,表示每天检查一次,其他可用值:
never——从不检查更新
always——每次构建都检查更新
interval:X——每隔X分钟检查一次更新,X值为整数 -->
<updatePolicy>daily</updatePolicy>
<!--检查校验和文件的策略,默认为warn,maven执行构建时输出警告信息,其他可用值:
fail——遇到校验和错误就让构建失败
ignore——完全忽略校验和错误 -->
<checksumPolicy>warn</checksumPolicy>
</releases>
</repository>
</repositories>
<!-- 插件仓库 -->
<pluginRepositories>
<pluginRepository>
<id>public</id>
<!-- <url>http://101.34.35.96:8081/repository/maven-public/</url> -->
<url>http://nexus.ciicsh.com/repository/maven-public/</url>
<releases>
<enabled>true</enabled>
<updatePolicy>daily</updatePolicy>
<checksumPolicy>warn</checksumPolicy>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</profile>
</profiles>
<activeProfiles>
<activeProfile>env-dev</activeProfile>
</activeProfiles>
</settings>
2.3 Maven本地仓库
Maven本地仓库的默认路径:在 Windows 中,该配置文件路径为:C:\Users\Username\.m2\repository\
;在 Linux 中,该配置文件路径为:/home/Username/.m2/repository/
;其中 Username
为你的登录系统的用户名。
这个默认路径可以在 settings.xml 中的 localRepository
属性中配置和更改:
<localRepository>/develop/mvnrepo_micro</localRepository>
2.4 Maven远程仓库-中央仓库
中央仓库是默认的远程仓库,maven在安装时,自带中央仓库的配置,所有的maven项目都会继承超级 pom,超级 pom 文件可以这样找到:
我使用的是 idea 中内置的 maven3.6.3,需要找到 maven-model-builder-3.6.3.jar
这个文件,该文件的路径是 $IDEA_HOME/plugins/maven/lib/maven3/lib/
(我是Ubuntu系统,$IDEA_HOME 是 idea 的安装目录),可以解压缩 maven-model-builder-3.6.3.jar
,也可以使用 JD-GUI
打开该 jar文件。如下图所示:
找到其中的 pom-4.0.0.xml
文件,这就是 超级 pom 文件。然后找到其中的 repositories
属性,就是配置的中央仓库的信息:
<repositories>
<repository>
<id>central</id>
<name>Central Repository</name>
<url>https://repo.maven.apache.org/maven2</url>
<layout>default</layout>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>central</id>
<name>Central Repository</name>
<url>https://repo.maven.apache.org/maven2</url>
<layout>default</layout>
<snapshots>
<enabled>false</enabled>
</snapshots>
<releases>
<updatePolicy>never</updatePolicy>
</releases>
</pluginRepository>
</pluginRepositories>
2.5 Maven远程仓库-私有远程仓库
实际开发时,我们不会使用默认的中央仓库,而是使用自己搭建的私有远程仓库,原因参考 1.1 前言。
2.6 Nexus中配置角色
- 进入“Roles”菜单,点击“Create Role”按钮
- 选择“Role Type”为“Nexus role”
- 填写“Role ID”为
developer
;选择“Privileges”为nx-all
(表示拥有所有权限)
- 点击“Save”按钮,创建成功了一个角色
developer
2.7 Nexus中创建用户
- 进入“Users”菜单,点击“Create local user”按钮
- 在页面上填写必填字段
其中,“Roles”选择之前我们创建的“开发者”。所有内容填完,点击“Create local user”按钮,创建成功了一个用户zhangsan
。
2.8 Nexus中开启releases仓库的重复发版权限
- 进入“Repositories”菜单
- “Deployment policy”属性中选择“Allow redeploy”,然后点击“Save”按钮保存
2.9 Nexus中配置阿里云远程仓库
首先,关于仓库基础知识的介绍,参考 企业级微服务构建-01搭建和使用Maven私有仓库(Nexus)-05仓库管理。
我们要新建一个代理仓库,代理访问阿里云仓库。
-
点击“Create repository”按钮
-
选择仓库格式为 maven2,仓库类型为 proxy
-
填写仓库名称 maven-aliyun(可自定义),和远程仓库URL
阿里云远程仓库的 URL,以下两个都可以(亲测),只不过一个是旧版本地址,一个是新版本地址:
https://maven.aliyun.com/nexus/content/groups/public/
(旧版本)
https://maven.aliyun.com/repository/public
(新版本)
-
点击“Create repository”按钮,就新建好了仓库
-
将阿里云远程仓库添加到默认仓库组中
点击 maven-public,进入该仓库组的编辑页面
选中之前创建的仓库 maven-aliyun,点击中间的“>”按钮
点击中间的“^”按钮,将 maven-aliyun 移动到顶部,表明查找依赖时首先查找阿里云仓库,然后点击“Save”按钮保存,即可
2.10 Maven中配置Nexus以及测试上传组件到托管仓库
本节目的是,在 Maven 的 settings.xml 配置文件中,将远程仓库设置为自己搭建的 Nexus 私服。
- 查看上面的 Nexus 中内置的仓库组 maven-public 的 URL,为:
http://localhost:8081/repository/maven-public/
- 修改 Maven 的 settings.xml 配置文件
主要修改/设置如下内容:
<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
<!-- 省略部分内容 -->
<mirrors>
<!-- 本来配置的是 aliyun 远程仓库
<mirror>
<id>aliyun</id>
<name>aliyun Maven</name>
<mirrorOf>*</mirrorOf>
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
</mirror> -->
<mirror>
<id>test_nexus</id>
<mirrorOf>*</mirrorOf>
<name>test nexus</name>
<!-- 这里的 url 就是 nexus 上查看到的URL -->
<url>http://localhost:8081/repository/maven-public/</url>
</mirror>
</mirrors>
<profiles>
<profile>
<id>test-nexus</id>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
</properties>
<repositories>
<repository>
<id>nexus</id>
<url>http://localhost:8081/repository/maven-public/</url>
<releases>
<!--支持从此仓库下载release版本-->
<enabled>true</enabled>
<!--从远程仓库检查更新的频率,默认daily,表示每天检查一次,其他可用值:
never——从不检查更新
always——每次构建都检查更新
interval:X——每隔X分钟检查一次更新,X值为整数 -->
<updatePolicy>daily</updatePolicy>
<!--检查校验和文件的策略,默认为warn,maven执行构建时输出警告信息,其他可用值:
fail——遇到校验和错误就让构建失败
ignore——完全忽略校验和错误 -->
<checksumPolicy>warn</checksumPolicy>
</releases>
<snapshots>
<!--支持从此仓库下载release版本-->
<enabled>true</enabled>
<!--从远程仓库检查更新的频率,默认daily,表示每天检查一次,其他可用值:
never——从不检查更新
always——每次构建都检查更新
interval:X——每隔X分钟检查一次更新,X值为整数 -->
<updatePolicy>daily</updatePolicy>
<!--检查校验和文件的策略,默认为warn,maven执行构建时输出警告信息,其他可用值:
fail——遇到校验和错误就让构建失败
ignore——完全忽略校验和错误 -->
<checksumPolicy>warn</checksumPolicy>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>nexus</id>
<url>http://localhost:8081/repository/maven-public/</url>
<releases>
<enabled>true</enabled>
<updatePolicy>daily</updatePolicy>
<checksumPolicy>warn</checksumPolicy>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</profile>
</profiles>
<!-- 需要将 activeProfiles 元素放在末尾,settings字段上方 -->
<activeProfiles>
<!-- 这里是设置激活的 profile元素,“test-nexus”,就是上面的 profile 元素的 id 属性值 -->
<activeProfile>test-nexus</activeProfile>
</activeProfiles>
</settings>
接下来进行一番测试:
-
在 idea 中创建一个 maven 项目 test3,在 test3 的 pom.xml 的配置内容如下:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.ian</groupId> <artifactId>test3</artifactId> <version>1.0.0</version> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> </properties> <dependencies> <!--SpringCloud 官方依赖--> <!--<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> <version>2.5.7</version> </dependency>--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> <version>2.5.7</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.22</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>2.5.7</version> <!--<configuration> <fork>true</fork> <!– 如果没有该配置,devtools不会生效 –> </configuration>--> </plugin> </plugins> </build> <distributionManagement> <repository> <id>nexus-releases</id> <name>Nexus Release Repository</name> <url>http://localhost:8081/repository/maven-releases/</url> </repository> <snapshotRepository> <id>nexus-snapshots</id> <name>Nexus Snapshot Repository</name> <url>http://localhost:8081/repository/maven-snapshots/</url> </snapshotRepository> </distributionManagement> </project>
-
点击“deploy”按钮,等待几秒钟,发现 下面的提示部署成功的消息
BUILD SUCCESS
-
进入到 Nexus 中,发现 test3 这个组件已经上传到 maven-releases 仓库
2.11 创建自己的托管仓库
上面,我们是使用了 nexus 内置的 maven-releases 托管仓库,我们也可以在 Nexus 中创建自己的托管仓库,这个完全可以参照 maven-releases 来创建,只需要换一个仓库名字就行。
- 点击“Create repository”按钮
- 选择“maven2(hosted)”组合类型
- 填写好仓库名称(唯一的),下面选择“Allow redeploy”,即允许重复发版,点击最下面的“Create repository”按钮
- 点击“maven-public”进入 maven-public 仓库的详情页面
- 将刚刚创建的仓库添加到右侧的 Members 成员列表中,让“maven-public”仓库组 能够包含和显示该仓库的内容
- 完工了。
接下来可以像使用 maven-releases 一样 使用这个新创建的 托管仓库了。
2.12 遇到的坑
2.12.1 ERROR1
-
ERROR DESC
pom.xml报错’settings.xml’ has syntax errors -
RCA
- 真的有语法问题,仔细检查 settings.xml,排除语法问题;
- 修改了 settings.xml 文件后,idea没有立刻生效,需要重启 idea。
-
SOLUTION
重启 idea即可。有时候修改了 settings.xml 文件,idea中不会立刻反应过来,需要重启下idea。
2.12.2 ERROR2
-
ERROR DESC
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-deploy-plugin:2.7:deploy (default-deploy) on project test3: Deployment failed: repository element was not specified in the POM inside distributionManagement element or in -DaltDeploymentRepository=id::layout::url parameter -> [Help 1] -
RCA
maven-deploy-plugin:2.7 不会自动读取 settings.xml 中的 仓库配置,需要手动在 pom.xml 文件中定义maven私服的地址。 -
SOLUTION
在 pom.xml 文件中定义maven私服的地址
<distributionManagement>
<repository>
<id>nexus-releases</id>
<name>Nexus Release Repository</name>
<url>http://localhost:8081/repository/maven-releases/</url>
</repository>
<snapshotRepository>
<id>nexus-snapshots</id>
<name>Nexus Snapshot Repository</name>
<url>http://localhost:8081/repository/maven-snapshots/</url>
</snapshotRepository>
</distributionManagement>
2.12.3 ERROR3
-
ERROR DESC
Failed to execute goal org.apache.maven.plugins:maven-deploy-plugin:2.7:deploy (default-deploy) on project test3: Failed to deploy artifacts: Could not transfer artifact com.ian:test3:jar:1.0.0 from/to nexus-releases (http://localhost:8081/repository/maven-releases/): Transfer failed for http://localhost:8081/repository/maven-releases/com/ian/test3/1.0.0/test3-1.0.0.jar 401 Unauthorized -
RCA
Nexus 私服没有授权,需要在 maven 的 settings.xml 中配置用户名密码。 -
SOLUTION
在 maven 的 settings.xml 文件中 添加:
<servers>
<server>
<!-- 注意:这里的配置一定要和 项目 pom.xml 中配置的 distributionManagement.repository.id 属性相同! -->
<id>nexus-releases</id>
<username>zhangsan</username>
<password>1</password>
</server>
<server>
<!-- 注意:这里的配置一定要和 项目 pom.xml 中配置的 distributionManagement.repository.id 属性相同! -->
<id>nexus-snapshots</id>
<username>zhangsan</username>
<password>1</password>
</server>
</servers>
-
扩展
password 属性如何加密呢,可以不使用明文密码吗(如上面代码块中的1
)?
答案是可以的,可以参考官方文档:https://maven.apache.org/guides/mini/guide-encryption.html注意: 执行
mvn --encrypt-master-password <password>
和mvn --encrypt-password <password>
时,两个命令中的<password>
必须相同,并且都是你需要设置的username
的密码,即上面代码块中的1
。否则还是会报401 Unauthorized
错误。
2.12.4 ERROR4
-
ERROR DESC
Failed to execute goal org.apache.maven.plugins:maven-deploy-plugin:2.7:deploy (default-deploy) on project test3: Failed to deploy artifacts: Could not transfer artifact com.ian:test3:jar:1.0.0 from/to nexus-releases (http://localhost:8081/repository/maven-releases/): Transfer failed for http://localhost:8081/repository/maven-releases/com/ian/test3/1.0.0/test3-1.0.0.jar 400 Repository does not allow updating assets: maven-releases -
RCA
maven-releases 仓库不允许重复发版,注意,这个是 maven-releases 仓库的默认设置。 -
SOLUTION
修改 maven-releases 仓库为允许重复发版:
2.12.5 ERROR5
-
ERROR DESC
仓库列表中的某个仓库的“Status”显示为:Online - Remote Auto Blocked and Unavailable
(以下截图中的仓库状态是正常的)
-
RCA
此处并不是 仓库对应的 URL 不可达,我能够正常访问 中央仓库 和 阿里云仓库。原因未知,最后重启 nexus 服务后就好了。 -
SOLUTION
重启 nexus 镜像(实际上就是重启 nexus 服务),命令为:docker restart nexus