作者都是各自领域经过审查的专家,并撰写他们有经验的主题. 我们所有的内容都经过同行评审,并由同一领域的Toptal专家验证.
Elene Latsoshvili的头像

Elene Latsoshvili

Elene是一名拥有12年以上经验的全栈开发人员. 她是语言/堆栈不可知论者,但她的主要领域是Java和JavaScript.

Expertise

Previously At

佐治亚银行
Share

当涉及到更新实时应用程序时, 有两种根本不同的方法来解决这个问题.

在第一种方法中,我们对系统的状态进行增量更改. For example, we update files, 修改环境属性, 安装额外的必需品, and so on. 第二种方法, 我们拆掉整个机器,用新的映像和声明性配置(例如, 使用Kubernetes).

Laravel部署变得简单

本文主要介绍相对较小的应用程序, 哪些可能不托管在云中, 不过我会提到怎么做 Kubernetes可以提供很大的帮助 我们的部署超出了“无云”场景. 我们还将讨论成功执行更新的一些一般问题和技巧,这些问题和技巧可能适用于各种不同的情况, 不仅仅是使用Laravel部署.

出于演示的目的,我将使用 Laravel 示例,但请记住,任何PHP应用程序都可以使用类似的方法.

Versioning

对于初学者来说,知道当前部署在生产环境中的代码版本是至关重要的. 它可以包含在某个文件中,或者至少包含在文件夹或文件的名称中. 至于命名,如果我们遵循的标准做法 语义版本控制,我们可以包含更多的信息,而不仅仅是一个数字.

看两个不同的版本, 这些附加的信息可以帮助我们很容易地理解它们之间引入的变化的性质.

显示语义版本控制解释的图像.

版本控制从版本控制系统开始,比如Git. 假设我们已经为部署准备了一个版本,例如,版本1.0.3. 当涉及到组织这些版本和代码流时, 有不同的开发风格,如 基于主干的开发和Git流程,您可以根据团队的偏好和项目的具体情况选择或混合使用. 最后,我们很可能会在我们的主分支上相应地标记我们的版本.

提交之后,我们可以像这样创建一个简单的标签:

git tag v1.0.3

然后我们在执行push命令时包含标签:

git push --tags

我们还可以使用它们的哈希值向旧提交添加标签.

将释放文件发送到目的地

Laravel部署需要时间,即使只是简单地复制文件. 然而,即使不需要太长时间,我们的目标也是要实现的 zero downtime.

Therefore, 我们应该避免就地安装更新,也不应该更改正在使用的文件. Instead, 我们应该部署到另一个目录,只有在安装完全准备好后才进行切换.

实际上,有各种各样的工具和服务可以帮助我们进行部署,例如 Envoyer.io (by Laravel.网站设计师Jack McDade), Capistrano, Deployer, etc. 我还没有在生产中全部使用它们, 因此,我无法提出建议或撰写全面的比较, 让我来展示一下这些产品背后的理念. 如果其中一些(或全部)不能满足您的要求, 您始终可以创建自定义脚本,以您认为合适的最佳方式自动化该过程.

为了演示的目的, 假设我们的Laravel应用程序由Nginx服务器从以下路径提供服务:

/var/www/demo/public

首先,每次进行部署时,我们需要一个目录来放置发布文件. 此外,我们需要一个符号链接,它将指向当前的工作版本. In this case, /var/www/demo 会成为我们的符号链接吗. 重新赋值指针将允许我们快速更改释放.

Laravel部署文件处理

如果我们正在处理一个Apache服务器, 我们可能需要在配置中允许以下符号链接:

+ FollowSymLinks选项

我们的结构可以是这样的:

/ opt /演示/释放/ v0.1.0
/ opt /演示/释放/ v0.1.1
/ opt /演示/释放/ v0.1.2

可能有一些文件需要在不同的部署中持久化.g.,日志文件(如果我们不使用Logstash,显然). 在Laravel部署的情况下,我们可能希望保留存储目录和 .环境配置文件. 我们可以将它们与其他文件分开,并使用它们的符号链接.

