Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:66772 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 59097 invoked from network); 23 Mar 2013 22:01:28 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 23 Mar 2013 22:01:28 -0000 Authentication-Results: pb1.pair.com header.from=tyra3l@gmail.com; sender-id=pass Authentication-Results: pb1.pair.com smtp.mail=tyra3l@gmail.com; spf=pass; sender-id=pass Received-SPF: pass (pb1.pair.com: domain gmail.com designates 209.85.223.174 as permitted sender) X-PHP-List-Original-Sender: tyra3l@gmail.com X-Host-Fingerprint: 209.85.223.174 mail-ie0-f174.google.com Received: from [209.85.223.174] ([209.85.223.174:41298] helo=mail-ie0-f174.google.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 19/D1-44422-6362E415 for ; Sat, 23 Mar 2013 17:01:26 -0500 Received: by mail-ie0-f174.google.com with SMTP id aq17so3106283iec.19 for ; Sat, 23 Mar 2013 15:01:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:x-received:in-reply-to:references:date:message-id :subject:from:to:cc:content-type; bh=++ECqw1IrGmKcRQ2ZGYAJjIniMEmFA95xoNFGq2L/4U=; b=gBTdJCHQMu4ljIlio5LB78IhgZ7ez7I1EvjAv4zKT6U2E/ijYGEBIupyhT6G0YO+hs GoGj4H05vmgbOiCUPbSbE5L3JCwPp/Em+ilc9HzAiIP81ZzUConTIiiwLPaEx1jCc5qw IimnCsjyPfOoH0sbUDfh5ErHOdXkynA8Pzq+soJGoy8yJYWV94KQDyeIsvIDKT2xiWhe UuWH2u5Tv5rEF6eRPMRtpP3Rp2NqCJZr0ktKtomPJzqzvWCAuM0aSfegWEeIRESFrWxg CQg+H/Z826YnkXA4RrrRE6eavFcx0kec8uLp6d0ahW3jRzFuD5M8PWuevdFpwqJmf4HJ SuhA== MIME-Version: 1.0 X-Received: by 10.42.93.19 with SMTP id v19mr3616021icm.39.1364076083475; Sat, 23 Mar 2013 15:01:23 -0700 (PDT) Received: by 10.50.114.137 with HTTP; Sat, 23 Mar 2013 15:01:23 -0700 (PDT) In-Reply-To: <514DFAFF.4010901@lerdorf.com> References: <514DFAFF.4010901@lerdorf.com> Date: Sat, 23 Mar 2013 23:01:23 +0100 Message-ID: To: Rasmus Lerdorf Cc: PHP internals Content-Type: multipart/alternative; boundary=90e6ba614d0666fd4804d89eb619 Subject: Re: [PHP-DEV] Continuous Integration Atomic Deploys and PHP 5.5 From: tyra3l@gmail.com (Ferenc Kovacs) --90e6ba614d0666fd4804d89eb619 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable On Sat, Mar 23, 2013 at 7:57 PM, Rasmus Lerdorf wrote: > One of the things I have been helping companies with for the past couple > of years is sorting through the complexities of deploying PHP code with > the least possible interruption to the running site. > > With APC you can achieve atomic deploys without a server restart and > without clearing the opcode cache through careful use of the > realpath/stat cache and a clearstatcache() call in the front-controller. > The logic behind it is a little complicated, but it goes something like > this: > > - Request 1 starts before the deploy and loads script A, B > - Deploy to a separate directory and the docroot symlink now points to he= re > - Request 2 starts and loads A, B, C > - Request 1 was a bit slow and gets to load C now > > So this is the scenario that trips up most deploy systems because > request 1 would load a version of C that doesn't match A and B already > loaded and thus this deploy is not atomic even though all the files were > deployed atomically. > > With the realpath/stat cache and APC's use of inodes as cache keys > request 1 will get the inode from the previous version of C, so it will > not be out of sync with the previously loaded A and B. In request 2 we > put a clearstatcache() call in the front-controller triggered usually by > comparing the version baked into the front-controller with a version > number written to shared memory. So by detecting that there is a more > recent version of the code available in the front-controller at the > start of a request we can make sure that all new requests will see the > new code while requests that were executing when the deploy happened > will continue to use the previous version until they are done. > > Now, with PHP 5.5 and the new OPcache things are a bit different. > OPcache is not inode-based so we can't use the same trick. Since we are > focusing on a single cache implementation I think we should document a > preferred approach to this common scenario. I see a couple of approaches: > > 1. Turn off validate_timestamps and always do a graceful server restart > on a deploy > + effective > - slow and annoying when you deploy a lot, especially companies who do > a lot of A/B testing and feature-based development with potentially > hundreds of small code and config deploys to ramp features up/down > throughout the day. Being able to invalidate a single cache entry might > mean you could avoid doing the full restart on a simple config-file > deploy, but currently opcache can't do that(*) > > 2. Do something interesting with revalidate_freq. If we always knew that > the file stat happened at :00 of the minute and we deploy at :01 then > perhaps we could get away with not doing anything else > + no server restarts and no cache clears > - scripts that take longer than 59 seconds to complete would be a > problem and the code currently can't guarantee timestamps checks at > regular intervals like this > > 3. Add some magic to OPcache that gives it the concept of a server > request. Almost like a DB transaction. Currently on a cache reset, > OPcache lets currently executing entries complete, but this is on a > per-entry basis. A web request is made up of many of these entries so > unless they are somehow bracketed it doesn't help us. So something like > opcache_request_begin()/opcache_request_done() might work. > + no server restarts and no cache clears > - This might get way too complex, especially since userspace may never > call opcache_request_done() which means we would need some sort of > timeout mechanism as well > > (*) for single-file deploys, such as a config-change to ramp a feature > up or down you could blacklist the config file and use apcu/yac or some > other user cache mechanism to speed things up. > > None of these approaches sound ideal to me, and that includes the > existing inode-caching APC approach. Too brittle and complicated. Any > other ideas? > > -Rasmus > > -- > PHP Internals - PHP Runtime Development Mailing List > To unsubscribe, visit: http://www.php.net/unsub.php > > realpath the document root(which is a symlink to the actual release directory) from your index.php/bootstrap file and use that as a base path for making absolute paths everywhere? that way the requests started before the symlink switch will continue with the old version but requests started after the switch will use the files from the new revision. ofc. you can still have issues like an ajax request from the old version gets served by the new version, and if you have more than one server sooner or later you will/have to sacrifice something from the CAP trio. --=20 Ferenc Kov=C3=A1cs @Tyr43l - http://tyrael.hu --90e6ba614d0666fd4804d89eb619--