如何基於SpringBoot+Docker構建公司級別的遠端除錯

擊水三千里發表於2019-01-16

背景:現在很多公司一般分為開發,測試,預發,生產等環境,除了生產其他環境出現一點小問題都要通過查詢日誌的形式來定位問題非常的費時費力影響開發效率。鑑於很多公司都採用了SpringBoot+Docker的形式來部署微服務,本文提出一套實際可以大大節省排查和定位問題所需時間的方法——遠端除錯程式碼

 

1、DockerFile檔案

FROM maven:3-jdk-8-alpine
MAINTAINER lzhcode
RUN mkdir -p  /home/admin/myapp
ENV app_name="myapp"
ENV compile_dir="/hyena/$app_name" \
    work_dir="/home/admin/$app_name"

ENV JAVA_OPTS=" -Dcatalina.vendor=ecarx -Djava.security.egd=file:/dev/./urandom -Dlog4j.defaultInitOverride=true -Dorg.apache.tomcat.util.http.ServerCookie.ALLOW_EQUALS_IN_VALUE=true -Dorg.apache.tomcat.util.http.ServerCookie.ALLOW_HTTP_SEPARATORS_IN_V0=true -server -Xms512m -Xmx512m -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=256m -Xmn256m -XX:MaxDirectMemorySize=1g -XX:SurvivorRatio=10 -XX:+UseConcMarkSweepGC -XX:CMSMaxAbortablePrecleanTime=5000 -XX:+CMSClassUnloadingEnabled -XX:CMSInitiatingOccupancyFraction=80 -XX:+UseCMSInitiatingOccupancyOnly -XX:+ExplicitGCInvokesConcurrent -Dsun.rmi.dgc.server.gcInterval=2592000000 -Dsun.rmi.dgc.client.gcInterval=2592000000 -XX:ParallelGCThreads=4 -Xloggc:$work_dir/logs/gc.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=$work_dir/logs/java.hprof -Djava.awt.headless=true -Dsun.net.client.defaultConnectTimeout=10000 -Dsun.net.client.defaultReadTimeout=30000 -DJM.LOG.PATH=$work_dir/logs -DJM.SNAPSHOT.PATH=$work_dir/snapshots -Dfile.encoding=utf-8 -Dserver.port=8007"


ENV REMOTE_DEBUG="-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=28000"

WORKDIR $work_dir

#把web專案copy到/hyena/$app_name目錄下
COPY ./ $compile_dir

#把shell指令碼列印出來,觀察是否copy成功
RUN  cat $compile_dir/docker-entrypoint.sh

#為shell指令碼授權
RUN  chmod 777 $compile_dir/docker-entrypoint.sh

RUN  sh -c ' mkdir -p $work_dir/logs && cp $compile_dir/boot/target/$app_name.jar $work_dir/'

#容器內的web服務埠
EXPOSE 8007

#容器內的遠端除錯埠
EXPOSE 28000


#啟動容器時執行web專案
ENTRYPOINT ["sh","-c","$compile_dir/docker-entrypoint.sh"]

docker-entrypoint.sh檔案內容 (和DockerFile在同一級目錄下)

#!/bin/bash
set -e

if [ "$ENV_TYPE" = 'development' ] || [ "$ENV_TYPE" = 'testing' ]; then

      java $REMOTE_DEBUG $JAVA_OPTS -jar  $work_dir/$app_name.jar

elif [ "$ENV_TYPE" = 'staging' ] || [ "$ENV_TYPE" = 'production' ]; then

      java  $JAVA_OPTS -jar  $work_dir/$app_name.jar

fi

exec "$@"

關鍵是  java $REMOTE_DEBUG $JAVA_OPTS -jar  $work_dir/$app_name.jar這句

表示用jdwp遠端除錯的方式啟動myapp.jar(注意這是jdk8的配置,jdk低版本的的配置見下圖IDEA裡的配置)

其中

1、$REMOTE_DEBUG = -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=28000

在shell指令碼里控制只有development和testing環境,才以遠端除錯的方式啟動jar

2、$ENV_TYPE 師配置在k8s裡的環境變數,在用k8s啟動容器時可以獲取到對應的值

 

2、靈雀雲配置外部埠對映Docker的內部埠

3、IDEA的配置

     點選Debug後就可以和ip 10.160.11.59 ,埠為28000的mysqpp服務建立Socket除錯連線

    

4、遠端除錯

    保證原生程式碼和遠端程式碼一致,直接在前端開啟dev或test下的系統,就可直接在本地斷點除錯不同環境下的程式碼了,但是需要注意的是當一個斷點卡住為釋放時,其他斷點也無法執行,而且一次只能有一個人打斷點。需要團隊內部事先協調好,適用於不同環境下疑難問題的快速排查。

日誌裡出現Debugger failed to attach: recv failed during handshake: Connection reset by peer 出現了這個就表示可以進行遠端除錯了

相關文章