52、构建生产部署流程

构建生产部署流程

在软件开发过程中,将应用程序部署到生产环境是至关重要的环节。本文将详细介绍如何构建一个生产部署流程,包括本地服务器部署、远程服务器上传以及特定应用服务器的部署等内容。

1. 编写安装到服务器的构建文件

对于 Tomcat 4.0 部署,我们参考了相关代码并进行了简化,因为我们总是部署到本地主机。为了确保部署的严谨性,我们将文件复制到 CATALINA_HOME/webapps 目录下,这样服务器重启时应用程序也会随之重启。

设置指向目标目录和文件的属性:

<property name="target.deploy.directory"
  location="${env.CATALINA_HOME}/webapps"/>   
<property name="webapp.expanded.dir"
 location="${target.deploy.directory}/${target.appname}" />  
<property name="webapp.copied.file"
 location="${target.deploy.directory}/${target.appname}.war" />  

我们复制未展开的 WAR 文件用于服务器重启,然后将其展开以安装到运行中的服务器。

1.1 卸载当前安装

我们省略卸载目标,其会对 http://localhost:8080/manager/remove?path=/${target.appname} 发起 <get> 请求。也可以考虑完全关闭应用服务器,这样能确保所有派生线程被销毁,所有内存被释放。

1.2 清理安装

在生产环境中,我们总是清理之前的文件集。卸载应用程序后,等待几秒再删除 WAR 文件的展开和未展开状态。

<target name="clean" depends="unload" 
    description="clean up: unload app and delete all files">
  <sleep seconds="${target.sleep.seconds}" />  
  <delete file="${webapp.copied.file}" />   
  <delete dir="${webapp.expanded.dir}" />   
</target>  

有些服务器并不总是卸载所有库,特别是包含 javax 包的 JAR 文件。我们可以将 failonerror 标志设置为 false 以继续执行,但在解压时可能会遇到问题。如果这是常见问题,每次部署都需要关闭 Web 服务器。

1.3 复制文件

清理完成后,复制新文件:

<target name="install-files" depends="clean">
  <copy file="${target.warfile}" 
    tofile="${webapp.copied.file}"/>
  <unzip src="${webapp.copied.file}" 
    dest="${webapp.expanded.dir}"/>
</target>

这样我们就可以通过服务器重启或管理 URL 调用运行应用程序。

1.4 加载应用程序

通过管理 URL 调用启动程序,对 http://localhost:8080/manager/install?path=/${target.appname}&war=file://${webapp.expanded.dir} 发起 <get> 请求。整个过程包括删除、复制和展开,比平时多花几秒,但总共只需 15 - 20 秒。

2. 上传到远程服务器

我们需要将本地安装和配置文件上传到远程服务器,目前选择使用 FTP。所有操作都在顶级 deploy.xml 文件中完成。

2.1 配置上传

Ant 首先要确定远端需要哪些文件,避免发送过多文件以防止混淆和维护安全。通过命令行定义远程主机名,如 ant -Dhostname=eiger ,构建文件加载主机名的属性文件并列出所需文件。

<property name="config.file" 
  location="${systems.dir}/${hostname}.properties"/>
<property file="${config.file}" />    
<property file="${systems.dir}/common.properties" /> 
<property name="servertype.file" 
  location="${servertypes.dir}/${target.servertype}.properties"/>
<property file="${servertype.file}" /> 
<property name="redeploy.dir" location="dist/redeploy" />  
<property name="remote.config.file" 
  location="${remote.dir}/install-${hostname}.properties"/>
<property name="remote.build.file" 
  location="${remote.dir}/${target.servertype}.xml"/>

构建时的配置文件包含比上传文件更多的信息,如服务器密码等。我们还从这些属性中派生其他值,以允许目标系统在必要时在配置文件中定义它们。

2.2 构建上传文件目录

根据配置细节,Ant 知道要上传哪些文件,将它们复制到新的重新部署目录,将配置文件与 WAR 文件本身结合。

<target name="build-deployment-package" depends="init">
  <copy todir="${redeploy.dir}" file="${warfile}"/>
  <copy todir="${redeploy.dir}" file="${remote.config.file}"/>
  <copy todir="${redeploy.dir}" file="${remote.build.file}"/>
  <copy todir="${redeploy.dir}" file="${remote.dir}/build.xml"/>
  <copy todir="${redeploy.dir}" 
    file="${remote.dir}/common.properties"/>
</target>

本地部署可以直接从这个目录运行,这是测试过程的最简单方法。

2.3 上传文件

使用 <ftp> 任务进行部署,连续调用三次:

