ホームページ バックエンド開発 PHPチュートリアル PHP コードを正しく公開する例を共有する

PHP コードを正しく公開する例を共有する

Mar 12, 2018 pm 02:44 PM
php 共有


ほぼすべての PHP プログラマーがコードを公開しており、そのコードは FTP または rsync を介して同期したり、svn または git を介して更新したりすることができます。活発なプロジェクトでは、1 日に数回コードがリリースされることがありますが、詳細に注意を払う人はほとんどいないのが現実で、実際には多くの落とし穴があり、知らないうちに落とし穴にはまっている可能性があります。

適切に実装されたパブリッシング システムは、少なくともアトミック パブリッシングをサポートする必要があります。各バージョンが独立した状態を表す場合、リリース期間中は、すべてのリクエストは単一の状態でのみ実行できます。これはアトミック リリースのサポートと呼ばれます。一方、リクエストがリリース中に異なる状態にまたがる場合、それはアトミック リリースとは言えません。説明するための例を示します: include a.php の場合、リクエストに 2 つの <code>include 两个 PHP 文件,分别是 a.phpb.php,当 include a.php 完成后,发布代码,接着 include b.php,如果处理不当的话,那么就可能会导致旧版本的 a.php 和新版本的 b.php 同时存在于同一个请求之中,换句话说就是没有实现原子发布。

开源世界里有很多不错的发布代码工具,比如  ruby 社区的 capistrano,其流程大致就是发布代码到一个全新的目录,然后再软链接到真正的发布目录。

├── current -> releases/v1
└── releases
    ├── v1
    │   ├── foo.php
    │   └── bar.php
    └── v2
        ├── foo.php
        └── bar.php
ログイン後にコピー

不过鉴于 PHP 本身的特殊性,如果只是简单套用上面的流程,那么将很难实现真正的原子发布。要理清个中缘由,还需要了解一下 PHP 中的两个 Cache 的概念:

  • opcode cache

  • PHP コードを正しく公開する例を共有する cache

先聊聊 opcode cache,基本就是 apc 或者 zend opcode,关于它的作用,大家都已经很熟悉,不必多言,需要注意的是 apc 的 bug 很多,比如开启了 apc.enable_cli 配置后就会有很多灵异问题,所以说 opcode cache 还是尽可能使用 zend opcache 吧,如果需要缓存数据,可以用 apcu。此外 apczend opcode 对缓存键的选择有所差异:apc 选择的是文件的 inodezend opcode 选择的是文件的 path

再聊聊 PHP コードを正しく公開する例を共有する cache,它的作用是缓冲获取文件信息的 IO 操作,大多数时候它对我们而言是透明的,以至于很多人都不知道它的存在,需要注意的是 PHP コードを正しく公開する例を共有する cache 是进程级别的,也就是说,每一个 php-fpm 进程都有自己独立的 PHP コードを正しく公開する例を共有する cache

假设在发布代码期间,opcode cache 或者 PHP コードを正しく公開する例を共有する cache 里的数据出现过期,那么就会出现一部分缓存是旧文件,一部分缓存是新文件的非原子发布的情况,为了避免出现这种情况,我们应该保证缓存过期时间足够长,最好是除非我们手动刷新,否则永远不过期,对应到配置上就是:关闭 apc.stat、opcache.validate_timestamps 配置,设置足够大的 PHP コードを正しく公開する例を共有する_cache_size、PHP コードを正しく公開する例を共有する_cache_ttl 配置,必要的监控总是有好处的。

相关的技术细节特别琐碎,建议大家仔细阅读如下资料:

  • PHP コードを正しく公開する例を共有する_cache
    PHP’s OPCache extension review
    Atomic PHP コードを正しく公開する例を共有するs at Etsy
    Cache invalidation for scripts in symlinked folders
    ログイン後にコピー

在采用软链接发布代码的时候,通常遇到的第一个问题多半是新代码不生效!即便调用了 apc_clear_cache 或者 opcache_reset 方法也无效,重启 php-fpm 自然是能够解决问题,不过对脚本语言来说重启太重了!难道除了重启就没有别的办法了么?

