hi,你好!欢迎访问本站!登录
本站由网站地图腾讯云宝塔系统阿里云强势驱动
当前位置:首页 - 教程 - 杂谈 - 正文 君子好学,自强不息!

docker-compose下的java运用启动递次两部曲之二:实战

2019-11-18杂谈搜奇网21°c
A+ A-

上篇回忆

  • 本文是《docker-compose下的java运用启动递次两部曲》的终篇,在上一篇《docker-compose下的java运用启动递次两部曲之一:题目剖析》中,我们以SpringCloud环境下的注册中间和营业效劳为例,展现了docker-compose.yml中depends_on参数的不足:即只能掌握容器建立递次,但我们想要的是eureka效劳停当以后再启动营业效劳,而且docker官方也以为depends_on参数是达不到这个请求的,以下图所示:
  • 针对上述题目,docker给出的解决方法是运用wait-for-it.sh脚原本解决题目,地点:https://docs.docker.com/compose/startup-order/ ,以下图:

    什么是wait-for-it.sh

  • wait-for-it.sh剧本用来接见指定的地点和端口,假如收不到相应就守候一段时候再去重试,直到收到相应后,再去做前面指定好的敕令,如上图红框所示./wait-for-it.sh db:5432 -- python app.py的意义是:比及db:5432这个长途接见能够相应的时刻,就去实行python app.py敕令
  • wait-for-it.sh文件的链接:
    https://raw.githubusercontent.com/zq2599/blog_demos/master/wait-for-it-demo/docker/wait-for-it.sh

    环境信息

    本次实战的环境以下:
  1. 操作体系:CentOS Linux release 7.7.1908
  2. docker:1.13.1
  3. docker-compose:1.24.1
  4. spring cloud:Finchley.RELEASE
  5. maven:3.6.0
  6. jib:1.7.0

实战简介

上一篇的例子中,我们用到了eureka和service两个容器,eureka是注册中间,service是一般营业运用,service容器向eureka容器注册时,eureka还没有初始化完成,因此service注册失利,在稍后的自动重试时由于eureka进入ready状况,因此service注册胜利。
本日我们来革新上一篇的例子,让service用上docker官方引荐的wait-for-it.sh剧本,守候eureka效劳停当再启动java历程,确保service能够一次性注册eureka胜利;
为了抵达上述目的,统共须要做以下几步:

  1. 简朴引见eureka和service容器的镜像是怎样制造的;
  2. 制造基本镜像,包括wait-for-it.sh剧本;
  3. 运用新的基本镜像构建service镜像;
  4. 革新docker-compose.yml;
  5. 启动容器,考证递次掌握是不是胜利;
  6. wait-for-it.sh计划的缺点;

接下来进入实战环节;

源码下载

假如您不想编码,也能够在GitHub上猎取文中一切源码和剧本,地点和链接信息以下表所示:
| 称号 | 链接 | 备注|
| :-------- | :----| :----|
| 项目主页| https://github.com/zq2599/blog_demos | 该项目在GitHub上的主页 |
| git堆栈地点(https)| https://github.com/zq2599/blog_demos.git | 该项目源码的堆栈地点,https协定 |
| git堆栈地点(ssh)| git@github.com:zq2599/blog_demos.git | 该项目源码的堆栈地点,ssh协定 |

这个git项目中有多个文件夹,本章的运用在wait-for-it-demo文件夹下,以下图红框所示:

源码的构造以下图所示:

接下来最先编码了;

简朴引见eureka和service容器

上一篇和本篇,我们都在用eureka和service这两个容器做试验,如今就来看看他们是怎样做出来的:

  1. eureka是个maven工程,和SpringCloud环境中的eureka效劳一样,唯一差别的是它的pom.xml中运用了jib插件,用来将工程构建成docker镜像:
