背景
本文是《Java 后端从小白到大神》修仙系列之框架学习,Java框架之 SpringBoot
框架第五篇
。SpringBoot框架
可以说是微服务的基石,很多复杂的系统几乎都是通过微服务构造而来,若想详细学习请点击首篇博文开始,现在开始学习。
文章概览
- Spring Boot 应用 Docker 打包部署
- 使用 Spring Boot Actuator 监控应用状态
- Spring Boot 整合 Eureka 实现服务注册与发现
- 使用 OpenFeign 实现微服务间调用
- 配置中心与服务发现结合使用实践
1. Spring Boot 应用 Docker 打包部署
一、创建 Dockerfile
第一步:构建 执行 mvn clean package
更新配置
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
|
更新docker-compose.yml,追加task-platform配置
services:
redis:
image: redis:7.2
container_name: redis
ports:
- "6379:6379"
restart: always
rabbitmq:
image: rabbitmq:3-management
container_name: rabbitmq
ports:
- "5672:5672" # 应用连接端口
- "15672:15672" # 管理后台
environment:
RABBITMQ_DEFAULT_USER: guest
RABBITMQ_DEFAULT_PASS: guest
restart: always
nacos:
image: nacos/nacos-server:v2.3.0
platform: linux/amd64
container_name: nacos
ports:
- "8848:8848"
- "9848:9848"
environment:
MODE: standalone
SPRING_DATASOURCE_PLATFORM: mysql
MYSQL_SERVICE_HOST: 192.168.1.3
MYSQL_SERVICE_PORT: 3306
MYSQL_SERVICE_USER: root
MYSQL_SERVICE_DB_PARAM: characterEncoding=utf8&connectTimeout=2000&allowPublicKeyRetrieval=true&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=Asia/Shanghai
MYSQL_SERVICE_PASSWORD: root
MYSQL_SERVICE_DB_NAME: nacos_config
volumes:
- /Users/yutao/Downloads/sourcecode/taskplatform/dev-env/jdbc.properties:/home/nacos/init.d/jdbc.properties
restart: always
task-platform:
image: task-platform:latest
container_name: task-platform
build:
context: .
dockerfile: Dockerfile
ports:
- "8080:8080" # 替换为你的实际端口
depends_on:
- redis
- rabbitmq
- nacos
environment:
# 这些是给 Spring Boot 使用的环境变量(可选,如果你的配置文件中使用了它们)
SPRING_PROFILES_ACTIVE: dev
restart: always
|
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
|
更新application.properties配置文件
# Server
server.port=8080
# 应用名称
spring.application.name=task-platform
# 配置导入:使用 Nacos 作为配置中心(Spring Boot 3.2 推荐方式)
spring.config.import=optional:nacos:nacos:8848
# Nacos 配置
spring.cloud.nacos.config.server-addr=nacos:8848
spring.cloud.nacos.config.file-extension=yaml
spring.cloud.nacos.config.group=DEFAULT_GROUP
spring.cloud.nacos.config.namespace=public
# Nacos 扩展配置文件:Redis、RabbitMQ、定时任务
spring.cloud.nacos.config.extension-configs[0].dataId=redis-config.yaml
spring.cloud.nacos.config.extension-configs[0].group=DEFAULT_GROUP
spring.cloud.nacos.config.extension-configs[0].refresh=true
spring.cloud.nacos.config.extension-configs[1].dataId=mq-config.yaml
spring.cloud.nacos.config.extension-configs[1].group=DEFAULT_GROUP
spring.cloud.nacos.config.extension-configs[1].refresh=true
spring.cloud.nacos.config.extension-configs[2].dataId=task-platform.yaml
spring.cloud.nacos.config.extension-configs[2].group=DEFAULT_GROUP
spring.cloud.nacos.config.extension-configs[2].refresh=true
# Redis 配置文件
spring.data.redis.host=redis
spring.data.redis.port=6379
spring.cache.type=redis
spring.cache.redis.time-to-live=300000
# 日志级别
logging.level.root=info
logging.level.com.yutao=debug
# 暴露 actuator 所有端点
management.endpoints.web.exposure.include=*
# 显示详细健康信息
management.endpoint.health.show-details=always
# 启用所有指标
management.metrics.enable.all=true
# 健康检查磁盘空间设置
management.health.diskspace.path=/
management.health.diskspace.threshold=10MB
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
更新bootstrap.properties配置文件
spring.application.name=task-platform
spring.cloud.nacos.config.server-addr=nacos:8848
spring.cloud.nacos.config.file-extension=yaml
spring.cloud.nacos.config.namespace=public
spring.cloud.nacos.config.group=DEFAULT_GROUP
# Nacos 扩展配置文件:Redis、RabbitMQ、定时任务
spring.cloud.nacos.config.extension-configs[0].dataId=redis-config.yaml
spring.cloud.nacos.config.extension-configs[0].group=DEFAULT_GROUP
spring.cloud.nacos.config.extension-configs[0].refresh=true
spring.cloud.nacos.config.extension-configs[1].dataId=mq-config.yaml
spring.cloud.nacos.config.extension-configs[1].group=DEFAULT_GROUP
spring.cloud.nacos.config.extension-configs[1].refresh=true
spring.cloud.nacos.config.extension-configs[2].dataId=task-platform.yaml
spring.cloud.nacos.config.extension-configs[2].group=DEFAULT_GROUP
spring.cloud.nacos.config.extension-configs[2].refresh=true
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
pom文件中需要添加如下插件
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
|
第二步:拷贝 taskplatform-1.0-SNAPSHOT.jar 拷贝到dev-evn目录下,命名为 app.jar
1
|
cp /Users/yutao/Downloads/sourcecode/taskplatform/target/taskplatform-1.0-SNAPSHOT.jar /Users/yutao/Downloads/sourcecode/taskplatform/dev-evn/app.jar
|
第三步:在根目录下创建Dockerfile文件,内容如下:
1
2
3
4
5
6
7
8
9
10
11
|
# 使用官方 OpenJDK 21 的基础镜像
FROM eclipse-temurin:21-jdk
# 将 jar 文件复制进镜像中
ADD app.jar /app.jar
# 暴露端口(如果你监听的是 8080)
EXPOSE 8080
# 启动命令
ENTRYPOINT ["java", "-jar", "/app.jar"]
|
二、构建镜像并运行容器
第四步:构建 Docker 镜像
在 Dockerfile
和 app.jar
所在的目录执行,-t task-platform-app
是你自定义的镜像名称,.
表示 Dockerfile 当前目录。
1
2
|
cd /Users/yutao/Downloads/sourcecode/taskplatform/dev-env
docker build -t task-platform .
|
第五步:运行容器
构建完成后,运行容器:
1
|
docker run -d --name task-platform -p 8080:8080 task-platform
|
参数说明:
-d
:后台运行容器;
-p 8080:8080
:将容器内部的 8080 端口映射到你本地 8080;
--name task-platform
:容器命名为 task-platform
;
task-platform
:前面构建的镜像名。
三、验证运行情况
第六步:验证运行情况
-
查看日志:
1
|
docker logs -f task-platform
|
-
访问接口:
浏览器访问或使用 curl:
http://localhost:8080/actuator/health
http://localhost:8080/actuator/info
四、常用命令补充
常用命令
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
|
查看镜像
docker images
查看容器
docker ps -a
停止并删除容器
docker stop task-platform
docker rm task-platform
查看日志
docker logs -f task-platform
启动容器+重新构建镜像
docker compose up -d --build
启动容器
docker compose up -d
停止容器
docker compose down
重启单个容器
docker-compose restart nacos
进入nacos容器
docker exec -it nacos /bin/sh
进入redis容器
docker exec -it redis redis-cli
删除镜像
docker rmi task-platform-app
查看指定容器
docker ps -a --filter ancestor=task-platform
查看 JAR 包中的 MANIFEST.MF 文件内容
jar tf target/taskplatform-1.0-SNAPSHOT.jar | grep META-INF/MANIFEST.MF
不解压缩文件,只是输出指定文件的内容
unzip -p target/taskplatform-1.0-SNAPSHOT.jar META-INF/MANIFEST.MF
|
2. 使用 Spring Boot Actuator 监控应用状态
一、引入依赖
1
2
3
4
|
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
|
二、配置开启端点
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
management:
endpoints:
web:
exposure:
include: '*'
endpoint:
health:
show-details: always
metrics:
enable:
all: true
health:
diskspace:
path: /
threshold: 10MB
|
三、常用端点
健康检查(磁盘、内存、依赖等)
http://localhost:8080/actuator/health
应用版本、说明等元信息
http://localhost:8080/actuator/info
JVM、线程、GC、HTTP 请求统计等
http://localhost:8080/actuator/metrics
Spring 管理的所有 Bean 列表
http://localhost:8080/actuator/beans
当前应用所有环境变量(支持搜索)
http://localhost:8080/actuator/env
当前所有定时任务(如果启用)
http://localhost:8080/actuator/scheduledtasks
单项指标(如 JVM 内存使用)
http://localhost:8080/actuator/metrics/jvm.memory.used
四、添加代码
因为 /actuator/info
的数据来源是:info.*
配置,InfoEndpoint
是一个 Actuator 提供的端点,默认只会扫描 本地配置环境(即 application.properties
/ application.yaml
)中的 info.*
,这些配置会在 Spring Boot 启动阶段通过 InfoPropertiesInfoContributor
注册到 InfoEndpoint 中,而这一步发生在 Spring Boot 应用早期阶段(Environment 初始化之后,Context refresh 之前),问题在于:Nacos 配置加载比这个阶段晚,所以 Nacos 中的 info.app.name
是不会被 Spring Boot 自动识别并注册到 /actuator/info
里的,/actuator/health
、/actuator/metrics
等属于运行时动态端点/actuator/health
是通过一组 HealthIndicator
动态计算出来的,/actuator/metrics
是基于 Micrometer 收集的运行时指标,实时监控 JVM、系统、线程、GC 等,它们的数据来源是程序运行期间不断采集、计算得到的,并不依赖某个配置文件中的固定值,因此不受 Nacos 加载时机的影响。
桥接info配置属性,从nacos动态加载
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
|
package com.yutao.config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.actuate.info.Info;
import org.springframework.boot.actuate.info.InfoContributor;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
@RefreshScope
@Component
public class CustomInfoContributor implements InfoContributor {
private static final Logger logger = LoggerFactory.getLogger(CustomInfoContributor.class);
private final Environment environment;
public CustomInfoContributor(Environment environment) {
this.environment = environment;
}
@Override
public void contribute(Info.Builder builder) {
String name = environment.getProperty("info.app.name");
String version = environment.getProperty("info.app.version");
String description = environment.getProperty("info.app.description");
logger.debug("App Name: {}", name);
logger.debug("App Version: {}", version);
logger.debug("App Description: {}", description);
builder.withDetail("app",
java.util.Map.of(
"name", name,
"version", version,
"description", description
)
);
}
}
|
1
2
3
4
5
6
7
8
|
在nacos的task-platform.yaml文件中添加如下内容:
info:
app:
name: task-platform
version: 1.0.0
description: 任务调度系统
|
3. Spring Boot 整合 Eureka 实现服务注册与发现
一、创建 Eureka Server
1
2
3
4
|
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
|
1
2
3
|
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApp {}
|
二、注册客户端
1
2
3
4
|
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
|
1
2
3
4
5
6
7
|
spring:
application:
name: service-client
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
|
4. 使用 OpenFeign 实现微服务间调用
一、引入依赖
1
2
3
4
|
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
|
二、开启 Feign
1
2
3
|
@SpringBootApplication
@EnableFeignClients
public class App {}
|
三、定义 Feign 接口
1
2
3
4
5
|
@FeignClient(name = "user-service")
public interface UserClient {
@GetMapping("/user/{id}")
User getUser(@PathVariable("id") Long id);
}
|
5. 配置中心与服务发现结合使用实践
一、将配置中心与注册中心合并(如 Nacos)
Nacos 同时支持配置中心与注册中心:
1
2
3
4
5
6
7
8
9
|
spring:
application:
name: user-service
cloud:
nacos:
config:
server-addr: localhost:8848
discovery:
server-addr: localhost:8848
|
二、服务调用整合 Feign 与配置属性
1
2
3
4
5
|
@FeignClient(name = "order-service")
public interface OrderClient {
@GetMapping("/orders/{uid}")
List<Order> getOrders(@PathVariable("uid") Long userId);
}
|
总结
SpringBoot 框架是微服务生态的基石,必知必会。