事实上之所以会出现这样的问题,主要是因为 opcode cache 是通过 PHP コードを正しく公開する例を共有する cache 获取文件信息,即便软链接已经指向了新位置,但是如果 PHP コードを正しく公開する例を共有する cache 里还保存着旧数据的话,opcode cache 依然无法知道新代码的存在,缺省情况下,PHP コードを正しく公開する例を共有する_cache_ttl 缓存有效期是两分钟,这意味着发布代码后,可能要两分钟才能生效。为了让发布尽快生效,需要以进程为单位清除 PHP コードを正しく公開する例を共有する cache

<?php

    $key = &#39;php.pid_&#39; . getmypid();    if (($rev = apc_fetch($key)) != DEPLOY_VERSION) {        if($rev < DEPLOY_VERSION) {
            apc_store($key, DEPLOY_VERSION);
        }

        clearstatcache(true);
    }
ログイン後にコピー

如此在 apc 环境下基本就能工作了,但是在 zend opcode 环境下还可能有问题。因为在缺省情况下 opcache.revalidate_path 是关闭的,此时会缓存未解析的符号链接的值,这会导致即便软链接指向修改了,也无法生效,所以在使用 zend opcode 的时候,如果使用了软链接,视情况可能需要把 opcache.revalidate_pathPHP

ファイル、つまり a.phpb.php > が必要だとします。 が完了したらコードを解放し、include b.php を正しく処理しないと、古いバージョンの a .php が生成される可能性があります。新しいバージョンの b.php が同じリクエスト内に同時に存在します。つまり、アトミック パブリッシングは実装されていません。 🎜🎜オープンソースの世界には、🎜ruby🎜コミュニティのcapistranoなど、優れたコード公開ツールがたくさんあります。そのプロセスは、大まかに言うと、コードを新しいディレクトリに公開してから、実際のリリースディレクトリにソフトリンクします。 🎜
    fastcgi_param SCRIPT_FILENAME $PHP コードを正しく公開する例を共有する_root$fastcgi_script_name;    fastcgi_param DOCUMENT_ROOT $PHP コードを正しく公開する例を共有する_root;
ログイン後にコピー
ログイン後にコピー
🎜しかし、🎜PHP🎜自体の特殊性を考慮すると、上記の処理を単純に適用しただけでは真のアトミックリリースを実現することは困難です。理由を明確にするには、🎜PHP🎜 の 2 つの Cache の概念も理解する必要があります: 🎜
  • 🎜🎜オペコード キャッシュ🎜 🎜
  • 🎜🎜リアルパス キャッシュ🎜🎜
🎜まず オペコード キャッシュ について話しましょう。基本的には apc または です。 > zend opcode については、誰もがその役割をよく知っています。言うまでもなく、apc には多くのバグがあることに注意してください。たとえば、apc.enable_cli 設定がオンになった後は、奇妙な問題なので、opcode Cache はできるだけ zend opcache を使用する必要があります。データをキャッシュする必要がある場合は、apcu を使用できます。さらに、apczend opcode ではキャッシュ キーの選択が異なります。apc はファイルの inode を選択します。 zend opcode は、ファイルの path を選択します。 🎜🎜 もう一度 PHP コードを正しく公開する例を共有する キャッシュ について話しましょう。その機能は 🎜IO🎜 操作をバッファリングしてファイル情報を取得することです。存在しますが、PHP コードを正しく公開する例を共有する キャッシュ はプロセス レベルであることに注意してください。つまり、各 php-fpm プロセスには独自の独立した PHP コードを正しく公開する例を共有する キャッシュ があります。コード> >。 🎜🎜 コードのリリース中に、opcode Cache または PHP コードを正しく公開する例を共有する Cache 内のデータの有効期限が切れると、キャッシュの一部が古いファイルになり、キャッシュの一部は新しいファイルです。この状況を回避するには、キャッシュの有効期限を手動で更新しない限り期限切れにならないようにするのが最善です。設定は次のとおりです: close apc.stat、opcache.validate_timestamps 設定。 PHP コードを正しく公開する例を共有する_cache_size および PHP コードを正しく公開する例を共有する_cache_ttl 設定を十分な大きさに設定し、必要な監視を実行することが常に有益です。 🎜🎜関連する技術的な詳細は非常に簡単なので、次の情報を注意深く読むことをお勧めします: 🎜
  • <?php// PHP コードを正しく公開する例を共有する:releaserun("cd {{PHP コードを正しく公開する例を共有する_path}} && if [ -h release ]; then rm release; fi");
    run("ln -s $releasePath {{PHP コードを正しく公開する例を共有する_path}}/release");// PHP コードを正しく公開する例を共有する:symlinkrun("cd {{PHP コードを正しく公開する例を共有する_path}} && ln -sfn {{release_path}} current");
    run("cd {{PHP コードを正しく公開する例を共有する_path}} && rm release");?>
    ログイン後にコピー
    ログイン後にコピー
