Tag Archives: uwsgi

uWSGI v2.0.12

It’s been a long time since I made a blog post about a uWSGI release but this one is special to me because it contains some features I asked for to a colleague of mine.

For his first contributions to a big Open Source project, our fellow @shir0kamii added two features (spooler_get_task and -if-hostname-match) which were backported in this release and that we needed at work for quite a long time : congratulations again ūüôā

Highlights

  • official PHP 7 support
  • uwsgi.spooler_get_task API to easily read and inspect a spooler file from your code
  • -if-hostname-match regexp on uWSGI configuration files to allow a more flexible configuration based on the hostname of the machine

Of course, all of this is already available on Gentoo Linux !

Full changelog here as usual.

uWSGI, gevent and pymongo 3 threads mayhem

This is a quick heads-up post about a behaviour change when running a gevent based application using the new pymongo 3 driver under uWSGI and its gevent loop.

I was naturally curious about testing this brand new and major update of the python driver for mongoDB so I just played it dumb : update and give a try on our existing code base.

The first thing I noticed instantly is that a vast majority of our applications were suddenly unable to reload gracefully and were force killed by uWSGI after some time !

worker 1 (pid: 9839) is taking too much time to die...NO MERCY !!!

uWSGI’s gevent-wait-for-hub

All our applications must be able to be gracefully reloaded at any time. Some of them are spawning quite a few greenlets on their own so as an added measure of making sure we never loose any running greenlet we use the gevent-wait-for-hub option, which is described as follow :

wait for gevent hub's death instead of the control greenlet

… which does not mean a lot but is explained in a previous uWSGI changelog :

During shutdown only the greenlets spawned by uWSGI are taken in account,
and after all of them are destroyed the process will exit.

This is different from the old approach where the process wait for
ALL the currently available greenlets (and monkeypatched threads).

If you prefer the old behaviour just specify the option gevent-wait-for-hub

pymongo 3

Compared to its previous 2.x versions, one of the overall key aspect of the new pymongo 3 driver is its intensive usage of threads to handle server discovery and connection pools.

Now we can relate this very fact to the gevent-wait-for-hub behaviour explained above :

the process wait for ALL the currently available greenlets
(and monkeypatched threads)

This explained why our applications were hanging until the reload-mercy (force kill) timeout option of uWSGI hit the fan !

conclusion

When using pymongo 3 with the gevent-wait-for-hub option, you have to keep in mind that all of pymongo’s threads (so monkey patched threads) are considered as active greenlets and will thus be waited for termination before uWSGI recycles the worker !

Two options come in mind to handle this properly :

  1. stop using the gevent-wait-for-hub option and change your code to use a gevent pool group to make sure that all of your important greenlets are taken care of when a graceful reload happens (this is how we do it today, the gevent-wait-for-hub option usage was just over protective for us).
  2. modify your code to properly close all your pymongo connections on graceful reloads.

Hope this will save some people the trouble of debugging this ūüėČ

Using uWSGI and Consul to design a distributed application

Foreword

Let’s say we have to design an application that should span across multiple datacenters while being able to scale¬†as easily as firing up a new vm/container without the need to update any kind of configuration.

Facing this kind of challenge is exciting and requires us to address a few key scaffolding points before actually starting to code something :

  • having a robust and yet versatile application container to run our application
  • having a datacenter aware, fault detecting and service discovery service

Seeing the title of this article, the two components I’ll demonstrate are obviously uWSGI and Consul which can now work together thanks to the uwsgi-consul plugin.

While this article example is written in python, you can benefit from the same features in all the languages supported by uWSGI which includes go, ruby, perl ad php !

Our first service discovering application

The application will demonstrate how simple it is for a client to discover all the available servers running a specific service on a given port. The best part is that the services will be registered and deregistered automatically by uWSGI as they’re loaded and unloaded.