<?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.bolingcavalry</groupId>
    <artifactId>eureka</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>eureka</name>
    <description>eureka</description>

    <parent>
        <groupId>com.bolingcavalry</groupId>
        <artifactId>wait-for-it-demo</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <relativePath>../pom.xml</relativePath> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Finchley.RELEASE</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </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>
                        <!--运用openjdk官方镜像,tag是8-jdk-stretch,示意镜像的操作体系是debian9,装好了jdk8-->
                        <image>openjdk:8-jdk-stretch</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>
                <executions>
                    <execution>
                        <phase>compile</phase>
                        <goals>
                            <goal>dockerBuild</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

上述pom.xml中多了个jib插件,如许在实行mvn compile的时刻,插件就会用构建效果制造好docker镜像并放入当地堆栈;

  1. service是个一般的SpringCloud运用,除了在pom.xml中也用到了jib插件来构建镜像,它的设置文件中,接见eureka的地点要写成eureka容器的称号:
spring:
  application:
    name: service

eureka:
  client:
    serviceUrl:
      defaultZone: http://eureka:8080/eureka/
  1. 关于如何将java运用制造成docker镜像,假如您想相识更多请参考以下两篇文章:
    《Docker与Jib(maven插件版)实战》
    《Jib运用小结(Maven插件版)》

制造基本镜像

从上面的pom.xml可见,我们将Java运用制造成docker镜像时,运用的基本镜像是openjdk:8-jdk-stretch,如许做出的运用镜像是不含wait-for-it.sh剧本的,天然就没法完成启动递次掌握了,因此我们要做一个带有wait-for-it.sh的基本镜像给营业镜像用:

  1. 把wait-for-it.sh文件准备好,下载地点:https://raw.githubusercontent.com/zq2599/blog_demos/master/wait-for-it-demo/docker/wait-for-it.sh
  2. 在wait-for-it.sh文件地点目次新建Dockerfile文件,内容以下:
FROM openjdk:8-jdk-stretch

ADD wait-for-it.sh /wait-for-it.sh
RUN sh -c 'chmod 777 /wait-for-it.sh'

注重:我这里用的是openjdk:8-jdk-stretch,您能够依据本身的实际须要挑选差别的openjdk版本,能够参考:《openjdk镜像的tag申明》

  1. 实行敕令docker build -t bolingcavalry/jkd8-wait-for-it:0.0.2 .就可以构建出名为bolingcavalry/jkd8-wait-for-it:0.0.2的镜像了,请您依据本身的状况设置镜像称号和tag,注重敕令的末端有个小数点,不要漏了;
  2. 假如您有hub.docker.com账号,建请运用docker push敕令将新建的镜像推送到镜像堆栈上去,或许推送到私有堆栈,由于背面运用jib插件构建镜像是,jib插件要去堆栈猎取基本镜像的元数据信息,取不到会致使构建失利;

运用新的基本镜像构建service镜像

我们的目的是让service效劳守候eureka效劳停当,所以应当革新service效劳,让它用docker官方引荐的wait-for-it.sh计划来完成守候:

  • 修正service工程的pom.xml,有关jib插件的设置改成以下内容:
<plugin>
                <groupId>com.google.cloud.tools</groupId>
                <artifactId>jib-maven-plugin</artifactId>
                <version>1.7.0</version>
                <configuration>
                    <!--from节点用来设置镜像的基本镜像,相当于Docerkfile中的FROM关键字-->
                    <from>
                        <!--运用克己的基本镜像,内里有wait-for-it.sh剧本-->
                        <image>bolingcavalry/jkd8-wait-for-it:0.0.2</image>
                    </from>
                    <to>
                        <!--镜像称号和tag,运用了mvn内置变量${project.version},示意当前工程的version-->
                        <image>bolingcavalry/${project.artifactId}:${project.version}</image>
                    </to>
                    <!--容器相干的属性-->
                    <container>
                        <!--entrypoint的值即是INHERIT示意jib插件不构建启动敕令了,此时要运用者本身掌握,能够在启动时输入,或许写在基本镜像中-->
                        <entrypoint>INHERIT</entrypoint>
                        <!--要暴露的端口-->
                        <ports>
                            <port>8080</port>
                        </ports>
                        <useCurrentTimestamp>true</useCurrentTimestamp>
                    </container>
                </configuration>
                <executions>
                    <execution>
                        <phase>compile</phase>
                        <goals>
                            <goal>dockerBuild</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