<target name="upload" depends="build-deployment-package"  
    unless="is.localhost" >

  <echo>connecting to ${target.server}
    as ${ftp.userid} into ${ftp.remotedir}
  </echo>
  <ftp server="${ftp.server}" port="${ftp.port}"
    action="mkdir"                                   
    remotedir="${ftp.remotedir}"
    userid="${ftp.userid}"
    password="${ftp.password}"
    verbose="true" passive="true"
    ignoreNoncriticalErrors="true"
    />

  <ftp server="${ftp.server}" port="${ftp.port}"
    remotedir="${ftp.remotedir}"
    userid="${ftp.userid}" password="${ftp.password}"
    depends="true" verbose="true" passive="true"
    binary="true"
    ignoreNoncriticalErrors="true"
    >
    <fileset dir="${redeploy.dir}">                  
      <include name="**/*.war"/>                     
    </fileset>                                       
  </ftp>  

  <ftp server="${ftp.server}" port="${ftp.port}"
    remotedir="${ftp.remotedir}"
    userid="${ftp.userid}" password="${ftp.password}"
    depends="true" verbose="true" passive="true"
    binary="false"
    ignoreNoncriticalErrors="true"
    >
    <fileset dir="${redeploy.dir}">                  
      <include name="**/*.xml"/>                     
      <include name="**/*.properties"/>              
    </fileset>
  </ftp>  
</target> 

第一次 <ftp> 调用创建目标目录,第二次上传 WAR 文件,第三次以文本模式上传 XML 和属性文件,以便 <telnet> 可以将行结尾转换为适合目标的格式。

2.4 准备运行远程构建

文件上传到远程服务器后,需要使用 <telnet> 远程运行构建。在调用 <telnet> 之前,需要解决不同服务器不同提示的问题,定义不同目标平台的初始提示和重置提示的命令。

<target name="unix-prompts" if="target.isUnix">
  <property name="telnet.prompt.command"
    value="export PS1=${telnet.prompt}"/>
  <property name="telnet.initial.prompt" value="$"/>
</target>
<target name="windows-prompts" unless="target.isUnix">
  <property name="telnet.prompt.command"
    value="PROMPT ${telnet.prompt}"/>
  <property name="telnet.initial.prompt" value="&gt;"/>
</target>
2.5 远程调用 Ant
<target name="install-remote"
    depends="upload,unix-prompts,windows-prompts"
    unless="is.localhost">
  <telnet server="${telnet.server}"  port="${telnet.port}"
      userid="${telnet.userid}" password="${telnet.password}"
      timeout="${telnet.timeout}" >
    <read string="${telnet.initial.prompt}"/>
    <write>${telnet.prompt.command}</write>   
    <read string="${telnet.prompt}"/>
    <write>cd ${telnet.cd.directory}</write>  
    <read string="${telnet.prompt}"/>
    <write>ant</write>                        
    <read string="${telnet.prompt}"/>  
  </telnet>
</target>

这个目标连接到远程服务器,使用提供的用户名和密码。需要设置一个超时时间,确保至少与远程运行构建文件的最长可能时间一样长。

3. 远程部署实战

实际运行构建时,日志显示 Ant 已成功登录到远程服务器,并运行了刚刚上传的远程 Ant 构建。如果远程构建失败,本地构建会继续执行,我们可以依赖功能测试来发现问题。

4. 部署流程回顾

这个部署流程虽然看起来有点复杂,但我们获得了可扩展性、灵活性和更高的安全性:
- 可扩展性 :添加新服务器只需添加两个配置文件,无需修改构建文件本身。
- 灵活性 :可以支持多种不同的服务器类型,每个服务器需要自己的安装构建文件。
- 安全性 :部署过程适用于安全系统,也可以通过 SSH 隧道工作。

下面是整个本地部署到远程部署的流程图:

graph LR
    A[开始] --> B[编写本地构建文件]
    B --> C[卸载当前安装]
    C --> D[清理安装]
    D --> E[复制文件]
    E --> F[加载应用程序]
    F --> G[配置上传信息]
    G --> H[构建上传文件目录]
    H --> I[上传文件到远程服务器]
    I --> J[准备远程构建]
    J --> K[远程调用 Ant 运行构建]
    K --> L[结束]

通过以上步骤,我们可以构建一个完整的生产部署流程,确保应用程序能够顺利部署到本地和远程服务器。在后续部分,我们将继续探讨特定应用服务器的部署。

构建生产部署流程

5. 部署到特定应用服务器

市面上有众多不同的应用服务器,每个都有其独特的部署步骤。接下来,我们将聚焦于一些具备特殊 <ant> 任务的服务器,并探讨如何与其他服务器协作。

5.1 Tomcat 4.0 和 4.1

Tomcat 4.0 和 4.1 采用相同的部署流程,Ant 会向管理 Servlet 发送 HTTP GET 请求。Tomcat 4.1 让这个过程稍微简便一些,但如果已有适用于 Tomcat 4.0 的部署流程,在后续版本中通常也能正常工作。

5.1.1 部署到 Tomcat 4.0

