写一下这次服务外包经历,主要从我后端所用到的技术出发,而需求和具体实现不会细说。因为我们准备的时间有点晚,4月17号结束,我们是3月22号才开始的,所以说很多我想实现的东西最后也没有去做,这些会在博客中说明,用来督促一下自己,之后去做做完。
一. 技术选型
![架构图 /program/policy/运行架构.png](/svg/loading.min.svg)
微服务架构
技术选型主要是:Nacos + Gateway + Sentinel + OpenFeign
存储层
技术选型主要是:Elasticsearch + Redis + mysql + 七牛云对象存储
工作流
其实并没有配CI/CD,只是用docker-maven-plugin
插件,能直接生成镜像并push到服务器的Register私服库中。然后写了个docker-compose.yml
文件,能一键启动。
后续的话,会将项目部署到k8s上,然后用Jekenis构建一个自动化部署的流水线,并实现金丝雀发布。
监控
目前的监控靠的是druid和hystrix中的监控,我觉得还是很鸡肋的。我用jmeter进行测试的时候,仍旧感觉整个项目的运行情况我是不可见的。
后续部署到k8s后,打算试试kubesphere,它内置了Prometheus实现项目的监控。也准备试试链路追踪的监控方案,如Skywalking。
二、Pom文件相关
这是我项目的总pom文件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
|
<?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>site.koisecret</groupId>
<artifactId>policy</artifactId>
<version>1.0-SNAPSHOT</version>
<modules>
<module>policy-search</module>
<module>policy-auth</module>
<module>policy-gateway</module>
<module>policy-commons</module>
<module>es-operation</module>
</modules>
<name>${project.artifactId}</name>
<packaging>pom</packaging>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring-boot.version>2.3.2.RELEASE</spring-boot.version>
<spring-cloud-alibaba.version>2.2.6.RELEASE</spring-cloud-alibaba.version>
<spring-cloud.version>Hoxton.SR9</spring-cloud.version>
<maven.compiler.version>3.8.1</maven.compiler.version>
<spring.checkstyle.version>0.0.28</spring.checkstyle.version>
<docker.plugin.version>1.0.0</docker.plugin.version>
<docker.registry>10.4.xx.xx:5000</docker.registry>
<docker.namespace>policy</docker.namespace>
<docker.host>http://10.4.xx.xx:2375</docker.host>
<tag>1.0</tag>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring-cloud-alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!--监控-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.18</version>
</dependency>
</dependencies>
<build>
<finalName>${project.name}</finalName>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<pluginManagement>
<plugins>
<!--spring boot 默认插件-->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<!--maven docker 打包插件 -->
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>${docker.plugin.version}</version>
<configuration>
<imageName>${docker.registry}/${docker.namespace}/${project.name}</imageName>
<dockerDirectory>${project.basedir}</dockerDirectory> <!-- 指定 Dockerfile 路径-->
<dockerHost>${docker.host}</dockerHost>
<imageTags>
<imageTag>${tag}</imageTag>
<imageTag>latest</imageTag>
</imageTags>
<forceTags>true</forceTags>
</configuration>
<executions>
<execution>
<id>push</id>
<phase>install</phase>
<goals>
<goal>build</goal>
<goal>push</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<!--代码格式插件,默认使用spring 规则-->
<plugin>
<groupId>io.spring.javaformat</groupId>
<artifactId>spring-javaformat-maven-plugin</artifactId>
<version>${spring.checkstyle.version}</version>
</plugin>
<!--代码编译指定版本插件-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven.compiler.version}</version>
<configuration>
<target>${maven.compiler.target}</target>
<source>${maven.compiler.source}</source>
<encoding>UTF-8</encoding>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>dev</id>
<properties>
<!-- 环境标识,需要与配置文件的名称相对应 -->
<profiles.active>dev</profiles.active>
</properties>
<activation>
<!-- 默认环境 -->
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<profile>
<id>prod</id>
<properties>
<profiles.active>prod</profiles.active>
</properties>
</profile>
<profile>
<id>test</id>
<properties>
<profiles.active>test</profiles.active>
</properties>
</profile>
</profiles>
<repositories>
<repository>
<id>public</id>
<name>aliyun nexus</name>
<url>https://maven.aliyun.com/repository/public/</url>
<releases>
<enabled>true</enabled>
</releases>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>aliyun-plugin</id>
<url>https://maven.aliyun.com/repository/public</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</project>
|
总pom文件解析
-
<modules>
本项目包含的模块信息。
-
<packaging>pom</packaging>
打包方式,总pom文件、包含多个模块的目录中的pom文件,它的打包方式就是pom。单独模块下的打包方式默认是jar
-
<properties>
进行版本管理,方便后续修改版本
-
<dependencyManagement>
依赖管理,这里的依赖不会导入到各个模块之中,只是作为版本管理。当模块的pom文件导入依赖时,可以不指定版本,版本由<dependencyManagement>中指定。
-
<dependencies>
这里的依赖会导入到各个模块中,通常放一些通用的依赖。
-
<build>
放一些构建项目的的插件,最基本的就是 spring-boot-maven-plugin
maven打包插件。
-
<profiles>
用于分隔多套环境,配合maven打包命令、application.yml使用。可以把<build>中的内容放到各个<profile>中,则可以实现选择不同环境就用不同的打包方式。
-
<repositories>和<pluginRepositories>
配置依赖和插件的下载地址。
插件解析
spring-boot-maven-plugin
spring boot 默认插件,用于maven打包。
docker-maven-plugin
docker打包镜像插件,配置好Dockerfle位置、docker服务器所在地址、私服库地址、镜像名称等信息后,可以通过命令行代码直接生成镜像并push到服务器。
maven-assembly-plugin
这个插件本项目中没用到,是用来生成zip包的,很多开源项目会有这种构建方式,可以配合shell脚本启动。
三、 异步
为了加快响应速度,采用多线程的方式异步处理是很有必要的。我还没学过消息队列,目前仅用线程池进行异步处理。
四、 部署
后端部署
主要是docker + docker-compose的方式。
policy-search模块的bootstrap.yml文件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
server:
port: 8001
spring:
application:
name: @artifactId@
profiles:
active: @profiles.active@
cloud:
nacos:
discovery:
server-addr: ${NACOS_HOST:policy-register}:${NACOS_PORT:8848}
namespace: 45735c42-3ca3-4f2c-b7a1-64axxx
config:
server-addr: ${NACOS_HOST:policy-register}:${NACOS_PORT:8848}
file-extension: yml
namespace: 45735c42-3ca3-4f2c-b7a1-64axxx
|
有关policy-search模块的docker-compose.yml文件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
version: "3"
services:
policy-search:
restart: always
container_name: policy-search
image: 10.4.xx.xx:5000/policy/policy-search
environment:
NACOS_HOST: 10.4.xx.xx
NACOS_PORT: 8848
spring.cloud.nacos.discovery.namespace: cfeacfb9-325b-494e-aa2c-axxxxxx
spring.cloud.nacos.discovery.config: cfeacfb9-325b-494e-aa2c-a35xxxxxx
# spring.cloud.nacos.ip: ###
ports:
- 8001:8001
|
${NACOS_HOST:policy-register}
:这个写法的意思是,如果项目启动时传了变量NACOS_HOST
,则使用传来的值;如果没有传值,则用policy-register
作为值传入。policy-register
在host
文件中做了映射,可以理解为localhost.
- environment中,可以传入变量,用于覆盖项目配置文件中的值
- 当用docker启动时,服务注册入nacos的ip地址是172.x.x.x,其他服务器上的服务是找不到该服务的,可以通过
spring.cloud.nacos.ip
指定暴露的ip地址。
前端部署
目前没有使用docker镜像,直接通过ngnix反向代理静态文件的方式,访问前端。但是有个问题,有些页面刷新就无法访问,如“ http://koisecret.site/mine/info
”,而直接从首页“ http://koisecret.site
”点击头像就可以访问。不知道是部署的问题还是前端打包的问题。
后续还会个项目部署一下证书。
五、 测试
目前我只用了Jmeter对几个接口进行了压力测试,观察了一下Jmeter给出的测试报告;用htop
命令观察了一下服务器cpu和内存的使用情况。
后续会用jvisualvm
,学习一下jvm调优过程,并结合链路追踪、Prometheus等,观察服务运行情况。