为了从Git存储库中获取我们的发布文件, 我们可以使用克隆或存档命令. 有些人使用git clone,但是你不能克隆一个特定的提交或标签. 这意味着将获取整个存储库,然后选择特定的标记. 当存储库包含许多分支或大量历史记录时, 它的大小比发布归档文件大得多. 因此,如果您在生产环境中并不特别需要git仓库,您可以使用 git archive. 这允许我们仅通过特定标记获取文件存档. 使用后者的另一个优点是,我们可以忽略一些不应该出现在生产环境中的文件和文件夹, e.g., tests. 方法中设置export-ignore属性 .gitattributes文件. In the OWASP安全编码实践清单 你可以找到以下建议: “在部署之前,删除测试代码或任何不打算用于生产的功能.”

如果我们从源代码版本控制系统获取发布, Git的归档和导出忽略功能可以帮助我们满足这个需求.

让我们看一看一个简化的脚本(它在生产环境中需要更好的错误处理):

deploy.sh

#!/bin/bash
#如果任何命令失败,终止执行
set -e

从脚本参数中获取标签
TAG=$1
GIT_REMOTE_URL='这里应该是repo的远程url '
BASE_DIR = / opt /演示

如果需要,为版本创建文件夹结构
RELEASE_DIR = BASE_DIR /版本/美元标签
mkdir -p $RELEASE_DIR
mkdir -p $BASE_DIR/storage
cd RELEASE_DIR美元

#从git中以tar格式获取发布文件并解压缩
git archive \
    ——远程= $ GIT_REMOTE_URL \
    --format=tar \
    $TAG \
    | tar xf -

#使用composer安装laravel依赖项
Composer install -o——无交互——无开发

