构建生产部署流程
在软件开发过程中,将应用程序部署到生产环境是至关重要的环节。本文将详细介绍如何构建一个生产部署流程,包括本地服务器部署、远程服务器上传以及特定应用服务器的部署等内容。
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=">"/>
</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[根据服务器特性选择合适部署方式]
通过合理运用这些技术和方法,你可以确保应用程序在各种环境下都能顺利部署和运行。
超级会员免费看
1312

被折叠的 条评论
为什么被折叠?



