Zope/Plone 在生产部署后重新加载代码

Zope/Plone code reload after deployment on production

有没有办法在生产时重新加载代码而无需重新启动 Zope? 新特性几乎2天实现一次,还得上传到服务器。目前唯一可行的方法是重新启动 zeo 服务器和所有实例。不能使用 "plone.reload" 因为它只在调试模式打开时在开发环境中工作。下面是buildout.cfg内容

[buildout]


  parts =
#    instance
        zeo
        client1
        client2
        client3
        zopepy
        zopeskel
        test
#    mysql
#    varnish-build
#    varnish
    supervisor
    pidproxy

extends =
    https://dist.plone.org/versions/zope-2-13-19-versions.cfg
find-links =
    https://dist.plone.org/release/4.2.4
    https://dist.plone.org/thirdparty
extensions =
    mr.developer
#    buildout.dumppickedversions
sources = sources
versions = versions
develop =

[versions]
plone.recipe.zeoserver = 1.3.1
plone.recipe.zope2instance = 4.2.8
five.localsitemanager = 2.0.5
Products.PluginRegistry = 1.3
Products.CMFCore = 2.2.7
Products.GenericSetup = 1.7.3
Products.ZSQLMethods = 2.13.4
zope.interface = 3.6.7
zope.app.publication = 3.12.0
#setuptools = 17.1.1
funcsigs = 0.4
openpyxl = 2.4.0
plone.reload = 2.0.2

[zeo]
recipe = plone.recipe.zeoserver
zeo-address = 127.0.0.1:9100
zeo-var = ${buildout:directory}/var
blob-storage = ${zeo:zeo-var}/blobstorage
#ggs = plone.app.blob

[client1]
recipe = plone.recipe.zope2instance
http-address = 9081
zeo-client = on
zeo-address =  ${zeo:zeo-address}
shared-blob = on
blob-storage =  ${zeo:zeo-var}/blobstorage
user = admin:Slick_RP@21!
products = ${buildout:directory}/matrix_git/prod/
debug-mode = off
verbose-security = off
eggs =
#    pillow
    mysql-python
    simplejson
    haversine
    openpyxl
    requests
    httpagentparser
    ordereddict
    python-memcached
#    python-crontab
#   setuptools
    Products.CMFCore
    Products.ZMySQLDA
#    Products.SQLAlchemyDA
    Products.PluggableAuthService
#    Products.ZopeProfiler
#    Products.MemoryProfiler
#    reportlab
    Products.BeakerSessionDataManager
    collective.fsexternalmethod
    plone.reload
zope-conf-additional =
    extensions ${buildout:directory}/matrix_git/Extensions
    <product-config beaker>
        session.type            file
        session.data_dir        ${buildout:directory}/var/sessions/data
        session.lock_dir        ${buildout:directory}/var/sessions/lock
        session.key             beaker.session
        session.secret          secret
    </product-config>
zcml =
    collective.fsexternalmethod
    plone.reload
event-log-max-size = 5 MB
event-log-old-files = 5
access-log-max-size = 20 MB
access-log-old-files = 10

[client2]
recipe = plone.recipe.zope2instance
http-address = 9082
zeo-client = ${client1:zeo-client}
zeo-address = ${client1:zeo-address}
blob-storage = ${client1:blob-storage}
shared-blob = ${client1:shared-blob}
user = ${client1:user}
products = ${client1:products}
debug-mode = off
verbose-security = off
eggs = ${client1:eggs}
zcml = ${client1:zcml}
zope-conf-additional = ${client1:zope-conf-additional}
event-log-max-size = ${client1:event-log-max-size}
event-log-old-files = ${client1:event-log-old-files}
access-log-max-size = ${client1:access-log-max-size}
access-log-old-files = ${client1:access-log-old-files}

[client3]
recipe = plone.recipe.zope2instance
http-address = 9083
zeo-client = ${client1:zeo-client}
zeo-address = ${client1:zeo-address}
blob-storage = ${client1:blob-storage}
shared-blob = ${client1:shared-blob}
user = ${client1:user}
products = ${client1:products}
debug-mode = off
verbose-security = off
eggs = ${client1:eggs}
zcml = ${client1:zcml}
zope-conf-additional = ${client1:zope-conf-additional}
event-log-max-size = ${client1:event-log-max-size}
event-log-old-files = ${client1:event-log-old-files}
access-log-max-size = ${client1:access-log-max-size}
access-log-old-files = ${client1:access-log-old-files}
[zopepy]
recipe = zc.recipe.egg
eggs = ${client1:eggs}
interpreter = zopepy
scripts = zopepy

[test]
recipe = zc.recipe.testrunner
defaults = ['--auto-color', '--auto-progress']
eggs =
    ${client1:eggs}

[zopeskel]
recipe = zc.recipe.egg
eggs =
    ZopeSkel
    PasteScript

[mysql]
recipe = zest.recipe.mysql
# Note that these urls usually stop working after a while... thanks...
mysql-url = http://downloads.mysql.com/archives/mysql-5.0/mysql-5.0.86.tar.gz
mysql-python-url = http://pypi.python.org/packages/source/M/MySQL-python/MySQL-python-1.2.3.tar.gz

[varnish-build]
recipe = zc.recipe.cmmi
url = ${varnish:download-url}

[varnish]
recipe = plone.recipe.varnish
daemon = ${buildout:parts-directory}/varnish-build/sbin/varnishd
bind = 127.0.0.1:8000
backends = 127.0.0.1:8080
cache-size = 50M

[pidproxy]
recipe = zc.recipe.egg
eggs = supervisor
scripts = pidproxy

[supervisor]
recipe = collective.recipe.supervisor
port = 127.0.0.1:24007
serverurl = http://127.0.0.1:24007
programs =
#    10 mysql      ${buildout:directory}/bin/pidproxy [${buildout:directory}/var/mysql/mysql.pid ${buildout:directory}/parts/mysql/install/bin/mysqld_safe --pid-file=${buildout:directory}/var/mysql/mysql.pid --socket=${buildout:directory}/var/mysql.socket] ${buildout:directory} true
    20 zeo       ${buildout:directory}/bin/zeo [console] ${buildout:directory} true
    30 client1   ${buildout:directory}/bin/client1 [console] ${buildout:directory} true
    40 client2   ${buildout:directory}/bin/client2 [console] ${buildout:directory} true
    50 client3   ${buildout:directory}/bin/client3 [console] ${buildout:directory} true

是的,有办法,尽管我在生产中从未这样做过在开发时这是一个很好的time-saver , 在 browser-view:

内重新加载
from plone.reload.code import reload_code
from Products.Five.browser import BrowserView


class View(BrowserView):

    def __call__(self):
        reload_code()
        return 'Code loaded.'

然后使用您在网站上注册时使用的名称调用视图。这甚至在 non-debug-mode 中有效,而实例在后台 运行。使用独立实例进行测试 (non-ZEO)。

如果您部署得如此频繁,您可以在低流量时间(即晚上)部署。

如果网站应该始终运行,您可以有两组 Plone 实例:一组处于活动状态并为请求提供服务,第二组不活动。

更新时,离线服务器被更新,完成后,切换(例如 HAProxy)以替换活动服务器。

您甚至可以让所有服务器始终可用,但为了更新,请在更新时让一些服务器离线。

正如其他人和您所指出的那样,我绝不会在生产中使用 plone.reload 或类似的开发工具。