The demo application logic is as follows :

  1. uWSGI will load two server applications which are each responsible for providing the specified service on the given port
  2. uWSGI will automatically register the configured service into Consul
  3. uWSGI will also automatically register a health check for the configured service into Consul so that Consul will also be able to detect any failure of the service
  4. Consul will then respond to any client requesting the list of the available servers (nodes) providing the specified service
  5. The client will query Consul for the service and get either an empty response (no server available / loaded) or the list of the available servers

Et voilà, the client can dynamically detect new/obsolete servers and start working !

Setting up uWSGI and its Consul plugin

On Gentoo Linux, you’ll just have to run the following commands to get started (other users refer to the uWSGI documentation or your distro’s package manager). The plugin will be built by hand as I’m still not sure how I’ll package the uWSGI external plugins…

$ sudo ACCEPT_KEYWORDS="~amd64" emerge uwsgi
$ cd /usr/lib/uwsgi/
$ sudo uwsgi --build-plugin https://github.com/unbit/uwsgi-consul
$ cd -

 

You’ll have installed the uwsgi-consul plugin which you should see here :

$ ls /usr/lib/uwsgi/consul_plugin.so
/usr/lib/uwsgi/consul_plugin.so

 

That’s all we need to have uWSGI working with Consul.

Setting up a Consul server

Gentoo users will need to add the ultrabug¬†overlay (use layman) and then install consul (other users refer to the Consul documentation or your distro’s package manager).

$ sudo layman -a ultrabug
$ sudo ACCEPT_KEYWORDS="~amd64" USE="web" emerge consul

 

Running the server and its UI is also quite straightforward. For this example, we will run it directly from a dedicated terminal so you can also enjoy the logs and see what’s going on (Gentoo users have an init script and conf.d ready for them shall they wish to go further).

Open a new terminal and run :

$ consul agent -data-dir=/tmp/consul-agent -server -bootstrap -ui-dir=/var/lib/consul/ui -client=0.0.0.0

 

You’ll see consul running and waiting for work. You can already enjoy the web UI by pointing your browser to¬†http://127.0.0.1:8500/ui/.

Running the application

To get this example running, we’ll use the uwsgi-consul-demo code that I prepared.

First of all we’ll need the consulate python library (available on pypi via pip). Gentoo users can just install it (also from the ultrabug overlay added before) :

$ sudo ACCEPT_KEYWORDS="~amd64" emerge consulate

 

Now let’s clone the demo repository and get into the project’s directory.

$ git clone git@github.com:ultrabug/uwsgi-consul-demo.git
$ cd uwsgi-consul-demo

 

First, we’ll run the client¬†which should report that no server is available yet. We will keep this terminal open to see the client detecting in real time the appearance and disappearance of the servers as we start and stop uwsgi :

$ python client.py 
no consul-demo-server available
[...]
no consul-demo-server available

 

Open a new terminal and get inside the project’s directory. Let’s have uWSGI load the two servers and register them in Consul :

$ uwsgi --ini uwsgi-consul-demo.ini --ini uwsgi-consul-demo.ini:server1 --ini uwsgi-consul-demo.ini:server2
[...]
* server #1 is up on port 2001


* server #2 is up on port 2002

[consul] workers ready, let's register the service to the agent
[consul] service consul-demo-server registered succesfully
[consul] workers ready, let's register the service to the agent
[consul] service consul-demo-server registered succesfully

 

Now let’s check back our client terminal, hooray it has discovered the two servers on the host named drakar (that’s my local box) !

consul-demo-server found on node drakar (xx.xx.xx.xx) using port 2002
consul-demo-server found on node drakar (xx.xx.xx.xx) using port 2001

Expanding our application

Ok it works great on our local machine but we want to see how to add more servers to the fun and scale dynamically.

Let’s add another machine (named cheetah here) to the fun and have servers running there also while our client is still running on our local machine.

On cheetah :

  • install uWSGI as described earlier
  • install Consul as described earlier

Run a Consul agent (no need of a server) and tell him to work with your already running consul server on your box (drakar in my case) :

