阿里云EWS 部署 Springboot2容器

519 阅读2分钟

背景

在做手淘定制服务的时候,定制的服务的域名被限制只能使用*.ewszjk.m.jaeapp.com,申请ews域名的要求是创建自己的服务,服务的部署方式为容器。以前也有过容器部署服务的操作和自己的理解,但对容器的认识都是空中楼阁,实在没有太多头绪。

第一步:如何去部署前后端服务

  • 前端:Nginx
  • 后端:Springboot

在没有容器高大上的技术前,服务的部署是:Nginx指向前端静态资源,反向打理到后端服务,应该现在多数项目都这么进行部署。那么上容器后核心的思想不会变的,变化的是后端服务的地址会随着容器的销毁和重建发生变化。那么先来看看EWS选择网络接入的界面:

  • 外网域名接入,需要想淘宝申请外网域名(支持手淘定制访问)

  • 内网slb接入,绑定内网的SLB的端口。slb如何动态负载容器的细节暂时未知。

有了这两种方式从手淘到后端服务就能走得通了。Ngxin容器申请外网域名,Nginx反向打理后端服务,服务地址为slb地址和固定的端口(8080)。内网动态负载Springboot容器中跑的服务。

第二步:如何部署容器

Nginx容器

配置Nginx容器比较简单,主要由两部分构成:

  1. 配置Nginx配置文件(如果部署多个服务,可以配置多个新建多个配置文件。)

  1. 上传前端代码。通过文件上传可以上传单个文件或是zip包。如果你上传了一个demo.zip的包上去,容器启动完成后会将demo.zip包压缩到 /acs/code/下。

Springboot容器

以往的项目都是通过手写启动脚本start.sh来启动,启动的核心思想是java -jar demo.jar --springxxxxx。现在只有个上传部署,如何去启动项目没有入口(聚石塔更贴近以往的操作)。经验告诉我们遇到个不未知的东西的时候应该去折腾他。通过上传部署,进入到容器里面发现了两个尤为重要的脚本:

start
JARINFDIR="/acs/code/BOOT-INF"
WARINFDIR="/acs/code/WEB-INF"
if [ -d "$JARINFDIR"  ]; then
    echo "jar inf dir exist"
    cd ${CODEDIR}
    /acs/user/jdk/bin/java ${JAVAOPT} org.springframework.boot.loader.JarLauncher ${SPRINGBOOTOPT} --server
.port=${MAINPORT} --management.server.port=${MANAGEMENTPORT} &
elif [ -d "$WARINFDIR" ]; then
    echo "war inf dir exist"
    cd ${CODEDIR}
    /acs/user/jdk/bin/java ${JAVAOPT} org.springframework.boot.loader.WarLauncher ${SPRINGBOOTOPT} --server
.port=${MAINPORT} --management.server.port=${MANAGEMENTPORT} &
else
    echo "no jar/war directory"
    exit 4
fi

我们只需要关注这段就可以了。支持jar报部署和war包部署,我这里是jar包部署。容器会去/acs/code/目录下找BOOT-INF目录,然后进到/acs/code/目录下执行

org.springframework.boot.loader.JarLauncher ${SPRINGBOOTOPT} --server
.port=${MAINPORT} --management.server.port=${MANAGEMENTPORT} &

以前项目打包用过maven-sprinboot-plugin打包期间各种出错(多模块项目),只好另辟蹊径使用了maven-shade-plugin插件。shade插件使用非常友好,于是项目中一直使用,可这次是绕不过去了(BOOT-INF正是maven-sprinboot-plugin构建的目录)。问题解决:

问题一:plugin加载不到

在maven中添加plugin的Repository

    <repositories>
        <repository>
            <id>spring-releases</id>
            <url>https://repo.spring.io/libs-release</url>
        </repository>
    </repositories>
    <pluginRepositories>
        <pluginRepository>
            <id>spring-releases</id>
            <url>https://repo.spring.io/libs-release</url>
        </pluginRepository>
    </pluginRepositories>
问题二:找不到符号

多模块的项目中plugin的配置只写到启动类所在的pom.xml中,不要配置在根module的pom.xml。

问题三:找不到主类
unzip -x -q demo.jar  -d demo

通过解压jar包,可以从程序的清单文件/META-INF/MANIFEST.MF中得到两个关键的信息。

  1. Main-Class:程序执行入口
  2. Start-Class:程序启动的入口 这里的理解不太正确,但主要值对应正确,那么启动就没问题了。这里涉及到Springboot的启动知识以后再补上。
Manifest-Version: 1.0
Implementation-Title: custom-web
Implementation-Version: 1.0-SNAPSHOT
Built-By: jiancaiwang
Implementation-Vendor-Id: apm.mc
Spring-Boot-Version: 2.0.3.RELEASE
Main-Class: org.springframework.boot.loader.JarLauncher
Start-Class: mc.apm.custom.web.Application
Spring-Boot-Classes: BOOT-INF/classes/
check

/actuator/health 就能知道后面改干啥了,也对Springboot容器有个整个认识。由于安全性,/health需要进行配置。

ENV_FILE="/acs/conf/env.properties"
PORT=`cat $ENV_FILE |grep -w port.managementport |sed "s/^port.managementport=//"`
HEALTH_URL="http://localhost:$PORT/actuator/health"
HEALTH_CHECK_CODE=`curl -s --connect-timeout 3 --max-time 5 ${HEALTH_URL} -o /dev/null -w %{http_code}`
if [ "$HEALTH_CHECK_CODE" == "200" ]; then
    echo "success"
    exit 0
else
    echo "start fail"
    exit 3
fi

打完收工。 EWS处理几个常规的容器外,还支持自定义容器。