我们已经介绍过如何部署到 Tomcat 4.0。不过,管理 Servlet 存在安全风险,因为任何人都能获取 Base - 64 编码的认证字符串并控制 Web 服务器。由于 <get> 任务不支持摘要认证,所以不能使用它安全地部署到生产系统,因为任何人都可能监听部署请求并自行发起。

为了保障安全,必须使用 IP 地址阀来保护 Servlet,限制对特定 IP 地址的访问。要实现最高级别的安全,可在 server.xml 中添加以下片段,配置阀以允许从本地服务器发起管理请求:

<Context path="/manager" docBase="manager" 
  debug="0" privileged="true">
  <Valve 
    className="org.apache.catalina.valves.RemoteAddrValve"
    allow="127.0.0.1" />         
</Context>

之前介绍的部署流程在如此配置的系统中能完美运行。

5.1.2 部署到 Tomcat 4.1

在撰写本文时,Tomcat 4.1 仍处于 Alpha 版本阶段。它具备一些特性,使其成为开发目标极具吸引力,例如 JMX 管理 API、专为与构建工具集成而重新设计的管理小程序,以及用于安装和移除应用程序的自有 Ant 任务:

<install url="http://${target.server}:${target.port}/manager"
    username="${target.username}"
    password="${target.password}"
        path="${target.appname}"
         war="file://${webapp.path}"/>

除了 <install> 任务,还有 <reload> <remove> 等任务用于重新加载和移除 Web 应用程序,以及 <list> 任务用于列出所有已加载的应用程序。这些任务将请求传递给重新设计的管理小程序版本,它们似乎可以直接替代我们一直使用的 Tomcat 4.0 部署目标。不过,它们需要一个 failonerror 标志,以便在应用程序缺失时, <remove> 任务不会中断构建。如果现在要使用它,需要在 <condition> 任务中使用 <http> 测试来探测应用程序是否正在运行,然后再进行卸载。

实际上,这些任务只是向我们在之前构建的相同 URL 发送 HTTP GET 请求,它们可能也适用于 Tomcat 4.0。和我们的 <get> 请求一样,密码以 Base - 64 编码形式传输,因此并不安全。

我们认可这些任务的理念,但尚未深入研究它们的长期运行效果。手册声称这些任务仅适用于本地主机,但这实际上是服务器端的配置问题,当前的 Tomcat 4.1 Alpha 版本仍然允许远程管理。为了进行安全的生产部署,必须像配置 Tomcat 4.0 一样,将服务器配置为仅支持本地管理。若要了解这些任务的更多信息,可查阅 Tomcat 文档。

以下是 Tomcat 4.0 和 4.1 部署步骤的对比表格:
| 服务器版本 | 部署方式 | 安全问题 | 特殊任务 |
| — | — | — | — |
| Tomcat 4.0 | 发送 HTTP GET 请求到管理 Servlet | 管理 Servlet 有安全风险, <get> 任务不支持摘要认证 | 无 |
| Tomcat 4.1 | 发送 HTTP GET 请求到管理 Servlet,可使用自有 Ant 任务 | 密码以 Base - 64 编码传输不安全 | <install> <reload> <remove> <list> 等 |

6. 总结

通过上述内容,我们详细介绍了从本地服务器部署到远程服务器部署的完整流程,以及针对特定应用服务器(如 Tomcat 4.0 和 4.1)的部署方法。整个部署流程虽然复杂,但为我们带来了显著的优势:
- 可扩展性 :添加新服务器变得简单,只需添加两个配置文件,无需修改构建文件本身,方便开发者将自己的系统集成到项目中,同时确保生产系统的安全。
- 灵活性 :能够支持多种不同的服务器类型,每个服务器可根据自身需求定制安装构建文件,这些文件还可在不同项目中复用或进行定制以执行额外任务。
- 安全性 :部署过程适用于安全系统,可通过 SSH 隧道工作,在一定程度上保障了部署的安全性。

在实际应用中,我们可以根据具体需求选择合适的部署方式和服务器类型。同时,要始终关注安全问题,采取必要的措施来保护系统和应用程序。希望这些内容能帮助你构建一个高效、安全且可扩展的生产部署流程。

下面是一个简单的决策流程图,帮助你选择合适的部署方式:

graph LR
    A[选择部署目标] --> B{是否为本地服务器}
    B -- 是 --> C[使用本地部署流程]
    B -- 否 --> D{是否为 Tomcat 服务器}
    D -- 是 --> E{是 Tomcat 4.0 还是 4.1}
    E -- Tomcat 4.0 --> F[使用 Tomcat 4.0 部署流程]
    E -- Tomcat 4.1 --> G[考虑使用自有 Ant 任务部署]
    D -- 否 --> H[根据服务器特性选择合适部署方式]

通过合理运用这些技术和方法,你可以确保应用程序在各种环境下都能顺利部署和运行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值