$ /usr/bin/consul agent -data-dir=/tmp/consul-agent -join drakar -ui-dir=/var/lib/consul/ui -client=0.0.0.0

The -join <your host or IP> is the important part.

 

Now run uWSGI so it starts and registers two new servers on cheetah :

$ uwsgi --ini uwsgi-consul-demo.ini --ini uwsgi-consul-demo.ini:server1 --ini uwsgi-consul-demo.ini:server2

 

And check the miracle on your client terminal still running on your local box, the new servers have appeared and will disappear if you stop uwsgi on the cheetah node :

consul-demo-server found on node drakar (xx.xx.xx.xx) using port 2001
consul-demo-server found on node drakar (xx.xx.xx.xx) using port 2002
consul-demo-server found on node cheetah (yy.yy.yy.yy) using port 2001
consul-demo-server found on node cheetah (yy.yy.yy.yy) using port 2002

Go mad

Check the source code, it’s so simple and efficient you’ll cry ūüėČ

I hope this example has given you some insights and ideas for your current or future application designs !

Europython 2014

I had the chance to participate to europython 2014 as my company was sponsoring the event.

IMG_20140725_161445-1024x576

This was a great week where I got to meet some very interesting people and hear about some neat python use cases, libraries and new technologies so I thought I’d write a quick summary of my biased point of view.

ZeroMQ

I had the chance to meet Pieter Hintjens and participate in a 3 hours workshop on ZeroMQ. This was very interesting and refreshing as to go in more depth into this technology which I’ve been using in production for several years now.

Pieter is also quite a philosophical person and I strongly encourage you to listen to¬†his keynote. I ended up pinging him in real life for an issue I’ve been waiting for bug correction on the libzmq and it got answered nicely.

uWSGI

Another big thing in our python stack is the uWSGI application container which I love and follow closely even if my lack of knowledge in C++ prevents me for going too deep in the source code… I got the chance to speak with¬†Roberto De Ioris about the next 2.1 release and propose him two new features.

Thanks a lot for your consideration Roberto !

Trends

  • Not tested = broken !
  • Python is strong and very lively in the Big Data world
  • Asynchronous and distributed architectures get more and more traction and interest

Videos

All the talks videos are already online, you should check them out !

uWSGI v2.0.5.1

This release is important to me (and my company) as it officially introduces a few features we developed for our needs and then contributed to uWSGI.

Special congratulations to my co-worker @btall for his first contribution and for those nice features to the metrics subsystem with many thanks as usual to @unbit for reviewing and merging them so quickly.

new features

  • graceful reload of mule processes (Credits: Paul Egan) :¬†SIGHUP is now sent to mules instead of directly killing them, by default you have 60 seconds to react before a¬†SIGKILL
  • ‚Äďmetrics-no-cores, ‚Äďstats-no-cores, ‚Äďstats-no-metrics : don’t calculate and process all those core related metrics (gevent anyone ?)
  • reset_after_push¬†for metrics (Credits: Babacar Tall) : this metric attribute ensures that the metric value is reset to 0 or its hardcoded initial_value every time the metric is pushed to some external system (like carbon, or statsd)
  • new metric_set_max and metric_set_min helpers (Credits: Babacar Tall)¬†: can be used to avoid having to call “metric_get“ when you need a metric to be set at a maximal or minimal value. Another simple use case is to use the “avg“ collector to calculate an average between some *max* and *min* set metrics. Available in C and python.

See the full changelog here, especially some interesting bugfixes.

uWSGI v2.0.4

Quick post for an interesting version bump of uWSGI which brings an experimental loopengine for python3.4 asyncio (aka tulip) !

If you want to try it out, I added a python_asyncio¬†USE flag. I’ve also made some cleanups on the ebuild wrt python versions and dropped older versions of uWSGI.

highlights

  • experimental asyncio loop engine (python 3.4 only)
  • httprouter advanced timeout management
  • purge LRU cache (v2) feature
  • allow duplicate headers in http parsers
  • faster on_demand Emperor management
  • fixed segfault for unnamed loggers

