在《極速體驗docker容器健康》一文已體驗了docker容器健康檢查功能,今天就來給java應用的容器加入健康檢查,使應用的狀態隨時均可以被監控和查看。java
今天實戰的java應用,是用來模擬生產環境應用的,特色以下:git
若是您不想寫代碼,上述springboot應用的源碼可在GitHub下載到,地址和連接信息以下表所示:程序員
這個git項目中有多個文件夾,本章的應用在springboot-app-docker-health-check文件夾下,以下圖紅框所示:web
應用接入容器健康檢查的步驟以下:spring
# Docker file from bolingcavalry # VERSION 0.0.1
# Author: bolingcavalry
#基礎鏡像
FROM openjdk:8-jdk-stretch
#做者
MAINTAINER BolingCavalry <zq2599@gmail.com>
#健康檢查參數設置,每5秒檢查一次,接口超時時間2秒,連續10次返回1就斷定該容器不健康
HEALTHCHECK --interval=5s --timeout=2s --retries=10 \
CMD curl --silent --fail localhost:8080/getstate || exit 1複製代碼
由上述可見Dockerfile的內容很是簡單,選定自身的基礎鏡像爲openjdk:8-jdk-stretch,再配置好健康檢查參數:docker
(base) zhaoqindeMacBook-Pro:springboot-app-docker-health-check zhaoqin$ docker build -t bolingcavalry/jdk8-healthcheck:0.0.1 .
Sending build context to Docker daemon 217.6kB
Step 1/3 : FROM openjdk:8-jdk-stretch
8-jdk-stretch: Pulling from library/openjdk
9a0b0ce99936: Already exists
db3b6004c61a: Already exists
f8f075920295: Already exists
6ef14aff1139: Already exists
962785d3b7f9: Already exists
631589572f9b: Already exists
c55a0c6f4c7b: Already exists
Digest: sha256:8bce852e5ccd41b17bf9704c0047f962f891bdde3e401678a52d14a628defa49
Status: Downloaded newer image for openjdk:8-jdk-stretch
---> 57c2c2d2643d
Step 2/3 : MAINTAINER BolingCavalry <zq2599@gmail.com>
---> Running in 270f78efa617
Removing intermediate container 270f78efa617
---> 01b5df83611d
Step 3/3 : HEALTHCHECK --interval=5s --timeout=2s --retries=10 CMD curl --silent --fail localhost:8080/getstate || exit 1
---> Running in 7cdd08b9ca22
Removing intermediate container 7cdd08b9ca22
---> 9dd7ffb22df4
Successfully built 9dd7ffb22df4
Successfully tagged bolingcavalry/jdk8-healthcheck:0.0.1複製代碼
docker push bolingcavalry/jdk8-healthcheck:0.0.1複製代碼
本次實戰的目標是讓Java應用支持docker的容器健康檢查功能,接下來一塊兒建立這個Java應用:apache
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.bolingcavalry</groupId>
<artifactId>springboot-app-docker-health-check</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot-app-docker-health-check</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!--使用jib插件-->
<plugin>
<groupId>com.google.cloud.tools</groupId>
<artifactId>jib-maven-plugin</artifactId>
<version>1.7.0</version>
<configuration>
<!--from節點用來設置鏡像的基礎鏡像,至關於Docerkfile中的FROM關鍵字-->
<from>
<!--基礎鏡像是bolingcavalry/jdk8-healthcheck:0.0.1,該鏡像已配置了健康檢查參數-->
<image>bolingcavalry/jdk8-healthcheck:0.0.1</image>
</from>
<to>
<!--鏡像名稱和tag,使用了mvn內置變量${project.version},表示當前工程的version-->
<image>bolingcavalry/${project.artifactId}:${project.version}</image>
</to>
<!--容器相關的屬性-->
<container>
<!--jvm內存參數-->
<jvmFlags>
<jvmFlag>-Xms1g</jvmFlag>
<jvmFlag>-Xmx1g</jvmFlag>
</jvmFlags>
<!--要暴露的端口-->
<ports>
<port>8080</port>
</ports>
<!--使用該參數將鏡像的建立時間與系統時間對其-->
<useCurrentTimestamp>true</useCurrentTimestamp>
</container>
</configuration>
</plugin>
</plugins>
</build>
</project>複製代碼
上述pom.xml有如下幾處須要注意:a. 使用jib插件來將當前工程構建成docker鏡像;b. 基礎鏡像是前面構建的bolingcavalry/jdk8-healthcheck:0.0.1,以此爲基礎鏡像的鏡像都帶有健康檢查功能;springboot
package com.bolingcavalry.springbootappdockerhealthcheck;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.http.ResponseEntity;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.io.*;
import java.util.List;
@SpringBootApplication
@RestController
@Slf4j
public class SpringbootAppDockerHealthCheckApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootAppDockerHealthCheckApplication.class, args);
}
/**
* 讀取本地文本文件的內容並返回
* @return
*/
private String getLocalFileContent() {
String content = null;
try{
InputStream is = new FileInputStream("/app/depend/abc.txt");
List<String> lines = IOUtils.readLines(is, "UTF-8");
if(null!=lines && lines.size()>0){
content = lines.get(0);
}
} catch (FileNotFoundException e) {
log.error("local file not found", e);
} catch (IOException e) {
log.error("io exception", e);
}
return content;
}
/**
* 對外提供的http服務,讀取本地的txt文件將內容返回,
* 若是讀取不到內容返回碼爲403
* @return
*/
@RequestMapping(value = "/hello", method = RequestMethod.GET)
public ResponseEntity<String> hello(){
String localFileContent = getLocalFileContent();
if(StringUtils.isEmpty(localFileContent)) {
log.error("hello service error");
return ResponseEntity.status(403).build();
} else {
log.info("hello service success");
return ResponseEntity.status(200).body(localFileContent);
}
}
/**
* 該http服務返回當前應用是否正常,
* 若是能從本地txt文件成功讀取內容,當前應用就算正常,返回碼爲200,
* 若是沒法從本地txt文件成功讀取內容,當前應用就算異常,返回碼爲403
* @return
*/
@RequestMapping(value = "/getstate", method = RequestMethod.GET)
public ResponseEntity<String> getstate(){
String localFileContent = getLocalFileContent();
if(StringUtils.isEmpty(localFileContent)) {
log.error("service is unhealthy");
return ResponseEntity.status(403).build();
} else {
log.info("service is healthy");
return ResponseEntity.status(200).build();
}
}
}複製代碼
上述代碼有如下幾處須要注意:a. hello方法是此應用對外提供的服務,若是本地文件abc.txt存在且內容不爲空,hello方法的返回碼就是200,不然返回碼爲403,表示當前服務出現異常;b. getstate方法是新增的服務,該接口會被docke-daemon調用,若是返回碼是200,就表示容器健康,若是返回碼是403,表示容器不健康;app
驗證的步驟以下:a. 讓應用容器正常工做,確保文件/app/depend/abc.txt是正常的,此時容器狀態應該是healthyb. 將文件/app/depend/abc.txt刪除,此時應用hello接口返回碼爲403,而且容器狀態變爲unhealthycurl
docker run --rm \
--name=java-health-check \
-p 8080:8080 \
-v /Users/zhaoqin/temp/201910/20:/app/depend \
bolingcavalry/springboot-app-docker-health-check:0.0.1-SNAPSHOT複製代碼
2019-10-20 14:16:34.875 INFO 1 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
2019-10-20 14:16:34.876 INFO 1 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2019-10-20 14:16:34.892 INFO 1 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 16 ms
2019-10-20 14:16:34.959 INFO 1 --- [nio-8080-exec-1] pringbootAppDockerHealthCheckApplication : service is healthy
2019-10-20 14:16:40.159 INFO 1 --- [nio-8080-exec-2] pringbootAppDockerHealthCheckApplication : service is healthy
2019-10-20 14:16:45.356 INFO 1 --- [nio-8080-exec-4] pringbootAppDockerHealthCheckApplication : service is healthy
2019-10-20 14:16:50.580 INFO 1 --- [nio-8080-exec-6] pringbootAppDockerHealthCheckApplication : service is healthy複製代碼
(base) zhaoqindeMBP:20 zhaoqin$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
51572d2488fb bolingcavalry/springboot-app-docker-health-check:0.0.1-SNAPSHOT "java -Xms1g -Xmx1g …" About a minute ago Up About a minute (healthy) 0.0.0.0:8080->8080/tcp java-health-check複製代碼
019-10-20 14:22:37.490 ERROR 1 --- [nio-8080-exec-7] pringbootAppDockerHealthCheckApplication : service is unhealthy複製代碼
(base) zhaoqindeMBP:20 zhaoqin$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
51572d2488fb bolingcavalry/springboot-app-docker-health-check:0.0.1-SNAPSHOT "java -Xms1g -Xmx1g …" 7 minutes ago Up 7 minutes (unhealthy) 0.0.0.0:8080->8080/tcp java-health-check複製代碼
至此,Java應用在docker環境配置容器健康檢查的實戰就完成了,但願您在給本身的應用添加健康檢查時,此文能給您一些參考。