🎜 コードを公開するとき。ソフト リンクを使用すると、通常最初に発生する問題は、新しいコードが有効にならないことです。 apc_clear_cache メソッドや opcache_reset メソッドを呼び出しても機能しません。php-fpm を再起動すると自然に解決しますが、スクリプト言語にとって再起動は重すぎます。再起動する以外に方法はないのでしょうか? 🎜🎜実際、このような問題が発生する主な理由は、ソフト リンクが新しい場所を指していても、opcode CachePHP コードを正しく公開する例を共有する Cache を通じてファイル情報を取得するためです。ただし、古いデータがまだ PHP コードを正しく公開する例を共有する キャッシュ に保存されている場合、opcode Cache は新しいコードの存在を認識できません。デフォルトでは、PHP コードを正しく公開する例を共有する_cache_ttl キャッシュの有効期間は 2 分です。コードが発行されてから有効になるまでに最大 2 分かかる場合があります。リリースをできるだけ早く有効にするには、プロセス単位で PHP コードを正しく公開する例を共有する キャッシュ をクリアする必要があります: 🎜
shell> strace ln -sfn releases/foo currentsymlink("releases/foo", "current")      = -1 EEXIST (File exists)unlink("current")                       = 0symlink("releases/foo", "current")      = 0
ログイン後にコピー
ログイン後にコピー
🎜これは基本的に apc 環境で動作します。ただし、zend opcode 環境に問題がある可能性もあります。 opcache.revalidate_path はデフォルトでオフになっているため、未解決のシンボリック リンクの値がキャッシュされるため、zend opcode を使用する場合、ソフト リンクが有効になりません。 、ソフト リンクが使用されている場合、状況に応じて opcache.revalidate_path をアクティブにする必要がある場合があります。 🎜

详细介绍参考:PHP’s OPCache extension review。

BTW:如果需要手动重置 opcode cache,需要注意的是因为它是基于 SAPI 的概念,所以不能直接在命令行下调用 apc_clear_cache 或者 opcache_reset 方法来重置缓存,当然办法总是有的,那就是使用 CacheTool 在命令行下模拟 fastcgi 请求。

分析到这里,我们不妨反思一下:在 PHP 中原子发布之所以是一个棘手的问题,归根结底是因为软链接和缓存之间的的矛盾。不管是 opcode cache 还是 PHP コードを正しく公開する例を共有する cache,都是 PHP 固有的缓存特性,基于客观需要无法绕开,如此说来是否有办法绕开软链接,使其成为马奇诺防线呢?答案是 NGINX 的 $PHP コードを正しく公開する例を共有する_root:

    fastcgi_param SCRIPT_FILENAME $PHP コードを正しく公開する例を共有する_root$fastcgi_script_name;    fastcgi_param DOCUMENT_ROOT $PHP コードを正しく公開する例を共有する_root;
ログイン後にコピー
ログイン後にコピー

有了 $PHP コードを正しく公開する例を共有する_root,即便 DOCUMENT_ROOT 目录中含有软链接,NGINX 也会把软链接指向的真正的路径发给 PHP,也就是说,对 PHP 而言,软链接已经不存在了!不过作为代价,每一次请求,NGINX 都要通过相对昂贵的 IO 操作获取 $PHP コードを正しく公開する例を共有する_root 的值,通过 strace 命令我们能监控这一过程,下图从 currentfoo 的过程:

PHP コードを正しく公開する例を共有する

在本例中,压测发现使用 $PHP コードを正しく公開する例を共有する_root 后,性能下降了大约 5% 左右,不过明眼人一下就能发现,虽然 $PHP コードを正しく公開する例を共有する_root 导致了 lstatreadlink 操作,但是 lstat 操作的次数是和目录深度成正比的,也就是说目录越深,执行的 lstat 次数越多,性能下降也就越大。如果能够降低发布目录的深度,那么可以预计还能降低一些性能损耗。

结尾介绍一下 Deployer,它是 PHP 中做得比较好的工具,有很多特色,比如支持并行发布,具体演示如下图,左边是串行,右边是并行,使用「vvv」能得到更详细信息:

PHP コードを正しく公開する例を共有する

不过 Deployer 在原子发布上有一点瑕疵,具体见 release/symlink 代码:

<?php// PHP コードを正しく公開する例を共有する:releaserun("cd {{PHP コードを正しく公開する例を共有する_path}} && if [ -h release ]; then rm release; fi");
run("ln -s $releasePath {{PHP コードを正しく公開する例を共有する_path}}/release");// PHP コードを正しく公開する例を共有する:symlinkrun("cd {{PHP コードを正しく公開する例を共有する_path}} && ln -sfn {{release_path}} current");
run("cd {{PHP コードを正しく公開する例を共有する_path}} && rm release");?>
ログイン後にコピー
ログイン後にコピー

release 的时候,它是先删除再创建,是一个两步的非原子操作,在 symlink 的时候,看上去「ln -sfn」是单步原子操作,实际上也是错误的:

shell> strace ln -sfn releases/foo currentsymlink("releases/foo", "current")      = -1 EEXIST (File exists)unlink("current")                       = 0symlink("releases/foo", "current")      = 0
ログイン後にコピー
ログイン後にコピー

通过 strace 我们能清晰的看到,虽然表面上使用「ln -sfn」是一步操作,但是内部依然是按照先删除再创建的逻辑执行的,实际上这里应该搭配使用「ln & mv」

shell> ln -sfn releases/foo current.tmpshell> mv -fT current.tmp current
ログイン後にコピー

先通过 ln 创建一个临时的软链接,再通过 mv 实现原子操作,此时如果使用 strace 监控,会发现 mv「T」 选项实际上仅仅执行了一个 rename 操作,所以是原子的。

BTW:在使用「ln -sfn」前后,如果使用 stat 查看新旧文件的 inode 的话,可能会发现它们拥有一样的 inode 值,看上去和我们的结论相悖,其实不然,实际上只是复用删除值而已(如果想验证,注意 Linux 会复用,Mac 不会复用)。

据说一千个人的心中就有一千个哈姆雷特,不过我希望所有的 PHP 程序员在发布 PHP 代码的时候都能采用一种方法,那就是本文介绍的方法,正确的方法。

相关推荐:

php代码标志基础讲解

提高PHP代码质量的方法

JS和PHP代码实现用户输入数字后显示最大的值

以上がPHP コードを正しく公開する例を共有するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

Ubuntu および Debian 用の PHP 8.4 インストールおよびアップグレード ガイド Ubuntu および Debian 用の PHP 8.4 インストールおよびアップグレード ガイド Dec 24, 2024 pm 04:42 PM

PHP 8.4 では、いくつかの新機能、セキュリティの改善、パフォーマンスの改善が行われ、かなりの量の機能の非推奨と削除が行われています。 このガイドでは、Ubuntu、Debian、またはその派生版に PHP 8.4 をインストールする方法、または PHP 8.4 にアップグレードする方法について説明します。

今まで知らなかったことを後悔している 7 つの PHP 関数 今まで知らなかったことを後悔している 7 つの PHP 関数 Nov 13, 2024 am 09:42 AM

あなたが経験豊富な PHP 開発者であれば、すでにそこにいて、すでにそれを行っていると感じているかもしれません。あなたは、運用を達成するために、かなりの数のアプリケーションを開発し、数百万行のコードをデバッグし、大量のスクリプトを微調整してきました。