上述设置有几点须要注重:

a. 基本镜像改成方才构建好的bolingcavalry/jkd8-wait-for-it:0.0.2

b. 增添entrypoint节点,内容是INHERIT,根据官方的说法,entrypoint的值即是INHERIT示意jib插件不构建启动敕令了,此时要运用者本身掌握,能够在启动时输入,或许写在基本镜像中,如许我们在docker-compose.yml顶用command参数来设置service容器的启动敕令,就可以够把wait-for-it.sh剧本用上了

c. 去掉jvmFlags节点,根据官方文档的说法,entrypoint节点的值即是INHERIT时,jvmFlags和mainClass参数会被疏忽,以下图,地点是:https://github.com/GoogleContainerTools/jib/tree/master/jib-maven-plugin

至此,service工程革新终了,接下来修正docker-compose.yml,让service容器能用上wait-for-it.sh
### 革新docker-compose.yml

  1. 完全的docker-compose.yml内容以下所示:
version: '3'
services:
 eureka:
   image: bolingcavalry/eureka:0.0.1-SNAPSHOT
   container_name: eureka
   restart: unless-stopped
 service:
   image: bolingcavalry/service:0.0.1-SNAPSHOT
   container_name: service
   restart: unless-stopped
   command: sh -c './wait-for-it.sh eureka:8080 -t 0  -- java -Xms1g -Xmx1g -cp /app/resources:/app/classes:/app/libs/* com.bolingcavalry.waitforitdemo.ServiceApplication'
   depends_on:
   - eureka
  1. 注重command参数的内容,以下,service容器建立后,会一向守候eureka:8080的相应,直到该地点有相应后,才会实行敕令java -Xms1g -Xmx1g -cp /app/resources:/app/classes:/app/libs/* com.bolingcavalry.waitforitdemo.ServiceApplication
sh -c './wait-for-it.sh eureka:8080 -t 0  -- java -Xms1g -Xmx1g -cp /app/resources:/app/classes:/app/libs/* com.bolingcavalry.waitforitdemo.ServiceApplication'
  1. 关于敕令java -Xms1g -Xmx1g -cp /app/resources:/app/classes:/app/libs/* com.bolingcavalry.waitforitdemo.ServiceApplication,您能够以为太长了不好写,这里有个小窍门,就是在不运用entrypoint节点的时刻,用jib插件制造的镜像本身是带有启动敕令的,容器运转的时刻,您能够经由过程docker ps --no-trunc敕令看到该容器的完全启动敕令,复制过来直接用就好了;

一切的革新事情都完成了,能够最先考证了;

启动容器,考证递次掌握是不是胜利

  1. 在docker-compose.yml文件地点目次实行敕令docker-compose up,会建立两个容器,而且日记信息会直接打印在掌握台,我们来剖析这些日记信息,考证递次掌握是不是胜利;
  2. 以下图,可见service容器中并没有启动java历程,而是在守候eureka:8080的相应:
  3. 继承看日记,可见eureka效劳停当的时刻,service容器的wait-for-it.sh剧本收到了相应,因而马上启动service运用的历程:
  4. 继承看日记,以下图,service在eureka上注册胜利:

    综上所述,运用docker官方引荐的wait-for-it.sh来掌握java运用的启动递次是可行的,能够根据营业本身的需求来量身定做适宜的启动递次;

    wait-for-it.sh计划的缺点

运用docker官方引荐的wait-for-it.sh来掌握容器启动递次,虽然已满足了我们的需求,但照旧留不是圆满计划,留下的缺点照样请您先晓得吧,或许这个缺点会对您的体系发生严峻的负面影响:

  1. 再开启一个SSH衔接,登录到实战的linux电脑上,实行敕令docker exec eureka ps -ef,将eureka容器内的历程打印出来,以下所示,java历程的PID即是1
[root@maven ~]# docker exec eureka ps -ef
UID         PID   PPID  C STIME TTY          TIME CMD
root          1      0  2 07:04 ?        00:00:48 java -Xms1g -Xmx1g -cp /app/resources:/app/classes:/app/libs/* com.bolingcavalry.waitforitdemo.EurekaApplication
root         56      0  0 07:25 ?        00:00:00 /bin/bash
root         63      0  0 07:31 ?        00:00:00 ps -ef
  1. 再来看看service的历程状况,实行敕令docker exec service ps -ef,将service容器内的历程打印出来,以下所示,PID即是1的历程不是java,而是启动时的shell敕令
[root@maven ~]# docker exec service ps -ef
UID         PID   PPID  C STIME TTY          TIME CMD
root          1      0  0 07:04 ?        00:00:00 sh -c ./wait-for-it.sh eureka:8080 -t 0  -- java -Xms1g -Xmx1g -cp /app/resources:/app/classes:/app/libs/* com.bolingcavalry.waitforitdemo.ServiceApplication
root          7      1  1 07:04 ?        00:00:32 java -Xms1g -Xmx1g -cp /app/resources:/app/classes:/app/libs/* com.bolingcavalry.waitforitdemo.ServiceApplication
root        107      0  0 07:33 ?        00:00:00 ps -ef
  1. 通常状况下,在实行敕令docker stop xxx住手容器时,只要PID=1的历程才会收到"SIGTERM"信号量,所以在运用docker stop住手容器时,eureka容器中的java历程收到了"SIGTERM"能够马上住手,然则service容器中的java历程收不到"SIGTERM",因此只能比及默许的10秒超时时候抵达的时刻,被"SIGKILL"信号量杀死,不只守候时候长,而且文雅停机的功用也用不上了
  2. 您能够离别输入docker stop eurekadocker stop service来感受一下,前者马上完成,后者要守候10秒。
  3. 我的shell妙技过于平凡,现在还找不到好的解决方法让service容器中的java历程获得1号历程ID,个人以为自定义entrypoint.sh脚原本挪用wait-for-it.sh而且处置惩罚"SIGTERM"说不定可行,假如您有好的方法请留言示知,在此感激涕零;
  4. 现在看来,掌握容器启动递次最好的解决计划并不是wait-for-it.sh,而是营业本身完成容错,比方service注册eureka失利后会自动重试,然则这对营业的请求就略高了,尤其是在庞杂的分布式环境中越发难以完成;
  5. docker官方引荐运用wait-for-it.sh剧本的文章地点是:https://docs.docker.com/compose/startup-order/ ,文章末端显现了顶和踩的数目,以下图,顶的数目是145,踩的数目抵达了563,一份官方文档竟然这么不受待见,也算是开了眼界,不知道和我前面提到的1号PID题目有无关联:

    至此,java运用的容器递次掌握实战就完成了,愿望您在对本身的运用做容器化的时刻,此文能给您供应一些参考。

    迎接关注民众号:程序员欣宸

  选择打赏方式
微信赞助

打赏

QQ钱包

打赏

支付宝赞助

打赏

  移步手机端
docker-compose下的java运用启动递次两部曲之二:实战

1、打开你手机的二维码扫描APP
2、扫描左则的二维码
3、点击扫描获得的网址
4、可以在手机端阅读此文章
未定义标签

本文来源:搜奇网

本文地址:https://www.sou7.cn/282180.html

关注我们:微信搜索“搜奇网”添加我为好友

版权声明: 本文仅代表作者个人观点,与本站无关。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。请记住本站网址https://www.sou7.cn/搜奇网。

发表评论

选填

必填

必填

选填

请拖动滑块解锁
>>