运行中的 SpringBoot
认识 Spring Boot 的各类 Actuator Endpoint
Actuator
目的:监控并管理应用程序
访问方式
1HTTP
2JMX
依赖
1<dependency>
2 <groupId>org.springframework.boot</groupId>
3 <artifactId>spring-boot-starter-actuator</artifactId>
4 </dependency>
一些常用的 Endpoint
如何访问 Actuator Endpoint
HTTP 访问
1/actuator/<Actuator ID>
端口与路径(配置 Actuator 发布的端口 和 应用程序分开,实现应用与管理的隔离,例如:应用发布在 8080 端口,Actuator 相关的所有 Endpoint 发布在 8090 端口,前段 nginx 请求转发给 8080 端口,外部请求不允许直接访问 8090 端口,起到了保护作用。)
1• management.server.address=
2• management.server.port=
3• management.endpoints.web.base-path=/actuator
4• management.endpoints.web.path-mapping.<id>=路径
开启 Endpoint
1• management.endpoint.<Actuator ID>.enabled=true
2• management.endpoints.enabled-by-default=false
暴露 Endpoint (按需发布 Endpoints)
1• management.endpoints.jmx.exposure.exclude=
2• management.endpoints.jmx.exposure.include=*
3• management.endpoints.web.exposure.exclude=
4• management.endpoints.web.exposure.include=info, health
手动定制自己的 Health Indicator
目的
- 检查应用程序的运行状态
状态
1• DOWN - 503
2• OUT_OF_SERVICE - 503
3• UP - 200
4• UNKNOWN - 200
机制
- 通过 HealthIndicatorRegistry 收集信息
- HealthIndicator 实现具体检查逻辑
配置项
1• management.health.defaults.enabled=true|false
2• management.health.<id>.enabled=true
3• management.endpoint.health.show-details=never|when-authorized|always
Spring Boot 自带的 Health Indicator
自定义 Health Indicator
步骤
1• 实现 HealthIndicator 接口
2• 根据自定义检查逻辑返回对应 Health 状态: Health 中包含状态和详细描述信息
依赖
1<dependency>
2 <groupId>org.springframework.boot</groupId>
3 <artifactId>spring-boot-starter-actuator</artifactId>
4 </dependency>
application.properties
1spring.jpa.hibernate.ddl-auto=none
2spring.jpa.properties.hibernate.show_sql=true
3spring.jpa.properties.hibernate.format_sql=true
4
5# 发布所有endpoints
6management.endpoints.web.exposure.include=*
7management.endpoint.health.show-details=always
8
9info.app.author=DigitalSonic
10info.app.encoding=@project.build.sourceEncoding@
CoffeeIndicator
1package geektime.spring.springbucks.waiter.support;
2
3import geektime.spring.springbucks.waiter.service.CoffeeService;
4import org.springframework.beans.factory.annotation.Autowired;
5import org.springframework.boot.actuate.health.Health;
6import org.springframework.boot.actuate.health.HealthIndicator;
7import org.springframework.stereotype.Component;
8
9@Component
10public class CoffeeIndicator implements HealthIndicator {
11 @Autowired
12 private CoffeeService coffeeService;
13
14 @Override
15 public Health health() {
16 long count = coffeeService.getCoffeeCount();
17 Health health;
18 if (count > 0) {
19 health = Health.up()
20 .withDetail("count", count)
21 .withDetail("message", "We have enough coffee.")
22 .build();
23 } else {
24 health = Health.down()
25 .withDetail("count", 0)
26 .withDetail("message", "We are out of coffee.")
27 .build();
28 }
29 return health;
30 }
31}
测试
1// http://localhost:8080/actuator
2
3{
4 "_links": {
5 "self": {
6 "href": "http://localhost:8080/actuator",
7 "templated": false
8 },
9 "auditevents": {
10 "href": "http://localhost:8080/actuator/auditevents",
11 "templated": false
12 },
13 "beans": {
14 "href": "http://localhost:8080/actuator/beans",
15 "templated": false
16 },
17 "caches-cache": {
18 "href": "http://localhost:8080/actuator/caches/{cache}",
19 "templated": true
20 },
21 "caches": {
22 "href": "http://localhost:8080/actuator/caches",
23 "templated": false
24 },
25 "health-component-instance": {
26 "href": "http://localhost:8080/actuator/health/{component}/{instance}",
27 "templated": true
28 },
29 "health": {
30 "href": "http://localhost:8080/actuator/health",
31 "templated": false
32 },
33 "health-component": {
34 "href": "http://localhost:8080/actuator/health/{component}",
35 "templated": true
36 },
37 "conditions": {
38 "href": "http://localhost:8080/actuator/conditions",
39 "templated": false
40 },
41 "configprops": {
42 "href": "http://localhost:8080/actuator/configprops",
43 "templated": false
44 },
45 "env": {
46 "href": "http://localhost:8080/actuator/env",
47 "templated": false
48 },
49 "env-toMatch": {
50 "href": "http://localhost:8080/actuator/env/{toMatch}",
51 "templated": true
52 },
53 "info": {
54 "href": "http://localhost:8080/actuator/info",
55 "templated": false
56 },
57 "loggers": {
58 "href": "http://localhost:8080/actuator/loggers",
59 "templated": false
60 },
61 "loggers-name": {
62 "href": "http://localhost:8080/actuator/loggers/{name}",
63 "templated": true
64 },
65 "heapdump": {
66 "href": "http://localhost:8080/actuator/heapdump",
67 "templated": false
68 },
69 "threaddump": {
70 "href": "http://localhost:8080/actuator/threaddump",
71 "templated": false
72 },
73 "prometheus": {
74 "href": "http://localhost:8080/actuator/prometheus",
75 "templated": false
76 },
77 "metrics-requiredMetricName": {
78 "href": "http://localhost:8080/actuator/metrics/{requiredMetricName}",
79 "templated": true
80 },
81 "metrics": {
82 "href": "http://localhost:8080/actuator/metrics",
83 "templated": false
84 },
85 "scheduledtasks": {
86 "href": "http://localhost:8080/actuator/scheduledtasks",
87 "templated": false
88 },
89 "httptrace": {
90 "href": "http://localhost:8080/actuator/httptrace",
91 "templated": false
92 },
93 "mappings": {
94 "href": "http://localhost:8080/actuator/mappings",
95 "templated": false
96 }
97 }
98}
99
100// http://localhost:8080/actuator/info
101{
102 "app": {
103 "author": "DigitalSonic",
104 "encoding": "UTF-8"
105 }
106}
107
108// http://localhost:8080/actuator/health
109{
110 "status": "UP",
111 "details": {
112 "coffeeIndicator": {
113 "status": "UP",
114 "details": {
115 "count": 5,
116 "message": "We have enough coffee."
117 }
118 },
119 "db": {
120 "status": "UP",
121 "details": {
122 "database": "H2",
123 "hello": 1
124 }
125 },
126 "diskSpace": {
127 "status": "UP",
128 "details": {
129 "total": 256059109376,
130 "free": 175957565440,
131 "threshold": 10485760
132 }
133 }
134 }
135}
通过 Micrometer 获取运行数据
在应用运行过程中需要收集一些度量指标:操作系统、JVM、应用业务指标 等……
SpringBoot2.X 中的 Micrometer 可以完成度量指标收集。Micrometer 为主流的监控系统提供了一些 instrumentation clients (探针客户端),允许向 JVM 中插入这些探针。同时它做了一层抽象,所以并不需要关心底层的这些探针的具体实现,可以把 Micrometer 看作是 度量界 的 SLF4J。
认识 Micrometer
特性
- 多维度度量
1• 支持 Tag
- 预置大量探针
1• 缓存、类加载器、GC、CPU 利用率、线程池……
- 与 Spring 深度整合
1• webMVC
2• webFlux
3• restTemplate
4• webClient
支持多种监控系统
- Dimensional (维度)
1AppOptics, Atlas, Azure Monitor, Cloudwatch, Datadog, Datadog StatsD, Dynatrace, Elastic, Humio, Inflflux, KairosDB,New Relic, Prometheus, SignalFx, Sysdig StatsD, Telegraf,StatsD, Wavefront
- Hierarchical(分层)
1Graphite, Ganglia, JMX, Etsy StatsD
一些核心度量指标
核心接口
- Meter
内置实现
- Gauge, TimeGauge
- Timer, LongTaskTimer, FunctionTimer
- Counter, FunctionCounter
- DistributionSummary
Micrometer in Spring Boot 2.x
⼀些 URL
1• /actuator/metrics
2• /actuator/prometheus
⼀些配置项
1• management.metrics.export.*
2• management.metrics.tags.*
3• management.metrics.enable.*
4• management.metrics.distribution.*
5• management.metrics.web.server.auto-time-requests
核心度量项
1JVM、CPU、⽂件句柄数、⽇志、启动时间
其他度量项
1• Spring MVC、Spring WebFlux
2• Tomcat、Jersey JAX-RS
3• RestTemplate、WebClient
4• 缓存、数据源、Hibernate
5• Kafka、RabbitMQ
自定义度量指标
1• 通过 MeterRegistry 注册 Meter
2• 提供 MeterBinder Bean 让 Spring Boot 自动绑定
3• 通过 MeterFilter 进行定制
CoffeeOrderService
1package geektime.spring.springbucks.waiter.service;
2
3import geektime.spring.springbucks.waiter.model.Coffee;
4import geektime.spring.springbucks.waiter.model.CoffeeOrder;
5import geektime.spring.springbucks.waiter.model.OrderState;
6import geektime.spring.springbucks.waiter.repository.CoffeeOrderRepository;
7import io.micrometer.core.instrument.Counter;
8import io.micrometer.core.instrument.MeterRegistry;
9import io.micrometer.core.instrument.binder.MeterBinder;
10import lombok.extern.slf4j.Slf4j;
11import org.springframework.beans.factory.annotation.Autowired;
12import org.springframework.stereotype.Service;
13import org.springframework.transaction.annotation.Transactional;
14
15import java.util.ArrayList;
16import java.util.Arrays;
17
18@Service
19@Transactional
20@Slf4j
21public class CoffeeOrderService implements MeterBinder {
22 @Autowired
23 private CoffeeOrderRepository orderRepository;
24
25 //计数器(监控订单总量)
26 private Counter orderCounter = null;
27
28 public CoffeeOrder get(Long id) {
29 return orderRepository.getOne(id);
30 }
31
32 public CoffeeOrder createOrder(String customer, Coffee...coffee) {
33 CoffeeOrder order = CoffeeOrder.builder()
34 .customer(customer)
35 .items(new ArrayList<>(Arrays.asList(coffee)))
36 .state(OrderState.INIT)
37 .build();
38 CoffeeOrder saved = orderRepository.save(order);
39 log.info("New Order: {}", saved);
40 //每次创建订单 +1
41 orderCounter.increment();
42 return saved;
43 }
44
45 public boolean updateState(CoffeeOrder order, OrderState state) {
46 if (state.compareTo(order.getState()) <= 0) {
47 log.warn("Wrong State order: {}, {}", state, order.getState());
48 return false;
49 }
50 order.setState(state);
51 orderRepository.save(order);
52 log.info("Updated Order: {}", order);
53 return true;
54 }
55
56 @Override
57 public void bindTo(MeterRegistry meterRegistry) {
58 this.orderCounter = meterRegistry.counter("order.count");
59 }
60}
测试
1// http://localhost:8080/actuator/metrics/order.count
2{
3 "name": "order.count",
4 "description": null,
5 "baseUnit": null,
6 "measurements": [
7 {
8 "statistic": "COUNT",
9 "value": 2.0
10 }
11 ],
12 "availableTags": [
13 ]
14}
15
16//访问prometheus
17http://localhost:8080/actuator/prometheus
18order_count_total 2.0
19
20//Micrometer 对 spring 有很好的支持
21// http://localhost:8080/actuator/metrics
22
23{
24 "names": [
25 "jvm.threads.states",
26 "http.server.requests",
27 "jdbc.connections.active",
28 "jvm.gc.memory.promoted",
29 "jvm.memory.max",
30 "jvm.memory.used",
31 "jvm.gc.max.data.size",
32 "jdbc.connections.max",
33 "jdbc.connections.min",
34 "jvm.memory.committed",
35 "system.cpu.count",
36 "logback.events",
37 "tomcat.global.sent",
38 "jvm.gc.pause",
39 "jvm.buffer.memory.used",
40 "tomcat.sessions.created",
41 "jvm.threads.daemon",
42 "system.cpu.usage",
43 "jvm.gc.memory.allocated",
44 "tomcat.global.request.max",
45 "hikaricp.connections.idle",
46 "hikaricp.connections.pending",
47 "tomcat.global.request",
48 "tomcat.sessions.expired",
49 "hikaricp.connections",
50 "jvm.threads.live",
51 "jvm.threads.peak",
52 "tomcat.global.received",
53 "hikaricp.connections.active",
54 "hikaricp.connections.creation",
55 "process.uptime",
56 "order.count",
57 "tomcat.sessions.rejected",
58 "process.cpu.usage",
59 "tomcat.threads.config.max",
60 "jvm.classes.loaded",
61 "hikaricp.connections.max",
62 "hikaricp.connections.min",
63 "jvm.classes.unloaded",
64 "tomcat.global.error",
65 "tomcat.sessions.active.current",
66 "tomcat.sessions.alive.max",
67 "jvm.gc.live.data.size",
68 "hikaricp.connections.usage",
69 "tomcat.threads.current",
70 "hikaricp.connections.timeout",
71 "jvm.buffer.count",
72 "jvm.buffer.total.capacity",
73 "tomcat.sessions.active.max",
74 "hikaricp.connections.acquire",
75 "tomcat.threads.busy",
76 "process.start.time"
77 ]
78}
79
80
81//SpringMVC 请求统计 (SpringBoot 和 Micrometer 一起实现的)
82//http://localhost:8080/actuator/metrics/http.server.requests
83
84{
85 "name": "http.server.requests",
86 "description": null,
87 "baseUnit": "seconds",
88 "measurements": [
89 {
90 "statistic": "COUNT",
91 "value": 9.0
92 },
93 {
94 "statistic": "TOTAL_TIME",
95 "value": 0.707585
96 },
97 {
98 "statistic": "MAX",
99 "value": 0.0015951
100 }
101 ],
102 "availableTags": [
103 {
104 "tag": "exception",
105 "values": [
106 "None"
107 ]
108 },
109 {
110 "tag": "method",
111 "values": [
112 "GET"
113 ]
114 },
115 {
116 "tag": "uri",
117 "values": [
118 "/actuator/metrics/{requiredMetricName}",
119 "/actuator",
120 "/actuator/prometheus",
121 "/actuator/metrics"
122 ]
123 },
124 {
125 "tag": "outcome",
126 "values": [
127 "CLIENT_ERROR",
128 "SUCCESS"
129 ]
130 },
131 {
132 "tag": "status",
133 "values": [
134 "404",
135 "200"
136 ]
137 }
138 ]
139}
Spring Boot Admin
目的:为 Spring Boot 应用程序提供⼀套管理界面
主要功能
- 集中展示应用程序 Actuator 相关的内容
- 变更通知
服务端
依赖
1<?xml version="1.0" encoding="UTF-8"?>
2<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4 <modelVersion>4.0.0</modelVersion>
5 <parent>
6 <groupId>org.springframework.boot</groupId>
7 <artifactId>spring-boot-starter-parent</artifactId>
8 <version>2.1.3.RELEASE</version>
9 <relativePath/> <!-- lookup parent from repository -->
10 </parent>
11 <groupId>geektime.spring.boot</groupId>
12 <artifactId>sba-server</artifactId>
13 <version>0.0.1-SNAPSHOT</version>
14 <name>sba-server</name>
15 <description>Demo project for Spring Boot</description>
16
17 <properties>
18 <java.version>1.8</java.version>
19 <spring-boot-admin.version>2.1.3</spring-boot-admin.version>
20 </properties>
21
22 <dependencies>
23 <dependency>
24 <groupId>org.springframework.boot</groupId>
25 <artifactId>spring-boot-starter-security</artifactId>
26 </dependency>
27 <dependency>
28 <groupId>org.springframework.boot</groupId>
29 <artifactId>spring-boot-starter-web</artifactId>
30 </dependency>
31 <dependency>
32 <groupId>de.codecentric</groupId>
33 <artifactId>spring-boot-admin-starter-server</artifactId>
34 </dependency>
35
36 <dependency>
37 <groupId>org.springframework.boot</groupId>
38 <artifactId>spring-boot-starter-test</artifactId>
39 <scope>test</scope>
40 </dependency>
41 <dependency>
42 <groupId>org.springframework.security</groupId>
43 <artifactId>spring-security-test</artifactId>
44 <scope>test</scope>
45 </dependency>
46 </dependencies>
47
48 <dependencyManagement>
49 <dependencies>
50 <dependency>
51 <groupId>de.codecentric</groupId>
52 <artifactId>spring-boot-admin-dependencies</artifactId>
53 <version>${spring-boot-admin.version}</version>
54 <type>pom</type>
55 <scope>import</scope>
56 </dependency>
57 </dependencies>
58 </dependencyManagement>
59
60 <build>
61 <plugins>
62 <plugin>
63 <groupId>org.springframework.boot</groupId>
64 <artifactId>spring-boot-maven-plugin</artifactId>
65 </plugin>
66 </plugins>
67 </build>
68</project>
application.properties
1spring.application.name=sba-server
2server.port=8080
3
4spring.security.user.name=geektime
5spring.security.user.password=sba-server-password
SbaServerApplication(启动类)
1package geektime.spring.boot.sba;
2
3import de.codecentric.boot.admin.server.config.AdminServerProperties;
4import de.codecentric.boot.admin.server.config.EnableAdminServer;
5import org.springframework.beans.factory.annotation.Autowired;
6import org.springframework.boot.SpringApplication;
7import org.springframework.boot.autoconfigure.SpringBootApplication;
8import org.springframework.security.config.annotation.web.builders.HttpSecurity;
9import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
10import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
11import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
12
13@SpringBootApplication
14@EnableAdminServer
15public class SbaServerApplication extends WebSecurityConfigurerAdapter {
16 @Autowired
17 private AdminServerProperties adminServerProperties;
18
19 public static void main(String[] args) {
20 SpringApplication.run(SbaServerApplication.class, args);
21 }
22
23 @Override
24 protected void configure(HttpSecurity http) throws Exception {
25 String adminContextPath = adminServerProperties.getContextPath();
26
27 SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler();
28 successHandler.setTargetUrlParameter("redirectTo");
29 successHandler.setDefaultTargetUrl(adminContextPath + "/");
30
31 http.authorizeRequests()
32 .antMatchers(adminContextPath + "/assets/**").permitAll()
33 .antMatchers(adminContextPath + "/login").permitAll()
34 .anyRequest().authenticated()
35 .and()
36 .formLogin().loginPage(adminContextPath + "/login").successHandler(successHandler).and()
37 .logout().logoutUrl(adminContextPath + "/logout").and()
38 .httpBasic().and()
39 .csrf()
40 .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
41 .ignoringAntMatchers(
42 adminContextPath + "/instances",
43 adminContextPath + "/actuator/**"
44 );
45 }
46}
测试
1http://localhost:8080/login
2
3geektime
4sba-server-password
客户端
依赖
1<?xml version="1.0" encoding="UTF-8"?>
2<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4 <modelVersion>4.0.0</modelVersion>
5 <parent>
6 <groupId>org.springframework.boot</groupId>
7 <artifactId>spring-boot-starter-parent</artifactId>
8 <version>2.1.3.RELEASE</version>
9 <relativePath/> <!-- lookup parent from repository -->
10 </parent>
11 <groupId>geektime.spring.boot</groupId>
12 <artifactId>sba-client</artifactId>
13 <version>0.0.1-SNAPSHOT</version>
14 <name>sba-client</name>
15 <description>Demo project for Spring Boot</description>
16
17 <properties>
18 <java.version>1.8</java.version>
19 <spring-boot-admin.version>2.1.3</spring-boot-admin.version>
20 </properties>
21
22 <dependencies>
23 <dependency>
24 <groupId>org.springframework.boot</groupId>
25 <artifactId>spring-boot-starter-actuator</artifactId>
26 </dependency>
27 <dependency>
28 <groupId>org.springframework.boot</groupId>
29 <artifactId>spring-boot-starter-security</artifactId>
30 </dependency>
31 <dependency>
32 <groupId>org.springframework.boot</groupId>
33 <artifactId>spring-boot-starter-web</artifactId>
34 </dependency>
35 <dependency>
36 <groupId>de.codecentric</groupId>
37 <artifactId>spring-boot-admin-starter-client</artifactId>
38 </dependency>
39
40 <dependency>
41 <groupId>org.springframework.boot</groupId>
42 <artifactId>spring-boot-starter-test</artifactId>
43 <scope>test</scope>
44 </dependency>
45 <dependency>
46 <groupId>org.springframework.security</groupId>
47 <artifactId>spring-security-test</artifactId>
48 <scope>test</scope>
49 </dependency>
50 </dependencies>
51
52 <dependencyManagement>
53 <dependencies>
54 <dependency>
55 <groupId>de.codecentric</groupId>
56 <artifactId>spring-boot-admin-dependencies</artifactId>
57 <version>${spring-boot-admin.version}</version>
58 <type>pom</type>
59 <scope>import</scope>
60 </dependency>
61 </dependencies>
62 </dependencyManagement>
63
64 <build>
65 <plugins>
66 <plugin>
67 <groupId>org.springframework.boot</groupId>
68 <artifactId>spring-boot-maven-plugin</artifactId>
69 </plugin>
70 </plugins>
71 </build>
72
73</project>
application.properties
1spring.application.name=sba-client
2server.port=8081
3
4management.endpoints.web.exposure.include=*
5
6info.demo.name=Spring Boot Admin Client Demo
7
8spring.security.user.name=geektime
9spring.security.user.password=sba-client-password
10
11spring.boot.admin.client.url=http://localhost:8080
12spring.boot.admin.client.username=geektime
13spring.boot.admin.client.password=sba-server-password
14
15spring.boot.admin.client.instance.metadata.user.name=${spring.security.user.name}
16spring.boot.admin.client.instance.metadata.user.password=${spring.security.user.password}
如何定制 Web 容器的运行参数
内嵌 Web 容器
1• spring-boot-starter-tomcat
2• spring-boot-starter-jetty
3• spring-boot-starter-undertow
4• spring-boot-starter-reactor-netty
修改容器配置
1# 端口
2server.port
3server.address
4
5# 压缩
6server.compression.enabled
7server.compression.min-response-size
8server.compression.mime-types
9
10# Tomcat 特定配置
11server.tomcat.max-connections=10000
12server.tomcat.max-http-post-size=2MB
13server.tomcat.max-swallow-size=2MB
14server.tomcat.max-threads=200
15server.tomcat.min-spare-threads=10
16
17# 修改容器配置
18server.error.path=/error
19server.error.include-exception=false
20server.error.include-stacktrace=never
21server.error.whitelabel.enabled=true
22
23# 其他
24server.use-forward-headers
25server.servlet.session.timeout
配置方式示例:
application.properties
1spring.jpa.hibernate.ddl-auto=none
2spring.jpa.properties.hibernate.show_sql=true
3spring.jpa.properties.hibernate.format_sql=true
4
5#server.compression.enabled=true
6#server.compression.min-response-size=512B
7
8server.error.include-stacktrace=always
9server.error.include-exception=true
编程方式修改容器配置
WebServerFactoryCustomizer
1• TomcatServletWebServerFactory
2• JettyServletWebServerFactory
3• UndertowServletWebServerFactory
变成方式示例:
WaiterServiceApplication
1package geektime.spring.springbucks.waiter;
2
3import com.fasterxml.jackson.datatype.hibernate5.Hibernate5Module;
4import geektime.spring.springbucks.waiter.controller.PerformanceInteceptor;
5import org.springframework.boot.SpringApplication;
6import org.springframework.boot.autoconfigure.SpringBootApplication;
7import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
8import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
9import org.springframework.boot.web.server.Compression;
10import org.springframework.boot.web.server.WebServerFactoryCustomizer;
11import org.springframework.cache.annotation.EnableCaching;
12import org.springframework.context.annotation.Bean;
13import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
14import org.springframework.util.unit.DataSize;
15import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
16import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
17
18import java.util.TimeZone;
19
20@SpringBootApplication
21@EnableJpaRepositories
22@EnableCaching
23public class WaiterServiceApplication implements WebMvcConfigurer,
24 WebServerFactoryCustomizer<TomcatServletWebServerFactory> {
25
26 public static void main(String[] args) {
27 SpringApplication.run(WaiterServiceApplication.class, args);
28 }
29
30 /**
31 * 编程方式配置 GZIP压缩
32 * @param factory
33 */
34 @Override
35 public void customize(TomcatServletWebServerFactory factory) {
36 Compression compression = new Compression();
37 compression.setEnabled(true);
38 compression.setMinResponseSize(DataSize.ofBytes(512));
39 factory.setCompression(compression);
40 }
41
42 @Override
43 public void addInterceptors(InterceptorRegistry registry) {
44 registry.addInterceptor(new PerformanceInteceptor())
45 .addPathPatterns("/coffee/**").addPathPatterns("/order/**");
46 }
47
48 @Bean
49 public Hibernate5Module hibernate5Module() {
50 return new Hibernate5Module();
51 }
52
53 @Bean
54 public Jackson2ObjectMapperBuilderCustomizer jacksonBuilderCustomizer() {
55 return builder ->
56 builder.indentOutput(true)
57 .timeZone(TimeZone.getTimeZone("Asia/Shanghai"));
58 }
59}
构建 Docker 镜像
Docker 镜像
- 镜像是静态的只读模版
- 镜像中包含构建 Docker 容器的指令
- 镜像是分层的
- 通过 Dockerfile 来创建镜像
Dockerfile
通过 Maven 构建 Docker 镜像
准备工作
- 提供一个 Dockerfile
1FROM java:8
2EXPOSE 8080
3ARG JAR_FILE
4ADD target/${JAR_FILE} /waiter-service.jar
5ENTRYPOINT ["java", "-jar","/waiter-service.jar"]
- 配置 dockerfile-maven-plugin 插件
pom.xml
1<?xml version="1.0" encoding="UTF-8"?>
2<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4 <modelVersion>4.0.0</modelVersion>
5 <parent>
6 <groupId>org.springframework.boot</groupId>
7 <artifactId>spring-boot-starter-parent</artifactId>
8 <version>2.1.3.RELEASE</version>
9 <relativePath/> <!-- lookup parent from repository -->
10 </parent>
11 <groupId>geektime.spring.springbucks</groupId>
12 <artifactId>waiter-service</artifactId>
13 <version>0.0.1-SNAPSHOT</version>
14 <name>waiter-service</name>
15 <description>Demo project for Spring Boot</description>
16
17 <properties>
18 <java.version>1.8</java.version>
19 <docker.image.prefix>springbucks</docker.image.prefix>
20 </properties>
21
22 <dependencies>
23 <dependency>
24 <groupId>org.springframework.boot</groupId>
25 <artifactId>spring-boot-starter-cache</artifactId>
26 </dependency>
27 <dependency>
28 <groupId>org.springframework.boot</groupId>
29 <artifactId>spring-boot-starter-data-jpa</artifactId>
30 </dependency>
31 <dependency>
32 <groupId>org.springframework.boot</groupId>
33 <artifactId>spring-boot-starter-web</artifactId>
34 </dependency>
35 <dependency>
36 <groupId>org.springframework.boot</groupId>
37 <artifactId>spring-boot-starter-actuator</artifactId>
38 </dependency>
39
40 <dependency>
41 <groupId>org.joda</groupId>
42 <artifactId>joda-money</artifactId>
43 <version>1.0.1</version>
44 </dependency>
45 <dependency>
46 <groupId>org.jadira.usertype</groupId>
47 <artifactId>usertype.core</artifactId>
48 <version>6.0.1.GA</version>
49 </dependency>
50 <!-- 增加Jackson的Hibernate类型支持 -->
51 <dependency>
52 <groupId>com.fasterxml.jackson.datatype</groupId>
53 <artifactId>jackson-datatype-hibernate5</artifactId>
54 <version>2.9.8</version>
55 </dependency>
56
57 <dependency>
58 <groupId>org.apache.commons</groupId>
59 <artifactId>commons-lang3</artifactId>
60 </dependency>
61
62 <dependency>
63 <groupId>com.h2database</groupId>
64 <artifactId>h2</artifactId>
65 <scope>runtime</scope>
66 </dependency>
67 <dependency>
68 <groupId>org.projectlombok</groupId>
69 <artifactId>lombok</artifactId>
70 <optional>true</optional>
71 </dependency>
72 <dependency>
73 <groupId>org.springframework.boot</groupId>
74 <artifactId>spring-boot-starter-test</artifactId>
75 <scope>test</scope>
76 </dependency>
77 </dependencies>
78
79 <build>
80 <plugins>
81 <plugin>
82 <groupId>org.springframework.boot</groupId>
83 <artifactId>spring-boot-maven-plugin</artifactId>
84 </plugin>
85 <plugin>
86 <groupId>com.spotify</groupId>
87 <artifactId>dockerfile-maven-plugin</artifactId>
88 <version>1.4.10</version>
89 <executions>
90 <execution>
91 <id>default</id>
92 <goals>
93 <goal>build</goal>
94 <goal>push</goal>
95 </goals>
96 </execution>
97 </executions>
98 <configuration>
99 <repository>${docker.image.prefix}/${project.artifactId}</repository>
100 <tag>${project.version}</tag>
101 <buildArgs>
102 <JAR_FILE>${project.build.finalName}.jar</JAR_FILE>
103 </buildArgs>
104 </configuration>
105 </plugin>
106 </plugins>
107 </build>
108
109</project>
执行构建
1mvn package
2或
3mvn dockerfile:build
检查结果
1docker images
2
3REPOSITORY TAG IMAGE ID CREATED SIZE
4springbucks/waiter-service 0.0.1-SNAPSHOT 61568abfa910 About a minute ago 683MB
5java 8 d23bdf5b1b1b 3 years ago 643MB