Bjoern
Contents
8. Bjoern
#
bjoern is an HTTP/1.1 WSGI Server for CPython2 and 3 written in C. It claims to be the fastest, smallest and most lightweight WSGI server.
Note
In a load test involving bjoern
, cheroot
, gunicorn
, waitress
and werkzeug
, bjoern
(version: 3.0.0) was the clear speed winner against both a ZEO and a non-ZEO Zope instance.
8.1. Prerequisites#
Bjoern
uses libev
and you will need to install both the library and the development header files on your box:
$ sudo apt install libev-dev
8.2. Use bjoern
in our buildout#
bjoern can be integrated using a shim package called dataflake.wsgi.bjoern.
You can use this package together with plone.recipe.zope2instance
to build a bjoern
based WSGI setup:
[instance]
recipe = plone.recipe.zope2instance
user = admin:admin
zeo-client = on
zeo-address = 8100
shared-blob = on
blob-storage = ${buildout:directory}/var/blobstorage
eggs =
Plone
wsgitraining.site
dataflake.wsgi.bjoern
wsgi-ini-template = ${buildout:directory}/templates/bjoern.ini.in
In addition to adding dataflake.wsgi.bjoern
to the eggs
list we specify the location of our bjoern.ini
configuration file.
Note that this file is not automatically created for us, we have to provide it ourself.
In addition to the PasteDeploy entry point and the p.r.zope2instance integration, dataflake.wsgi.bjoern
provides facilities to create a set of Zope configuration files for bjoern
with the included kbjoerninstance
utility.
We will however not use this option since it is easier to provide a custom template for the wsgi.ini
file to plone.recipe.zope2instance
.
A suitable template is included in the buildout for the training (file bjoern.ini.in
in the templates
folder).
It is basically a copy from the template contained in the buildout recipe with a slightly changed [server:main]
section:
[server:main]
use = egg:dataflake.wsgi.bjoern#main
listen = %(http_address)s
reuse_port = True
Note
Let's run some checks in order to verify that bin/instance
actually invokes bjoern:
Let's first find the processes' PID:
$ ps -ef | grep wsgi.ini
thomas 20009 20006 0 10:26 pts/1 00:00:22 /home/thomas/devel/plone/minimal52/bin/python /home/thomas/devel/plone/minimal52/parts/instance/bin/interpreter /home/thomas/.buildout/eggs/cp37m/Zope-4.1.1-py3.7.egg/Zope2/Startup/serve.py /home/thomas/devel/plone/minimal52/parts/instance/etc/wsgi.ini -d debug-mode=on
Using the above PID we can check the process map to see whether bjoern's C extension has been loaded:
thomas@blake:~$ pmap 17245 | grep bjoern
17245: /home/thomas/devel/plone/minimal52/bin/python /home/thomas/devel/plone/minimal52/parts/instance/bin/interpreter /home/thomas/.buildout/eggs/cp37m/Zope-4.1.1-py3.7.egg/Zope2/Startup/serve.py /home/thomas/devel/plone/minimal52/etc/bjoern.ini -d debug-mode=on
00007f7537fa5000 44K r-x-- _bjoern.cpython-37m-x86_64-linux-gnu.so
00007f7537fb0000 2048K ----- _bjoern.cpython-37m-x86_64-linux-gnu.so
00007f75381b0000 4K r---- _bjoern.cpython-37m-x86_64-linux-gnu.so
00007f75381b1000 4K rw--- _bjoern.cpython-37m-x86_64-linux-gnu.so
8.2.1. Exercise 1#
Additional PasteDeploy entrypoints are available for the werkzeug entrypoints and cheroot entrypoints WSGI servers. Pick one and use it to run Plone behind werkzeug or cheroot.
Solution
cheroot:
You will need to create two files, an .ini
template and the buildout configuration.
As a starting point, copy bjoern.cfg
to cheroot.cfg
and templates/bjoern.ini.in
to templates/cheroot.ini.in
in your buildout directory:
$ cp bjoern.cfg cheroot.cfg
$ cp templates/bjoern.ini.in templates/cheroot.ini.in
Then edit the files so they pull in cheroot
as WSGI server rather than bjoern.
cheroot.cfg
:
[instance]
recipe = plone.recipe.zope2instance
user = admin:admin
zeo-client = on
zeo-address = 8100
shared-blob = on
blob-storage = ${buildout:directory}/var/blobstorage
eggs =
Plone
wsgitraining.site
dataflake.wsgi.cheroot
wsgi-ini-template = ${buildout:directory}/templates/cheroot.ini.in
And templates/cheroot.ini.in
:
[server:main]
use = egg:dataflake.wsgi.cheroot#main
host = localhost
port = 8080
[app:zope]
Note that the dataflake.wsgi.cheroot
shim doesn't understand either reuse_port
nor listen
.
This means we cannot use the http-address
parameter passed by plone.recipe.zope2instance
.
We resolve to specifying host and port in the template instead.
dataflake.wsgi.cheroot
accepts a couple of other options in the .ini
file that we will not consider for this exercise.
Next run buildout with the new configuration:
(wsgitraining) $ buildout -c cheroot.cfg
You can now start your instance as usual:
(wsgitraining) $ bin/instance fg
2019-10-07 12:43:08,856 INFO [Zope:45][MainThread] Ready to handle requests
Starting server in PID 3906.
werkzeug:
For werkzeug
the steps are pretty much the same.
Copy the configuration files:
$ cp bjoern.cfg werkzeug.cfg
$ cp templates/bjoern.ini.in templates/werkzeig.ini.in
Edit them.
werkzeug.cfg
:
[instance]
recipe = plone.recipe.zope2instance
user = admin:admin
zeo-client = on
zeo-address = 8100
shared-blob = on
blob-storage = ${buildout:directory}/var/blobstorage
eggs =
Plone
wsgitraining.site
dataflake.wsgi.werkzeug
wsgi-ini-template = ${buildout:directory}/templates/werkzeug.ini.in
templates/werkzeug.ini.in
:
[server:main]
use = egg:dataflake.wsgi.werkzeug#main
host = localhost
port = 8080
[app:zope]
After running buildout -c werkzeug.cfg
you can start your Plone instance:
(wsgitraining) $ bin/instance fg
2019-10-07 12:58:54,660 INFO [Zope:45][MainThread] Ready to handle requests
Starting server in PID 4337.
2019-10-07 12:58:54,661 INFO [werkzeug:122][MainThread] * Running on http://localhost:8080/ (Press CTRL+C to quit)
Like the cheroot
shim, dataflake.wsgi.werkzeug
accepts a couple of additional options in the .ini
file that we will not use here.