From c7dfe13bc4984c63848a6662655883dea2feae1b Mon Sep 17 00:00:00 2001 From: Jens Vagelpohl Date: Thu, 28 Nov 2019 13:26:37 -0600 Subject: [PATCH] - Updated Zope documentation sources for Zope 5 --- CHANGES.rst | 3 + docs/INSTALL.rst | 10 +- docs/conf.py | 4 +- docs/index.rst | 4 +- docs/migrations/index.rst | 9 + .../migration => migrations/zope4}/code.rst | 0 .../zope4}/content.rst | 0 .../migration => migrations/zope4}/index.rst | 4 +- .../zope4}/removed.rst | 0 .../migration => migrations/zope4}/zodb.rst | 0 docs/{zope4 => }/news.rst | 59 ++- docs/operation.rst | 359 ++++++++++++++++- docs/wsgi.rst | 375 ------------------ docs/zope4/index.rst | 7 - setup.py | 2 +- 15 files changed, 414 insertions(+), 422 deletions(-) create mode 100644 docs/migrations/index.rst rename docs/{zope4/migration => migrations/zope4}/code.rst (100%) rename docs/{zope4/migration => migrations/zope4}/content.rst (100%) rename docs/{zope4/migration => migrations/zope4}/index.rst (54%) rename docs/{zope4/migration => migrations/zope4}/removed.rst (100%) rename docs/{zope4/migration => migrations/zope4}/zodb.rst (100%) rename docs/{zope4 => }/news.rst (85%) delete mode 100644 docs/wsgi.rst delete mode 100644 docs/zope4/index.rst diff --git a/CHANGES.rst b/CHANGES.rst index 0c3218dac8..2c19d14cf2 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -9,6 +9,9 @@ https://github.com/zopefoundation/Zope/blob/4.x/CHANGES.rst 5.0a1 (unreleased) ------------------ +- Updated Zope documentation sources for Zope 5 + (`#659 `_) + - The method ``unrestrictedTraverse`` raises an error when the argument ``path`` is not something it can work with (`#674 `_) diff --git a/docs/INSTALL.rst b/docs/INSTALL.rst index 29336cd35d..5582f0b384 100644 --- a/docs/INSTALL.rst +++ b/docs/INSTALL.rst @@ -14,9 +14,8 @@ In order to install Zope, you must have the following prerequisites available: - A supported version of Python, including the development support if - installed from system-level packages. Supported versions include: - - * 3.5 up to 3.8 + installed from system-level packages. Supported versions include + **3.5** up to **3.8**. - Zope needs the Python ``zlib`` module to be importable. If you are building your own Python from source, please be sure that you have the @@ -126,10 +125,9 @@ options, please see the [zopeinstance] recipe = plone.recipe.zope2instance - eggs = - Products.TemporaryFolder user = admin:adminpassword http-address = 8080 + zodb-temporary-storage = off One feature this kind of installation offers is the easy integration of WSGI servers other than the built-in ``waitress``. You can specify a file path to a @@ -143,10 +141,10 @@ include the WSGI server software egg in the ``eggs`` specification: [zopeinstance] recipe = plone.recipe.zope2instance eggs = - Products.TemporaryFolder gunicorn user = admin:adminpassword http-address = 8080 + zodb-temporary-storage = off wsgi = /path/to/zope.ini Installing Zope with ``pip`` diff --git a/docs/conf.py b/docs/conf.py index 0fefd9dbb8..48315f2358 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -24,9 +24,9 @@ author = 'The Zope developer community' # The short X.Y version -version = '4.1' +version = '5.0' # The full version, including alpha/beta/rc tags -release = '4.1' +release = '5.0' # -- General configuration --------------------------------------------------- diff --git a/docs/index.rst b/docs/index.rst index b6b3917cd8..8810236f9b 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -5,10 +5,10 @@ This is the official home for all Zope documentation. .. toctree:: :maxdepth: 2 - zope4/index + news INSTALL + migrations/index operation - wsgi maintenance changes zopebook/index diff --git a/docs/migrations/index.rst b/docs/migrations/index.rst new file mode 100644 index 0000000000..cbf59736c9 --- /dev/null +++ b/docs/migrations/index.rst @@ -0,0 +1,9 @@ +Migrating between Zope versions +=============================== + +These documents outline migration steps that may be required when upgrading +Zope. + +.. toctree:: + + zope4/index diff --git a/docs/zope4/migration/code.rst b/docs/migrations/zope4/code.rst similarity index 100% rename from docs/zope4/migration/code.rst rename to docs/migrations/zope4/code.rst diff --git a/docs/zope4/migration/content.rst b/docs/migrations/zope4/content.rst similarity index 100% rename from docs/zope4/migration/content.rst rename to docs/migrations/zope4/content.rst diff --git a/docs/zope4/migration/index.rst b/docs/migrations/zope4/index.rst similarity index 54% rename from docs/zope4/migration/index.rst rename to docs/migrations/zope4/index.rst index 987c0e7b1d..84ed0f14c9 100644 --- a/docs/zope4/migration/index.rst +++ b/docs/migrations/zope4/index.rst @@ -1,7 +1,7 @@ .. _zope4migration: -Migrating to Zope 4 -=================== +Migrating from Zope 2 to Zope 4 or 5 +==================================== .. toctree:: :maxdepth: 2 diff --git a/docs/zope4/migration/removed.rst b/docs/migrations/zope4/removed.rst similarity index 100% rename from docs/zope4/migration/removed.rst rename to docs/migrations/zope4/removed.rst diff --git a/docs/zope4/migration/zodb.rst b/docs/migrations/zope4/zodb.rst similarity index 100% rename from docs/zope4/migration/zodb.rst rename to docs/migrations/zope4/zodb.rst diff --git a/docs/zope4/news.rst b/docs/news.rst similarity index 85% rename from docs/zope4/news.rst rename to docs/news.rst index 06e9e91a96..1fd324de2e 100644 --- a/docs/zope4/news.rst +++ b/docs/news.rst @@ -1,19 +1,41 @@ -What's new in Zope 4 -==================== -The article explains the new high-level features and changes found in this -version of Zope. +What's new in Zope +================== +The article explains the new high-level features and changes found in Zope. + +You can have a look at the `detailed change log <./changes.html>`_ to learn +about all minor new features and bugs being solved in the latest release. + +.. attention:: + + If you are upgrading from Zope 2, make sure you study the + :ref:`zope4migration` documentation -You can have a look at the `detailed change log <../changes.html>`_ to learn -about all minor new features and bugs being solved in this release. When you -are ready to migrate, make sure you study the :ref:`zope4migration` -documentation. .. contents:: :local: +What's new in Zope 5 +-------------------- + +Dropped support for Python 2 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Zope 5 supports Python 3 only, versions 3.5 up through 3.8. All support code +and special casing for Python 2, including the use of the ``six`` package, have +been removed. + +Dropped support for ``ZServer`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +As ``ZServer`` only supports Python 2, its integration has been removed. Only +`WSGI` is now supported for web service. + + + +What's new in Zope 4 +-------------------- + Restored sane version numbering -------------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Version numbers for Zope have been confusing in the past. The original Zope project iterated through version one to two up to version 2.13. In parallel a separate project was launched using the name Zope 3. Zope 3 wasn't a new @@ -28,19 +50,18 @@ found in this release. Extended Python version support -------------------------------- -Zope 5 supports Python 3.5 up to Python 3.8. +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Zope 4 supports Python 2.7 and Python 3 versions 3.5 up to 3.8. The Python 3 support currently covers the core dependencies shipped with Zope and is limited to the new WSGI based publisher. Migrating an existing ZODB to Python 3 is not an automated process. You have -to update to Zope 4 first, see -`Zope 4 migration `_. +to update to Zope 4 first, see :ref:`zope4migration`. WSGI as the new default server type ------------------------------------ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Zope 2.13 first gained support for running Zope as a WSGI application, using any WSGI capable web server instead of the built-in ZServer. @@ -106,7 +127,7 @@ based publisher. View component Acquisition changes ----------------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In Zope 2.12 Zope Toolkit view components changed and stopped inheriting from Acquisition base classes, as Acquisition got aware of `__parent__` pointers, which meant that ``aq_parent(view)`` worked, without the view @@ -119,7 +140,7 @@ view page template files or viewlets. Page Templates now rendered by Chameleon ----------------------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Chameleon is an alternative implementation of the page template language supporting additional features and impressive template rendering speed. @@ -138,7 +159,7 @@ manually. Lower memory consumption at runtime ------------------------------------ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Zope 4 depends on a new DateTime release. The new release has been optimized for better memory use. Applications using a lot of DateTime values like the Plone CMS have seen total memory usage to decrease by 10% to 20% for medium @@ -146,7 +167,7 @@ to large deployments. Simplified encoding configuration ---------------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ As it is reasonable to have one unified encoding in ZMI and frontend, support for ``management_page_charset`` (as property of a folder) has been removed. ``default-zpublisher-encoding`` in `zope.conf` is the only place where to @@ -155,7 +176,7 @@ Templates handle encoding and decoding of text. Restyled Zope Management Interface (ZMI) ----------------------------------------- +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The ZMI (Zope Management Interface) is now styled with Bootstrap. See :ref:`ZMI-label` for details how to adapt Zope add-on packages to the new styling. diff --git a/docs/operation.rst b/docs/operation.rst index 0fb6ec4fbc..8a95aabcfe 100644 --- a/docs/operation.rst +++ b/docs/operation.rst @@ -63,12 +63,22 @@ Configuring Zope Your instance's configuration is defined in its ``etc/zope.conf`` and ``etc/zope.ini`` configuration files. +.. note:: + + Any changes in these configuration files require you to restart your Zope + instance before they become active. + +``zope.ini``: WSGI configuration +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The file ``etc/zope.ini`` contains all settings related to the `WSGI` pipeline, +the `WSGI` server and logging. + When starting Zope, if you see errors indicating that an address is in use, then you may have to change the ports Zope uses for HTTP. The default HTTP port used by Zope is 8080. You can change the port -used by editing ./etc/zope.ini appropriately. - -The section in the configuration file looks like this: +used by editing the ``[server]`` configuration section, which defines settings +for the `WSGI` server itself: .. code-block:: ini @@ -77,8 +87,43 @@ The section in the configuration file looks like this: host = 127.0.0.1 port = 8080 -After making any changes to the configuration file, you need to restart any -running Zope server for the affected instance before changes are in effect. +See the section `Using alternative WSGI server software`_ to learn how to +integrate `WSGI` servers other than the default ``waitress``. + +Zope is configured in the ``[app]`` section. It defines the so-called "entry +point" called by the `WSGI` server and where the Zope configuration file +``zope.conf`` is located: + +.. code-block:: ini + + [app:zope] + use = egg:Zope#main + zope_conf = /path/to/zope.conf + +The logging configurations are part of the ``etc/zope.ini`` file as well. +The default configurations created by ``mkwsgiinstance`` and +``plone.recipe.zope2instance`` are suitable for most applications. +The `Python Logging Cookbook +`_ has a great +selection of topics for advanced configurations. + +Keep in mind that different WSGI servers have different logging behaviors. +Some have their own access and event logging, some don't log anything at all. +For good control over your application's logging needs, the default +configurations use the ``translogger`` WSGI middleware from the ``Paste`` +package. It can capture and log all errors propagating from your application. + +.. note :: + + If your application is created using a custom ``zc.buildout`` configuration + and you want to use ``translogger`` for logging, make sure to specify + the ``wsgi`` extra for Zope in your buildout's ``eggs`` specification, + like ``Zope[wsgi]``. + +``zope.conf``: Zope settings +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You configure Zope itself in ``etc/zope.conf``. For a full description of the supported sections and directives for ``zope.conf``, refer to the :ref:`configuration reference section @@ -203,11 +248,11 @@ Again in the WSGI setup the `zconsole` module and console script can be used: Adding users ~~~~~~~~~~~~ If you need to add a Manager to an existing Zope instance, you can do -this using `addzope2user` as follows: +this using ``addzopeuser`` as follows: .. code-block:: console - $ bin/addzope2user user password + $ bin/addzopeuser user password The script expects to find the configuration file at ``etc/zope.conf``. @@ -415,6 +460,305 @@ Troubleshooting .. _configuration_reference: + +Using alternative WSGI server software +-------------------------------------- +The WSGI integration gives you a choice of WSGI server software to run your +Zope application. This section lists several options that were selected +because they either have a `PasteDeploy` entry point or have one provided by +shim software, which means they work with the default Zope scripts for +starting/stopping the service. + + +Things to watch out for +~~~~~~~~~~~~~~~~~~~~~~~ +The ZODB uses connection pooling where a working thread grabs a connection +from the pool to serve content and then releases it when the work is done. +The default size of this connection pool is 7. You should choose a number of +application threads that stays safely below that number of ZODB connections. +If the WSGI server lets you configure the number of threads, 4 is a safe +choice. + +Another recommendation from Zope 2 is still valid as well: If you have a choice +between less Zope instances with a higher number of threads each, or more +instances with less threads each, choose the latter. Create more separate Zope +instances and set the WSGI server threads value to e.g. 2. + +.. warning:: + + If the WSGI server software lets you configure a number of worker processes, + like ``gunicorn`` does, do not configure more than a single worker. + Otherwise you will see issues due to concurrent ZODB access by more than + one process, which may corrupt your ZODB. + + +Test criteria for recommendations +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +A simple contrived load test was done with the following parameters: + +- 100 concurrent clients accessing Zope +- 100 seconds run time +- the clients just fetch "/" +- standard Zope 4 instances, one with ZEO and one without +- Python 2.7.16 on macOS Mojave/10.14.4 +- standard WSGI server configurations, the only changes are to number of + threads and/or number of workers where available. + +This load test uncovered several issues: + +- ``cheroot`` (tested version: 6.5.5) was magnitudes slower than all others. + Unlike the others, it did not max out CPU. It is unclear where the slowdown + originates. Others reached 500-750 requests/second. ``cheroot`` only served + 12 requests/second per configured thread. +- ``gunicorn`` (tested version: 19.9.0) showed very strange behavior against + the non-ZEO Zope instance. It serves around 500 requests/second, but then + hangs and serves no requests for several seconds, before picking up again. +- ``gunicorn`` (tested version: 19.9.0) does not like the ZEO instance at all. + No matter what configuration in terms of threads or workers was chosen + ``gunicorn`` just hung so badly that even CTRL-C would not kill it. + Switching to an asynchronous type of worker (tested with ``gevent``) + did not make a difference. +- ``werkzeug`` (tested version: 0.15.2) does not let you specify the number + of threads, you only tell it to use threads or not. In threaded mode it + spawns too many threads and immedialy runs up agains the ZODB connection + pool limits, so with Zope only the unthreaded mode is suitable. Even in + unthreaded mode, the service speed was inconsistent. Just like ``gunicorn`` + it had intermittent hangs before recovering. +- ``bjoern`` (tested version: 3.0.0) is the clear speed winner with 740 + requests/second against both the ZEO and non-ZEO Zope instance, even though + it is single-threaded. +- ``waitress`` (tested version: 1.3.0) is the all-around best choice. It's + just 10-15% slower than ``bjoern``, but both the built-in WSGI tools as well + as ``plone.recipe.zope2instance`` use it as the default and make it very + convenient to use. + + +Recommended WSGI servers +~~~~~~~~~~~~~~~~~~~~~~~~ + +waitress (the default and recommended choice) ++++++++++++++++++++++++++++++++++++++++++++++ +If you create a Zope instance using the ``mkwsgiinstance`` script described +above or the ``plone.recipe.zope2instance`` buildout recipe, you will +automatically get a ``waitress``-based server. The default configurations set +up for you will be sufficient for most applications. See the `waitress +documentation `_ for +additional information. + +Here's a very simple configuration using ``plone.recipe.zope2instance``: + +.. code-block:: ini + + [zopeinstance] + recipe = plone.recipe.zope2instance + eggs = + zodb-temporary-storage = off + user = admin:password + http-address = 8080 + +Note the empty ``eggs`` section, you cannot leave it out. + +``waitress`` has many options that you can add to the buildout section. A full +list is `part of the waitress documentation +`_. + + +bjoern (the fastest) +++++++++++++++++++++ +The `bjoern WSGI server `_ can be +integrated using a shim package called `dataflake.wsgi.bjoern +`_. See the `Using this package` +section for details on how to integrate `bjoern` using Zope's own +``runwsgi`` script and how to create a suitable WSGI configuration. + +If you use ``plone.recipe.zope2instance``, the following +section will pull in the correct dependencies: + +.. code-block:: ini + + [zopeinstance] + recipe = plone.recipe.zope2instance + eggs = + dataflake.wsgi.bjoern + zodb-temporary-storage = off + user = admin:password + http-address = 8080 + wsgi = ${buildout:directory}/etc/bjoern.ini + + +Problematic WSGI servers +~~~~~~~~~~~~~~~~~~~~~~~~ + +werkzeug +++++++++ +`werkzeug `_ is a WSGI library that +contains not just a WSGI server, but also a powerful debugger. It can +easily integrate wth Zope using a shim package called `dataflake.wsgi.werkzeug +`_. See the `Using this package` +section for how to integrate `werkzeug` using Zope's own ``runwsgi`` script and +how to create a suitable WSGI configuration. + +If you use ``plone.recipe.zope2instance``, the following section will pull in +the correct dependencies, after you have created a WSGI configuration file: + +.. code-block:: ini + + [zopeinstance] + recipe = plone.recipe.zope2instance + eggs = + dataflake.wsgi.werkzeug + zodb-temporary-storage = off + user = admin:password + http-address = 8080 + wsgi = ${buildout:directory}/etc/werkzeug.ini + + +gunicorn +++++++++ +The `gunicorn WSGI server `_ has a built-in +`PasteDeploy` entry point and integrates easily. The following example buildout +configuration section will create a ``bin/runwsgi`` script that uses +`gunicorn`. + +.. code-block:: ini + + [gunicorn] + recipe = zc.recipe.egg + eggs = + Zope + gunicorn + scripts = + runwsgi + +You can use this script with a WSGI configuration file that you have to create +yourself. Please see the `gunicorn documentation +`_, especially the `Configuration File` section on +`Configuration Overview`, for Paster Application configuration information. A +very simple server configuration looks like this: + +.. code-block:: ini + + [server:main] + use = egg:gunicorn#main + host = 192.168.0.1 + port = 8080 + proc_name = zope + +You can then run the server using ``runwsgi``: + +.. code-block:: console + + $ bin/runwsgi etc/gunicorn.ini + 2019-04-22 11:45:39 INFO [Zope:45][MainThread] Ready to handle requests + Starting server in PID 84983. + +.. note:: + gunicorn version 19.9.0 or less will print an ominous warning message on the + console upon startup that seems to suggest their WSGI entry point is + deprecated in favor of using their own built-in scripts. This is misleading. + Future versions will not show this message. + +If you use ``plone.recipe.zope2instance``, you can make it use `gunicorn` by +adding its egg to the buildout section and setting the WSGI configuration file +path to the path of the configuration file you created yourself: + +.. code-block:: ini + + [zopeinstance] + recipe = plone.recipe.zope2instance + eggs = + gunicorn + zodb-temporary-storage = off + user = admin:password + http-address = 8080 + wsgi = ${buildout:directory}/etc/gunicorn.ini + + +cheroot ++++++++ +The `cheroot WSGI server `_ can be integrated +using a shim package called `dataflake.wsgi.cheroot +`_. See the `Using this package` +section for details on how to integrate `cheroot` using Zope's own +``runwsgi`` script and how to create a suitable WSGI configuration. + +If you use ``plone.recipe.zope2instance``, the following +section will pull in the correct dependencies: + +.. code-block:: ini + + [zopeinstance] + recipe = plone.recipe.zope2instance + eggs = + dataflake.wsgi.cheroot + zodb-temporary-storage = off + user = admin:password + http-address = 8080 + wsgi = ${buildout:directory}/etc/cheroot.ini + + +Debugging Zope applications under WSGI +-------------------------------------- +You can debug a WSGI-based Zope application by adding a statement to activate +the debugger. In addition, you can take +advantage of WSGI middleware or debugging facilities built into the chosen +WSGI server. + +When developing your application or debugging, which is the moment you want to +use debugging tools, you can start your Zope instance in `exceptions debug +mode`. This will disable all registered exception views including +``standard_error_message`` so that exceptions are not masked or hidden. + +This is how you run Zope in exceptions debug mode using the built-in +``runwsgi`` script: + +.. code-block:: console + + $ bin/runwsgi -e etc/zope.ini + +If you built your environment using ``plone.recipe.zope2instance`` you will +need to do a manual change to your Zope configuration file. Enable exceptions +debug mode by adding the ``debug-exceptions on`` setting before starting your +application. The example presumes the Zope instance was named ``zopeinstance``, +your Zope configuration file will be at `parts/zopeinstance/etc/zope.conf`. + +.. code-block:: console + + bin/zopeinstance fg + +With Zope set up to let WSGI handle exceptions, these are a few options for the +WSGI pipeline: + +If you use ``waitress``, you can make it output exception tracebacks in the +browser by configuring ``expose_tracebacks``. The keyword works in both +standard and ``plone.recipe.zope2instance`` configurations: + +.. code-block:: ini + + [server:main] + use = egg:waitress#main + host = 127.0.0.1 + port = 8080 + expose_tracebacks = True + + ... or ... + + [server:main] + paste.server_factory = plone.recipe.zope2instance:main + use = egg:plone.recipe.zope2instance#main + listen = 0.0.0.0:8080 + threads = 2 + expose_tracebacks = True + +``werkzeug`` includes a full-featured debugging tool. See the +`dataflake.wsgi.werkzeug documentation +`_ +for how to enable the debugger. Once you're up and running, the `werkzeug +debugger documentation +`_ +will show you how to use it. + + Zope configuration reference ---------------------------- @@ -422,4 +766,3 @@ Zope configuration reference :file: wsgischema.xml -.. _`Creating a Zope instance for Zope 2.13` : http://zope.readthedocs.io/en/2.13/INSTALL-buildout.html#creating-a-zope-instance diff --git a/docs/wsgi.rst b/docs/wsgi.rst deleted file mode 100644 index be230e0d29..0000000000 --- a/docs/wsgi.rst +++ /dev/null @@ -1,375 +0,0 @@ -Zope and WSGI -============= -Starting with Zope 4, a WSGI-compatible application entry point is the default -option for serving your site. Zope comes with a set of scripts to set up a -default WSGI stack with ``waitress`` as WSGI server, but any other WSGI server -can be used. - -.. contents:: - :local: - - -WSGI application entry points ------------------------------ -To use Zope as an application in a PasteDeploy-style ``.ini`` configuration -file, use the ``Zope#main`` entry point and specify a path to a Zope -configuration file: - -.. code-block:: ini - - [app:zope] - use = egg:Zope#main - zope_conf = /path/to/zope.conf - -To compose your pipeline in Python code: - -.. code-block:: python - - from Zope2.startup.run import make_wsgi_app - - app = make_wsgi_app({}, '/path/to/zope.conf') - - -Building a Zope instance with WSGI support ------------------------------------------- -Zope ships with several helper scripts to set up a default WSGI-enabled -environment. The document :doc:`operation` walks you through using -``mkwsgiinstance`` for a default configuration that you can use in conjunction -with the ``runwsgi`` script to start a Zope instance. - -The buildout extension ``plone.recipe.zope2instance`` expands on that and -adds a script wrapper for convenient starting and stopping as well as a host -of other functions. Take a look at `their PyPI page listing all options -`_. - - -Logging configuration ---------------------- -The logging configurations are part of the WSGI configuration ``.ini`` file. -The default configurations created by ``mkwsgiinstance`` and -``plone.recipe.zope2instance`` are suitable for most applications. - -Keep in mind that different WSGI servers have different logging behaviors. Some -have their own access and event logging, some don't log anything at all. For -good control over your application's logging needs, the default configurations -use the ``translogger`` WSGI middleware from the ``Paste`` package. It can -capture and log all errors propagating from your application. - -.. note :: - - If your application is created using a custom ``zc.buildout`` configuration - and you want to use ``translogger`` for logging, make sure to include the - ``Paste`` egg in your buildout's ``eggs`` specification. - -You can use the generated default WSGI configuration's logging sections as a -starting point for changes. The `Python Logging Cookbook -`_ has a great selection -of topics for advanced configurations. - - -Choosing WSGI server software ------------------------------ -The WSGI integration gives you a choice of WSGI server software to run your -Zope application. This section lists several options that were selected -because they either have a `PasteDeploy` entry point or have one provided by -shim software, which means they work with the default Zope scripts for -starting/stopping the service. - - -Things to watch out for -~~~~~~~~~~~~~~~~~~~~~~~ -The ZODB uses connection pooling where a working thread grabs a connection -from the pool to serve content and then releases it when the work is done. -The default size of this connection pool is 7. You should choose a number of -application threads that stays safely below that number of ZODB connections. -If the WSGI server lets you configure the number of threads, 4 is a safe -choice. - -Another recommendation from Zope 2 is still valid as well: If you have a choice -between less Zope instances with a higher number of threads each, or more -instances with less threads each, choose the latter. Create more separate Zope -instances and set the WSGI server threads value to e.g. 2. - -.. warning:: - - If the WSGI server software lets you configure a number of worker processes, - like ``gunicorn`` does, do not configure more than a single worker. - Otherwise you will see issues due to concurrent ZODB access by more than - one process, which may corrupt your ZODB. - - -Test criteria for recommendations -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -A simple contrived load test was done with the following parameters: - -- 100 concurrent clients accessing Zope -- 100 seconds run time -- the clients just fetch "/" -- standard Zope 4 instances, one with ZEO and one without -- Python 2.7.16 on macOS Mojave/10.14.4 -- standard WSGI server configurations, the only changes are to number of - threads and/or number of workers where available. - -This load test uncovered several issues: - -- ``cheroot`` (tested version: 6.5.5) was magnitudes slower than all others. - Unlike the others, it did not max out CPU. It is unclear where the slowdown - originates. Others reached 500-750 requests/second. ``cheroot`` only served - 12 requests/second per configured thread. -- ``gunicorn`` (tested version: 19.9.0) showed very strange behavior against - the non-ZEO Zope instance. It serves around 500 requests/second, but then - hangs and serves no requests for several seconds, before picking up again. -- ``gunicorn`` (tested version: 19.9.0) does not like the ZEO instance at all. - No matter what configuration in terms of threads or workers was chosen - ``gunicorn`` just hung so badly that even CTRL-C would not kill it. - Switching to an asynchronous type of worker (tested with ``gevent``) - did not make a difference. -- ``werkzeug`` (tested version: 0.15.2) does not let you specify the number - of threads, you only tell it to use threads or not. In threaded mode it - spawns too many threads and immedialy runs up agains the ZODB connection - pool limits, so with Zope only the unthreaded mode is suitable. Even in - unthreaded mode, the service speed was inconsistent. Just like ``gunicorn`` - it had intermittent hangs before recovering. -- ``bjoern`` (tested version: 3.0.0) is the clear speed winner with 740 - requests/second against both the ZEO and non-ZEO Zope instance, even though - it is single-threaded. -- ``waitress`` (tested version: 1.3.0) is the all-around best choice. It's - just 10-15% slower than ``bjoern``, but both the built-in WSGI tools as well - as ``plone.recipe.zope2instance`` use it as the default and make it very - convenient to use. - - -Recommended WSGI servers -~~~~~~~~~~~~~~~~~~~~~~~~ - -waitress (the default and recommended choice) -+++++++++++++++++++++++++++++++++++++++++++++ -If you create a Zope instance using the ``mkwsgiinstance`` script described -above or the ``plone.recipe.zope2instance`` buildout recipe, you will -automatically get a ``waitress``-based server. The default configurations set -up for you will be sufficient for most applications. See the `waitress -documentation `_ for -additional information. - -Here's a very simple configuration using ``plone.recipe.zope2instance``: - -.. code-block:: ini - - [zopeinstance] - recipe = plone.recipe.zope2instance - eggs = - zodb-temporary-storage = off - user = admin:password - http-address = 8080 - -Note the empty ``eggs`` section, you cannot leave it out. - -``waitress`` has many options that you can add to the buildout section. A full -list is `part of the waitress documentation -`_. - - -bjoern (the fastest) -++++++++++++++++++++ -The `bjoern WSGI server `_ can be -integrated using a shim package called `dataflake.wsgi.bjoern -`_. See the `Using this package` -section for details on how to integrate `bjoern` using Zope's own -``runwsgi`` script and how to create a suitable WSGI configuration. - -If you use ``plone.recipe.zope2instance``, the following -section will pull in the correct dependencies: - -.. code-block:: ini - - [zopeinstance] - recipe = plone.recipe.zope2instance - eggs = - dataflake.wsgi.bjoern - zodb-temporary-storage = off - user = admin:password - http-address = 8080 - wsgi = ${buildout:directory}/etc/bjoern.ini - - -Problematic WSGI servers -~~~~~~~~~~~~~~~~~~~~~~~~ - -werkzeug -++++++++ -`werkzeug `_ is a WSGI library that -contains not just a WSGI server, but also a powerful debugger. It can -easily integrate wth Zope using a shim package called `dataflake.wsgi.werkzeug -`_. See the `Using this package` -section for how to integrate `werkzeug` using Zope's own ``runwsgi`` script and -how to create a suitable WSGI configuration. - -If you use ``plone.recipe.zope2instance``, the following section will pull in -the correct dependencies, after you have created a WSGI configuration file: - -.. code-block:: ini - - [zopeinstance] - recipe = plone.recipe.zope2instance - eggs = - dataflake.wsgi.werkzeug - zodb-temporary-storage = off - user = admin:password - http-address = 8080 - wsgi = ${buildout:directory}/etc/werkzeug.ini - - -gunicorn -++++++++ -The `gunicorn WSGI server `_ has a built-in -`PasteDeploy` entry point and integrates easily. The following example buildout -configuration section will create a ``bin/runwsgi`` script that uses -`gunicorn`. - -.. code-block:: ini - - [gunicorn] - recipe = zc.recipe.egg - eggs = - Zope - gunicorn - scripts = - runwsgi - -You can use this script with a WSGI configuration file that you have to create -yourself. Please see the `gunicorn documentation -`_, especially the `Configuration File` section on -`Configuration Overview`, for Paster Application configuration information. A -very simple server configuration looks like this: - -.. code-block:: ini - - [server:main] - use = egg:gunicorn#main - host = 192.168.0.1 - port = 8080 - proc_name = zope - -You can then run the server using ``runwsgi``: - -.. code-block:: console - - $ bin/runwsgi etc/gunicorn.ini - 2019-04-22 11:45:39 INFO [Zope:45][MainThread] Ready to handle requests - Starting server in PID 84983. - -.. note:: - gunicorn version 19.9.0 or less will print an ominous warning message on the - console upon startup that seems to suggest their WSGI entry point is - deprecated in favor of using their own built-in scripts. This is misleading. - Future versions will not show this message. - -If you use ``plone.recipe.zope2instance``, you can make it use `gunicorn` by -adding its egg to the buildout section and setting the WSGI configuration file -path to the path of the configuration file you created yourself: - -.. code-block:: ini - - [zopeinstance] - recipe = plone.recipe.zope2instance - eggs = - gunicorn - zodb-temporary-storage = off - user = admin:password - http-address = 8080 - wsgi = ${buildout:directory}/etc/gunicorn.ini - - -cheroot -+++++++ -The `cheroot WSGI server `_ can be integrated -using a shim package called `dataflake.wsgi.cheroot -`_. See the `Using this package` -section for details on how to integrate `cheroot` using Zope's own -``runwsgi`` script and how to create a suitable WSGI configuration. - -If you use ``plone.recipe.zope2instance``, the following -section will pull in the correct dependencies: - -.. code-block:: ini - - [zopeinstance] - recipe = plone.recipe.zope2instance - eggs = - dataflake.wsgi.cheroot - zodb-temporary-storage = off - user = admin:password - http-address = 8080 - wsgi = ${buildout:directory}/etc/cheroot.ini - - -Debugging Zope applications under WSGI --------------------------------------- -You can debug a WSGI-based Zope application by adding a statement to activate -the debugger. In addition, you can take -advantage of WSGI middleware or debugging facilities built into the chosen -WSGI server. - -When developing your application or debugging, which is the moment you want to -use debugging tools, you can start your Zope instance in `exceptions debug -mode`. This will disable all registered exception views including -``standard_error_message`` so that exceptions are not masked or hidden. - -This is how you run Zope in exceptions debug mode using the built-in -``runwsgi`` script: - -.. code-block:: console - - $ bin/runwsgi -e etc/zope.ini - -If you built your environment using ``plone.recipe.zope2instance`` you will -need to do a manual change to your Zope configuration file. Enable exceptions -debug mode by adding the ``debug-exceptions on`` setting before starting your -application. The example presumes the Zope instance was named ``zopeinstance``, -your Zope configuration file will be at `parts/zopeinstance/etc/zope.conf`. - -.. code-block:: console - - bin/zopeinstance fg - -With Zope set up to let WSGI handle exceptions, these are a few options for the -WSGI pipeline: - -If you use ``waitress``, you can make it output exception tracebacks in the -browser by configuring ``expose_tracebacks``. The keyword works in both -standard and ``plone.recipe.zope2instance`` configurations: - -.. code-block:: ini - - [server:main] - use = egg:waitress#main - host = 127.0.0.1 - port = 8080 - expose_tracebacks = True - - ... or ... - - [server:main] - paste.server_factory = plone.recipe.zope2instance:main - use = egg:plone.recipe.zope2instance#main - listen = 0.0.0.0:8080 - threads = 2 - expose_tracebacks = True - -``werkzeug`` includes a full-featured debugging tool. See the -`dataflake.wsgi.werkzeug documentation -`_ -for how to enable the debugger. Once you're up and running, the `werkzeug -debugger documentation -`_ -will show you how to use it. - - -WSGI documentation links ------------------------- -- the WSGI standard is described in `PEP-3333 - `_. -- The WSGI website at https://wsgi.readthedocs.io/ is comprehensive but also - rather outdated. -- AppDynamics did an interesting `WSGI server performance analysis - `_. diff --git a/docs/zope4/index.rst b/docs/zope4/index.rst deleted file mode 100644 index 514f29ea40..0000000000 --- a/docs/zope4/index.rst +++ /dev/null @@ -1,7 +0,0 @@ -Zope 4 -====== - -.. toctree:: - - news - migration/index diff --git a/setup.py b/setup.py index e73c85666d..5ba90732e6 100644 --- a/setup.py +++ b/setup.py @@ -142,7 +142,7 @@ def _read_file(filename): 'httpexceptions=ZPublisher.httpexceptions:main', ], 'console_scripts': [ - 'addzope2user=Zope2.utilities.adduser:main', + 'addzopeuser=Zope2.utilities.adduser:main', 'runwsgi=Zope2.Startup.serve:main', 'mkwsgiinstance=Zope2.utilities.mkwsgiinstance:main', 'zconsole=Zope2.utilities.zconsole:main',