PHP 開発用に Visual Studio Code (VS Code) をセットアップする方法 PHP 開発用に Visual Studio Code (VS Code) をセットアップする方法 Dec 20, 2024 am 11:31 AM

Visual Studio Code (VS Code とも呼ばれる) は、すべての主要なオペレーティング システムで利用できる無料のソース コード エディター (統合開発環境 (IDE)) です。 多くのプログラミング言語の拡張機能の大規模なコレクションを備えた VS Code は、

JSON Web Tokens(JWT)とPHP APIでのユースケースを説明してください。 JSON Web Tokens(JWT)とPHP APIでのユースケースを説明してください。 Apr 05, 2025 am 12:04 AM

JWTは、JSONに基づくオープン標準であり、主にアイデンティティ認証と情報交換のために、当事者間で情報を安全に送信するために使用されます。 1。JWTは、ヘッダー、ペイロード、署名の3つの部分で構成されています。 2。JWTの実用的な原則には、JWTの生成、JWTの検証、ペイロードの解析という3つのステップが含まれます。 3. PHPでの認証にJWTを使用する場合、JWTを生成および検証でき、ユーザーの役割と許可情報を高度な使用に含めることができます。 4.一般的なエラーには、署名検証障害、トークンの有効期限、およびペイロードが大きくなります。デバッグスキルには、デバッグツールの使用とロギングが含まれます。 5.パフォーマンスの最適化とベストプラクティスには、適切な署名アルゴリズムの使用、有効期間を合理的に設定することが含まれます。

PHPでHTML/XMLを解析および処理するにはどうすればよいですか? PHPでHTML/XMLを解析および処理するにはどうすればよいですか? Feb 07, 2025 am 11:57 AM

このチュートリアルでは、PHPを使用してXMLドキュメントを効率的に処理する方法を示しています。 XML(拡張可能なマークアップ言語)は、人間の読みやすさとマシン解析の両方に合わせて設計された多用途のテキストベースのマークアップ言語です。一般的にデータストレージに使用されます

母音を文字列にカウントするPHPプログラム 母音を文字列にカウントするPHPプログラム Feb 07, 2025 pm 12:12 PM

文字列は、文字、数字、シンボルを含む一連の文字です。このチュートリアルでは、さまざまな方法を使用してPHPの特定の文字列内の母音の数を計算する方法を学びます。英語の母音は、a、e、i、o、u、そしてそれらは大文字または小文字である可能性があります。 母音とは何ですか? 母音は、特定の発音を表すアルファベットのある文字です。大文字と小文字など、英語には5つの母音があります。 a、e、i、o、u 例1 入力:string = "tutorialspoint" 出力:6 説明する 文字列「TutorialSpoint」の母音は、u、o、i、a、o、iです。合計で6元があります

PHPでの後期静的結合を説明します(静的::)。 PHPでの後期静的結合を説明します(静的::)。 Apr 03, 2025 am 12:04 AM

静的結合(静的::) PHPで後期静的結合(LSB)を実装し、クラスを定義するのではなく、静的コンテキストで呼び出しクラスを参照できるようにします。 1)解析プロセスは実行時に実行されます。2)継承関係のコールクラスを検索します。3)パフォーマンスオーバーヘッドをもたらす可能性があります。

PHPマジックメソッド(__construct、__destruct、__call、__get、__setなど)とは何ですか? PHPマジックメソッド(__construct、__destruct、__call、__get、__setなど)とは何ですか? Apr 03, 2025 am 12:03 AM

PHPの魔法の方法は何ですか? PHPの魔法の方法には次のものが含まれます。1。\ _ \ _コンストラクト、オブジェクトの初期化に使用されます。 2。\ _ \ _リソースのクリーンアップに使用される破壊。 3。\ _ \ _呼び出し、存在しないメソッド呼び出しを処理します。 4。\ _ \ _ get、dynamic属性アクセスを実装します。 5。\ _ \ _セット、動的属性設定を実装します。これらの方法は、特定の状況で自動的に呼び出され、コードの柔軟性と効率を向上させます。

See all articles