See the full changelog here.

uWSGI v2.0

Yesterday was a big day for the famous application container uWSGI. We released the brand new version 2.0 LTS along with quite a huge bump of the ebuild, closing 6 bugs at once. I thought I’d give some input about the ebuild changes and some quick notes about uWSGI. Many thanks again to¬†@dev-zero !

New plugins selection : UWSGI_PLUGINS

We introduced a new USE_EXPAND named UWSGI_PLUGINS so that you can now select which plugins to build individually. This is a great step as it makes the compilation more clear and lets you fine tune your uWSGI installation.

Along this work, we had to describe each plugin which was also quite a challenge. To my knownledge, this has not been done anywhere else so here it is. Please ping me if you have something to add or if we failed to describe a plugin correctly.

Migration note :¬†You will need to change your package.use configuration to switch to using UWSGI_PLUGINS. As an example, where you had the USE flag spooler enabled you’ll now need to use uwsgi_plugins_spooler.

uWSGI v2.0 highlights

These are my biased favorites, go check for more, it’s huge !

uWSGI : v1.4.9 released

Yet another version bump for this very active package.

highlights

  • avoid crashing carbon on master shutdown
  • call ERR_clear_error after each https session close
  • fixed broodlord mode
  • removed broken JVM and JWSGI plugins (stable versions are in 1.9)
  • backported cache_update for lua and fixed its lock handling

Full changelog is here.

uWSGI : v1.4.8 released & v2.0 sneak peek

Yet another bump for uWSGI as upstream is working hard on the 1.9 branch which will lead to the 2.0 LTS version. I guess it’s time I take a few moments to give you some hints about what’s coming for the v2.0 of uWSGI, be aware that this is some heavy stuff.

future v2.0 highlights

  • new fully non-blocking API which applies to all plugins, this will benefit the perl/PSGI plugin as well
  • faster uwsgi/HTTP/FastCGI/SCGI native sockets thanks to better parsers
  • splitted error logging from request logging for enhanced debugging
  • more offloading¬†improvements such as a new function to write files on disk and non-blocking workers for static files service
  • better static files handling thanks to the new caching system
  • totally rewritten web cache system allows you to have multiple caches per instance and tune them finely
  • replaced the old clustering system with a new Legion subsystem providing resources management (yeah you wouldn’t need stuff like pacemaker to handle your uWSGI cluster)
  • advanced exception subsystem
  • SPDY v3 support
  • SNI support
  • support for¬†HTTP router keepalive, auto-chunking, auto-gzip and transparent websockets
  • a SSL router will be available
  • websockets API sponsored by¬†20Tab S.r.l. (a company working on HTML5 browsers game, thanks guys)
  • programmable internal router
  • and of course, the Mono/ASP.NET plugin I talked about in my previous post

See the full and detailed list here

v1.4.8 highlights

  • added support for ruby 2.0
  • removed the mono/asp.net plugin (a new, working one, is in 1.9)
  • backported the improved carbon plugin
  • fixed a corner-case bug with the caching subsystem (Laurent Luce)
  • fixed ipcsem on Linux
  • backported –not-log-alarm (negative version of –log-alarm)
  • backported add_timer and add_rb_timer api functions for the perl/psgi
    plugin
  • backported –for-glob, this is like –for but with glob expansion (Guido
    Berhoerster)
  • avoid gateways crash on master shutdown
  • backported https re-handshake management
  • improved gevent timeout management
  • uWSGI can now be installed as a ruby gem
  • backported –http-socket-modifier1/2

uWSGI : Mono ASP.NET support

Quick post to point out that the upcoming 1.9 release of uWSGI will support running ASP.NET applications using Mono.

Not to mention all the benefits of the uWSGI application deployment and monitoring mechanisms, this is a very interesting point as you can have a unique platform running your Python and ASP.NET applications ! I’ll certainly keep an eye on it.