docker-compose下的java應用啓動順序兩部曲之一:問題分析

在docker-compose編排多個容器時,須要按實際狀況控制各容器的啓動順序,本文是《docker-compose下的java應用啓動順序兩部曲》的第一篇,文中會分析啓動順序的重要性,以及啓動順序有問題時會有什麼樣的影響,再給出臨時解決的和官方推薦的兩種解決方案,爲下一篇的實戰作好鋪墊。java

環境信息

本次實戰的環境以下:程序員

  1. 操做系統:CentOS Linux release 7.7.1908
  2. docker:1.13.1
  3. docker-compose:1.24.1
  4. spring cloud:Finchley.RELEASE

分佈式環境中的依賴關係

在分佈式環境中,各服務之間可能存在依賴關係,例如SpringCloud環境中的應用在啓動時都會先往註冊中心Eurka發起請求,以下圖(來自spring官方博客:https://spring.io/blog/2015/07/14/microservices-with-spring ):在這裏插入圖片描述從上圖可知,若是Eureka的服務不可用,就會影響業務服務的功能;web

Docker環境中的依賴關係

  1. 上述服務若是用docker-compose編排在一塊兒,也面依賴着問題:Eureka容器啓動完畢而且能提供http服務之後,業務服務的容器才能在Eureka註冊成功並取得服務列表,一般咱們都使用depends_on參數來設定依賴關係;
  2. 如下是個docker-compose.yml文件,裏面有兩個容器:eureka和service,eureka是註冊中心,service是業務服務,service啓動後要去eureka註冊,爲了確保啓動順序,service配置了depends_on參數:
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 'java -Xms1g -Xmx1g -cp /app/resources:/app/classes:/app/libs/* com.bolingcavalry.waitforitdemo.ServiceApplication'
    depends_on:
    - eureka複製代碼
  1. 上述yml文件能解決依賴問題嗎?service服務啓動時可否成功在eureka註冊?來試試吧,在Linux電腦上建立docker-compose.yml文件,內容如上所示;
  2. 在docker-compose.yml所在目錄執行docker-compose up,docker服務會先去hub.docker.com下載鏡像,而後依次建立容器,控制檯會同時打印eureka和service的日誌,以下圖所示,service註冊eureka失敗了,請注意圖中的文字分析:
    在這裏插入圖片描述
  3. 爲什麼會註冊失敗呢?繼續看後面的日誌,以下圖,service註冊失敗後eureka才初始化完成,因此前面的service註冊會失敗:
    在這裏插入圖片描述
  4. 至此能夠肯定:dependson參數能夠確保eureka容器啓動後再啓動service容器,但咱們真正想要的,是eureka容器啓動後,而且eureka服務初始化完畢進入可用狀態後,再啓動service容器,顯然dependson參數達不到咱們的要求;
  5. docker官方文檔也證明了這一點,以下圖紅框所示:
    在這裏插入圖片描述
  6. 看來depends_on參數解決不了咱們的問題,須要去尋找其餘方法;

另外您可能會說:不要緊,service會自動從新註冊,可是在真實環境中,不是每一個服務都有能力去本身解決依賴不可用的問題,例如spring-cloud-config服務若是起不來,依賴它的服務可能會當即中止;redis

有一種臨時方法(此方法V3版語法再也不支持)

  1. 若是eureka容器配置了健康檢查,那麼service容器能夠配置健康檢查依賴來控制啓動時機,具體的作法能夠參考官方示例,以下所示,地址是:https://docs.docker.com/compose/compose-file/compose-file-v2/ :
version: "2.4"
services:
  web:
    build: .
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_started
  redis:
    image: redis
  db:
    image: redis
    healthcheck:
      test: "exit 0"複製代碼

從上述編排內容可見:db容器有健康檢查,能夠肯定db容器的服務是否可用,web容器的depends_on參數內能夠配置condition,這樣就作到了只有redis已經啓動而且db的健康檢查經過,纔會啓動web容器;spring

  1. 上述配置看起來彷佛是個不錯的方案,在咱們這裏,只要給eureka配置要健康檢查,再讓service容器的dependson參數內配置condition: servicehealthy就能夠了;
  2. 不幸的是:在docker-compose的第三版語法中,取消了condition參數!文檔地址是:https://docs.docker.com/compose/compose-file/ ,以下圖紅框所示:
    在這裏插入圖片描述
  3. 所以,condition參數看似好用,可是從V3版開始的docker-compose.yml已經再也不支持該參數,不能做爲標準的解決方案;

官方推薦的方案

以下圖紅框所示,docker官方推薦使用wait-for-it.sh腳原本解決問題,地址:https://docs.docker.com/compose/startup-order/ :在這裏插入圖片描述至此,本篇已經分析了docker-compose下容器啓動順序的問題,下一篇文章,咱們用SpringCloud應用來作實戰,將其作到在docker-compose下有序啓動;docker

參考文章

若是您對docker容器健康檢查有興趣,能夠參考如下文章:app

  1. 《極速體驗docker容器健康》
  2. 《Java應用在docker環境配置容器健康檢查》

歡迎關注公衆號:程序員欣宸

相關文章
相關標籤/搜索