创建到“storage”和“storage”的符号链接.env`
ln -sf $BASE_DIR/.env ./
rm -rf storage && ln -sf $BASE_DIR/storage ./

#运行数据库迁移
PHP工匠迁移——无交互——强制

#运行laravel优化命令
PHP工匠优化
PHP工匠缓存:清除
PHP工匠路由:缓存
PHP工匠视图:清除
PHP工匠配置:缓存

#删除现有的目录或符号链接,并创建一个新的.
NGINX_DIR = / var / www /公众
mkdir -p $NGINX_DIR
rm -f $NGINX_DIR/demo
ln -sf $RELEASE_DIR $NGINX_DIR

为了部署我们的发布版本,我们可以执行以下命令:

deploy.sh v1.0.3

Note: 在这个例子中,v1.0.3是我们版本的git标签.

作曲家制作?

您可能已经注意到,脚本正在调用Composer来安装依赖项. 尽管您在许多文章中都看到过这种方法,但这种方法可能存在一些问题. Generally, 最佳实践是创建应用程序的完整构建,并通过基础设施的各种测试环境推进该构建. 最后,您将得到一个经过彻底测试的构建,它可以安全地部署到生产环境中. 即使每个构建都应该是从头开始可复制的, 这并不意味着我们应该在不同的阶段重新构建应用. 当我们把composer安装在产品上时, 这不是真正的构建与测试的一个,这是什么可能会出错:

  • 网络错误可能会中断下载依赖项.
  • 库供应商可能并不总是遵循SemVer.

网络错误很容易被发现. 我们的脚本甚至会因为出现错误而停止执行. 但是,如果不运行测试,可能很难确定库中的重大更改, 在生产环境中不能这样做吗. 在安装依赖项时, Composer, npm, 其他类似的工具依赖于语义版本控制.minor.patch. If you see ~1.0.2 .在作曲家.Json,表示安装版本1.0.2或最新补丁版本,如1.0.4. If you see ^1.0.2,表示安装版本1.0.2或最新的次要版本或补丁版本,如1.1.0. 我们相信库供应商会在引入任何重大更改时更改主号, 但有时会忽略或不遵守这一要求. 过去也有过这样的案例. 即使你把固定的版本放在你的作曲器里.Json中,您的依赖项可能在其编写器中有~和^.json.

如果它是可访问的,在我看来,一个更好的方法是使用工件存储库(Nexus, JFrog, etc.). 包含所有必要依赖项的发布版本最初只创建一次. 该工件将存储在存储库中,并从中提取用于各种测试阶段. 此外,这将是要部署到生产环境的构建,而不是从Git重新构建应用程序.

保持代码和数据库兼容

我第一眼爱上Laravel的原因是它的作者对细节的关注, 考虑到开发人员的便利性, 并且还将许多最佳实践整合到框架中, 比如数据库迁移.

数据库迁移允许我们使数据库和代码保持同步. 它们的更改都可以包含在一次提交中,因此是一次发布. 但是,这并不意味着可以在不停机的情况下部署任何更改. 在部署过程中的某个时刻, 将会有不同版本的应用程序和数据库在运行. 如果出现问题,这个点甚至可能变成一个周期. 我们应该始终尝试使它们与它们的同伴的先前版本兼容:旧数据库-新应用程序, 新数据库-旧应用程序.

例如,假设有一个 address 列,需要把它分成 address1 and address2. 为了保持所有内容的兼容性,我们可能需要几个版本.

  1. 在数据库中添加两个新列.
  2. 修改应用程序以尽可能使用新字段.
  3. Migrate address 数据到新列并删除它.

这个案例也是一个很好的例子,说明小的更改如何更适合部署. 它们的回滚也更容易. 如果我们几周或几个月都在修改代码库和数据库, 在不停机的情况下更新生产系统可能是不可能的.

Kubernetes的一些伟大之处

即使我们的应用程序的规模可能不需要云, nodes, and Kubernetes, 我还是想提一下k8中的部署是什么样的. In this case, 我们不改变系统, 而是声明我们想要实现什么以及应该在多少个副本上运行什么. 然后,Kubernetes确保实际状态与期望的状态匹配.

只要我们准备好了新版本, 我们在其中创建一个包含新文件的映像, 用新版本标记图像, 然后传给K8s. 后者将在集群内快速启动我们的映像. 它将根据我们提供的准备情况检查等待应用程序准备就绪, 然后不知不觉地将流量重定向到新应用程序,并杀死旧应用程序. 我们可以很容易地有几个版本的应用程序运行,这将让我们执行蓝/绿或金丝雀部署只需几个命令.

如果你感兴趣的话,演讲中有一些令人印象深刻的演示。”伯尔·萨特的《欧博体育app下载》.”

了解基本知识

  • 什么是Laravel ?为什么要使用它?

    Laravel是一个带有MVC架构的PHP框架, 为快速开发提供现代工具和富有表现力的语法, maintenance, testing, and, consequently, 更短的发布周期.

  • Laravel受欢迎吗?

    根据2019年的图表,Laravel是最受欢迎的PHP框架.

  • Laravel的优势是什么?

    Eloquent ORM, 流畅查询生成器, 伟大的文档, 并且始终更新的laracast无疑使该框架脱颖而出. Laravel通过提供像Artisan这样的工具来支持自动化和快速开发.

就这一主题咨询作者或专家.
预约电话
Elene Latsoshvili的头像
Elene Latsoshvili

Located in 第比利斯,格鲁吉亚

Member since 2019年1月21日

作者简介

Elene是一名拥有12年以上经验的全栈开发人员. 她是语言/堆栈不可知论者,但她的主要领域是Java和JavaScript.

Toptal作者都是各自领域经过审查的专家,并撰写他们有经验的主题. 我们所有的内容都经过同行评审,并由同一领域的Toptal专家验证.

Expertise

Previously At

佐治亚银行

世界级的文章,每周发一次.

订阅意味着同意我们的 privacy policy

世界级的文章,每周发一次.

订阅意味着同意我们的 privacy policy

Toptal开发者

加入总冠军® community.