A huge, grateful "thank you!"

Kent

On Mon, Mar 21, 2016 at 6:30 PM, Graham Dumpleton <
graham.dumple...@gmail.com> wrote:

>
> On 22 Mar 2016, at 4:01 AM, Kent Bower <k...@bowermail.net> wrote:
>
> In your recipe for a background monitoring thread watching memory
> consumption, after issuing the SIGUSR1, I'd probably just want the thread
> to exit instead of sleeping... do I just do "sys.exit()" to safely
> accomplish that?
>
>
> The code isn’t just sleeping. It waits on a queue object which has
> something placed on it when mod_wsgi is shutting down the process via
> atexit callback. When the thread gets that it will exit cleanly, with the
> main thread waiting on it to exit to ensure it isn’t running.
>
> If you just call sys.exit() that results in a SystemExit exception being
> raised which causes the thread to exit but leaves an exception in the error
> logs.
>
> The use of the queue is better as it ensures that threads are shutdown
> properly when process is shutting down, else you risk that the thread could
> try and run while interpreter is being destroyed, causing Python to crash
> the process.
>
> Also, regarding my observations of paster returning garbage-collected
> memory to the OS, was I just getting lucky while monitoring (the memory was
> at the very top of the allocated memory)?  This is a universal python issue?
>
>
> It is a universal issue with any programs running on a UNIX system.
>
> You may want to Google up some articles on how memory allocation in UNIX
> as well as in Python works.
>
>
> Again, thanks for all your help!
>
> On Sat, Mar 19, 2016 at 11:22 PM, Graham Dumpleton <
> graham.dumple...@gmail.com> wrote:
>
>>
>> On 20 Mar 2016, at 1:10 AM, Kent Bower <k...@bowermail.net> wrote:
>>
>> Thanks Graham, few more items inline...
>>
>> On Sat, Mar 19, 2016 at 1:24 AM, Graham Dumpleton <
>> graham.dumple...@gmail.com> wrote:
>>
>>>
>>> On 17 Mar 2016, at 11:28 PM, Kent Bower <k...@bowermail.net> wrote:
>>>
>>> My answers are below, but before you peek, Graham, note that you and I
>>> have been through this memory discussion before & I've read the vertical
>>> partitioning article and use inactivity-timeout, "WSGIRestrictEmbedded On",
>>> considered maximum-requests, etc.
>>>
>>> After years of this, I'm resigned to the fact that python is memory
>>> hungry, especially built on many of these web-stack and database libraries,
>>> etc.  I'm Ok with that.   I'm fine with a high-water RAM mark imposed by
>>> running under Apache, mostly.  But, dang, it sure would be great if the 1
>>> or 2% of requests that really (and legitimately) hog a ton of RAM, like,
>>> say 500MB extra, didn't keep it when done.  I may revisit vertical
>>> partitioning again, but last time I did I think I found that the 1 or 2% in
>>> my case generally won't be divisible by url.  In most cases I wouldn't know
>>> whether the particular request is going to need lots of RAM until
>>> *after *the database queries return (which is far too late for vertical
>>> partitioning to be useful).
>>>
>>> So I was mostly just curious about the status of nginx running wsgi,
>>> which doesn't solve python's memory piggishness, but would at least
>>> relinquish the extra RAM once python garbage collected.
>>>
>>>
>>> Where have you got the idea that using nginx would result in memory
>>> being released back to the OS once garbage collected? It isn’t able to do
>>> that.
>>>
>>> The situations are very narrow as to when a process is able to give back
>>> memory to the operating system. It can only be done when the now free
>>> memory was at top of allocated memory. This generally only happens for
>>> large block allocations and not in normal circumstances for a running
>>> Python application.
>>>
>>
>>
>> At this point I'm not sure where I got that idea, but I'm surprised at
>> this.  For example, my previous observations of paster running wsgi were
>> that it is quite faithful at returning free memory to the OS.  Was I just
>> getting lucky, or would paster be different for some reason?
>>
>> In any case, if nginx won't solve that, then I can't see any reason to
>> even consider it over apache/mod_wsgi.  Thank you for answering that.
>>
>>
>>>
>>> (Have you considered a max-memory parameter to mod_wsgi that would
>>> gracefully stop taking requests and shutdown after the threshold is reached
>>> for platforms that would support it?  I recall -- maybe incorrectly -- you
>>> saying on Windows or certain platforms you wouldn't be able to support
>>> that.  What about the platforms that *could *support it?  It seems to
>>> me to be the very best way mod_wsgi could approach this Apache RAM nuance,
>>> so seems like it would be tremendously useful for the platforms that could
>>> support it.)
>>>
>>>
>>> You can do this yourself rather easily with more recent mod_wsgi version.
>>>
>>> If you create a background thread from a WSGI script file, in similar
>>> way as monitor for code changes does in:
>>>
>>>
>>> http://modwsgi.readthedocs.org/en/develop/user-guides/debugging-techniques.html#extracting-python-stack-traces
>>>
>>> but instead of looking for code changes, inside the main loop of the
>>> background thread do:
>>>
>>>     import os
>>>     import mod_wsgi
>>>
>>>     metrics = mod_wsgi.process_metrics()
>>>
>>>     if metrics[‘memory_rss’] > MYMEMORYTHRESHOLD:
>>>         os.kill(os.getpid(), signal.SIGUSR1)
>>>
>>> So mod_wsgi provides the way of determining the amount of memory without
>>> resorting to importing psutil, which is quite fat in itself, but how you
>>> use it is up to you.
>>>
>>
>>
>> Right, that's an idea; (could even be a shell script that takes this
>> approach, I suppose, but I like your recipe.)
>>
>> Unfortunately, I don't want to *automate *bits that can feasibly clobber
>> blocked sessions.  SIGUSR1, after graceful-timeout & shutdown-timeout, can
>> result in ungraceful killing.  Our application shares a database with an
>> old legacy application which was poorly written to hold transactions while
>> waiting on user input (this was apparently common two decades ago).  So,
>> unfortunately, it isn't terribly uncommon that our application is blocked
>> at the database level waiting for someone using the legacy application who
>> has a record(s) locked and may not even be at their desk or may have gone
>> to lunch.  Sometimes our client's IT staff has to hunt down these people or
>> decide to kill their database session.  In any case, from a professional
>> point of view, our application should be the responsible one and wait
>> patiently, allowing our client's IT staff the choice of how to handle those
>> cases.  So, while the likelihood is pretty low, even with graceful-timeout
>> & shutdown-timeout set at a very high value like 5 minutes,* I still run
>> the risk of killing legitimate sessions with SIGUSR1*.  (I've brought
>> this up before and you didn't agree with my gripe and I do understand why,
>> but in my use case, I don't feel I can automate that route responsibly....
>> we do use SIGUSR1 manually sometimes, when we can monitor and react to
>> cases where a session is blocked at the database level.)
>>
>>
>> If we have discussed it previously, then I may not have anything more to
>> add.
>>
>> Did I previously suggest offloading this memory consuming tasks behind a
>> job queue run under Celery or something else? That way they are out of the
>> web server processes at least.
>>
>> inactivity-timeout doesn't present this concern: it won't ever kill
>> anything, just silently restarts like a good boy when inactive.  I've
>> recently reconsidered dropping that way down from 30 minutes.  (When I
>> first implemented this, it was just to reclaim RAM at the end of the day,
>> so that's why it is 30 minutes.  I didn't like the idea of churning new
>> processes during busy periods, but I've been thinking 1 or 2 minutes may be
>> quite reasonable.)
>>
>> If I could signal processes to shutdown at their next opportunity
>> (meaning the next time they are handling no requests, like
>> inactivity-timeout), that would solve many issues in this regard for me
>> because I could signal these processes when their RAM consumption is high
>> and let them restart when "convenient," being the ultimate in
>> gracefulness.  SIGUSR2 could mean "the next time you get are completely
>> idle," while SIGUSR1 continues to mean "initiate shutdown now.”
>>
>>
>> That is what SIGUSR1 does it you set graceful-timeout large enough. It is
>> SIGINT or SIGTERM which is effectively initiate shutdown now. So shouldn’t
>> be a need to have a SIGUSR2 as SIGUSR1 should already do what you are
>> hoping for with a reasonable setting of graceful-timeout.
>>
>>
>>> Do note that if using SIGUSR1 to restart the current process (which
>>> should only be done for deamon mode), you should also set graceful-timeout
>>> option to WSGIDaemonProcess if you have long running requests. It is the
>>> maximum time process will wait to shutdown while still waiting for requests
>>> when doing a SIGUSR2 graceful shutdown of process, before going into forced
>>> shutdown mode where no requests will be accepted and requests can be
>>> interrupted.
>>>
>>> Here (
>>> http://blog.dscpl.com.au/2009/05/blocking-requests-and-nginx-version-of.html)
>>> you discuss nginx's tendency to block requests that may otherwise be
>>> executing in a different process, depending on timing, etc.  Is this issue
>>> still the same (I thought I read a hint somewhere that there may be a
>>> workaround for that), so I ask.
>>>
>>>
>>> That was related to someones attempt to embedded a Python interpreter
>>> inside of nginx processes themselves. That project died a long time ago. No
>>> one embeds Python interpreters inside of nginx processes. It was a flawed
>>> design.
>>>
>>> I don’t what you are reading to get all these strange ideas. :-)
>>>
>>
>>
>> Google, I suppose ;)   That's why I finally asked you when I couldn't
>> find anything more about it via Google.
>>
>>
>>
>>>
>>> And so I wanted your opinion on nginx...
>>>
>>> ====
>>> Here is what you asked for if it can still be useful.
>>>
>>> I'm on mod_wsgi-4.4.6 and the particular server that prompted me this
>>> time is running Apache 2.4 (prefork), though some of our clients use 2.2
>>> (prefork).
>>>
>>> Our typical wsgi conf setting is something like this, though threads and
>>> processes varies depending on server size:
>>>
>>> LoadModule wsgi_module modules/mod_wsgi.so
>>> WSGIPythonHome /home/rarch/tg2env
>>> # see http://code.google.com/p/modwsgi/issues/detail?id=196#c10 concerning
>>> timeouts
>>> WSGIDaemonProcess rarch processes=20 threads=14 inactivity-timeout=1800
>>> display-name=%{GROUP} graceful-timeout=5
>>> python-eggs=/home/rarch/tg2env/lib/python-egg-cache
>>>
>>>
>>> Is your web server really going to be idle for 30 minutes? I can’t see
>>> how that would have been doing anything.
>>>
>>> Also, in mod_wsgi 4.x when inactivity-timeout kicks in has changed.
>>>
>>> It used to apply when there were active requests and they were blocked,
>>> as well as when no requests were running.
>>>
>>> Now it only applies to case where there are no requests.
>>>
>>> The case for running but blocked requests is now handled by
>>> request-timeout.
>>>
>>> You may be better of setting request-timeout now to be a more reasonable
>>> value for your expected longest request, but set inactivity-timeout to
>>> something much shorter.
>>>
>>> So suggest you play with that.
>>>
>>> Also, are you request handles I/O or CPU intensive and how many requests?
>>>
>>> Such a high number of processes and threads always screams to me that
>>> half the performance problems are due to setting these too [HIGH], invoking
>>> pathological OS process swapping issues and Python GIL issues.
>>>
>>>
>>
>> Yes, the requests are I/O intensive (that is, database intensive, which
>> adds a huge overhead to our typical request).  Often requests finish in
>> under a second or two, but they also can take many seconds (not
>> *terrible *for the user, but sometimes they do a lot of processing with
>> many trips to the database).
>> We have several clients (companies), so the number of requests varies
>> widely, but can get pretty heavy on busy days (like black friday, since
>> they are in retail).   We've played with those numbers quite a bit and
>> without high numbers like that, responsiveness suffers because we backlog
>> due to requests often taking several seconds.
>>
>> Thanks for all your input, you've been tremendously helpful!
>> Kent
>>
>>
>>
>>
>>> WSGIProcessGroup rarch
>>> WSGISocketPrefix run/wsgi
>>> WSGIRestrictStdout Off
>>> WSGIRestrictStdin On
>>> # Memory tweak.
>>> http://blog.dscpl.com.au/2009/11/save-on-memory-with-modwsgi-30.html
>>> WSGIRestrictEmbedded On
>>> WSGIPassAuthorization On
>>>
>>> # we'll make the /tg/ directory resolve as the wsgi script
>>> WSGIScriptAlias /tg
>>> /home/rarch/trunk/src/appserver/wsgi-config/wsgi-deployment.py
>>> process-group=rarch application-group=%{GLOBAL}
>>> WSGIScriptAlias /debug/tg
>>> /home/rarch/trunk/src/appserver/wsgi-config/wsgi-deployment.py
>>> process-group=rarch application-group=%{GLOBAL}
>>>
>>> MaxRequestsPerChild  0
>>> <IfModule prefork.c>
>>> MaxClients       308
>>> ServerLimit      308
>>> </IfModule>
>>> <IfModule worker.c>
>>> ThreadsPerChild  25
>>> MaxClients       400
>>> ServerLimit      16
>>> </IfModule>
>>>
>>>
>>> Thanks for all your help and for excellent software!
>>> Kent
>>>
>>>
>>> On Wed, Mar 16, 2016 at 7:27 PM, Graham Dumpleton <
>>> graham.dumple...@gmail.com> wrote:
>>>
>>>> On the question of whether nginx will solve this problem, I can’t see
>>>> how.
>>>>
>>>> When one talks about nginx and Python web applications, it is only as a
>>>> proxy for HTTP requests to some backend WSGI server. The Python web
>>>> application doesn’t run in nginx itself. So memory issues and how to deal
>>>> with them are the provence of the WSGI server used, whatever that is and
>>>> not nginx.
>>>>
>>>> Anyway, answer the questions below and can start with that.
>>>>
>>>> You really want to be using recent mod_wsgi version and not Apache 2.2.
>>>>
>>>> Apache 2.2 design has various issues and bad configuration defaults
>>>> which means it can gobble up more memory than you want. Recent mod_wsgi
>>>> versions have workarounds for Apache 2.2 issues and are much better at
>>>> eliminating those Apache 2.2 issues. Recent mod_wsgi versions also have
>>>> fixes for memory usage problems in some corner cases. As far as what I mean
>>>> by recent, I recommend 4.4.12 or later. The most recent version is 4.4.21.
>>>> If you are stuck with 3.4 or 3.5 from your Linux distro that is not good
>>>> and that may increase problems.
>>>>
>>>> So long as got recent mod_wsgi version then can look at using vertical
>>>> partitioning to farm out memory hungry request handlers to their own daemon
>>>> process group and better configure those to handle that and recycle
>>>> processes based on activity or, memory usage. A blog post related to that
>>>> is:
>>>>
>>>> *
>>>> http://blog.dscpl.com.au/2014/02/vertically-partitioning-python-web.html
>>>>
>>>> Graham
>>>>
>>>> On 17 Mar 2016, at 7:15 AM, Graham Dumpleton <
>>>> graham.dumple...@gmail.com> wrote:
>>>>
>>>> What version of mod_wsgi and Apache are you using?
>>>>
>>>> Are you stuck with old versions of both?
>>>>
>>>> For memory tracking there are API calls mod_wsgi provides in recent
>>>> versions for getting memory usage which can be used as part of scheme to
>>>> trigger a process restart. You can’t use sys.exit(), but can use signals to
>>>> trigger a clean shutdown of a process. Again better to have recent mod_wsgi
>>>> versions as can then also set up some graceful timeout options for signal
>>>> induced restart.
>>>>
>>>> Also, what is your mod_wsgi configuration so can make sure doing all
>>>> the typical things one would do to limit memory usage, or quarantine
>>>> particular handlers which are memory hungry?
>>>>
>>>> Graham
>>>>
>>>> On 17 Mar 2016, at 4:29 AM, Kent Bower <k...@bowermail.net> wrote:
>>>>
>>>> Interesting idea..  yes, we are using multiple threads and also other
>>>> stack frameworks, so that's not straightforward, but worth thinking
>>>> about... not sure how to approach that with the other threads.  Thank you
>>>> Bill.
>>>>
>>>> On Wed, Mar 16, 2016 at 1:11 PM, Bill Freeman <ke1g...@gmail.com>
>>>> wrote:
>>>>
>>>>> I don't know about nginx, but one possibility, if the large memory
>>>>> requests are infrequent, is to detect when you have completed one and
>>>>> trigger the exit/reload of the daemon process (calling sys.exit() is not
>>>>> the way, since there could be other threads in the middle of something,
>>>>> unless you run one thread per process).
>>>>>
>>>>> On Wed, Mar 16, 2016 at 7:50 AM, Kent <jkentbo...@gmail.com> wrote:
>>>>>
>>>>>> I'm looking for a very brief high-level pros vs. cons of wsgi under
>>>>>> *apache *vs. under *nginx *and then to be pointed to more details I
>>>>>> can study myself (or at least the latter).
>>>>>>
>>>>>> Our application occasionally allows requests that consume a large
>>>>>> amount of RAM (no obvious way around that, they are valid requests) and
>>>>>> occasionally this causes problems since we can't reclaim the RAM readily
>>>>>> from apache.  (We already have tweaked with and do use
>>>>>> "inactivity-timeout".   This helps, but still now and then we hit 
>>>>>> problems
>>>>>> where we run into swapping to disk.)
>>>>>>
>>>>>> I'm wondering if nginx may solve this problem.  I've read much of
>>>>>> what you (Graham) have had to say about the memory strategies with apache
>>>>>> and mod_wsgi, but wonder what your opinion of nginx is and where you've
>>>>>> already discussed this.  I've read articles I could find you've written 
>>>>>> on
>>>>>> nginx, such as "Blocking requests and nginx version of mod_wsgi,"  but
>>>>>> wonder if the same weaknesses are still applicable today, 7 years later?
>>>>>>
>>>>>>
>>>>>> Thank you very much in advance!
>>>>>> Kent
>>>>>>
>>>>>> --
>>>>>> You received this message because you are subscribed to the Google
>>>>>> Groups "modwsgi" group.
>>>>>> To unsubscribe from this group and stop receiving emails from it,
>>>>>> send an email to modwsgi+unsubscr...@googlegroups.com.
>>>>>> To post to this group, send email to modwsgi@googlegroups.com.
>>>>>> Visit this group at https://groups.google.com/group/modwsgi.
>>>>>> For more options, visit https://groups.google.com/d/optout.
>>>>>>
>>>>>
>>>>>
>>>>> --
>>>>> You received this message because you are subscribed to a topic in the
>>>>> Google Groups "modwsgi" group.
>>>>> To unsubscribe from this topic, visit
>>>>> https://groups.google.com/d/topic/modwsgi/wyo2bJP0Cfc/unsubscribe.
>>>>> To unsubscribe from this group and all its topics, send an email to
>>>>> modwsgi+unsubscr...@googlegroups.com.
>>>>> To post to this group, send email to modwsgi@googlegroups.com.
>>>>> Visit this group at https://groups.google.com/group/modwsgi.
>>>>> For more options, visit https://groups.google.com/d/optout.
>>>>>
>>>>
>>>>
>>>> --
>>>> You received this message because you are subscribed to the Google
>>>> Groups "modwsgi" group.
>>>> To unsubscribe from this group and stop receiving emails from it, send
>>>> an email to modwsgi+unsubscr...@googlegroups.com.
>>>> To post to this group, send email to modwsgi@googlegroups.com.
>>>> Visit this group at https://groups.google.com/group/modwsgi.
>>>> For more options, visit https://groups.google.com/d/optout.
>>>>
>>>>
>>>>
>>>>
>>>> --
>>>> You received this message because you are subscribed to a topic in the
>>>> Google Groups "modwsgi" group.
>>>> To unsubscribe from this topic, visit
>>>> https://groups.google.com/d/topic/modwsgi/wyo2bJP0Cfc/unsubscribe.
>>>> To unsubscribe from this group and all its topics, send an email to
>>>> modwsgi+unsubscr...@googlegroups.com.
>>>> To post to this group, send email to modwsgi@googlegroups.com.
>>>> Visit this group at https://groups.google.com/group/modwsgi.
>>>> For more options, visit https://groups.google.com/d/optout.
>>>>
>>>
>>>
>>> --
>>> You received this message because you are subscribed to the Google
>>> Groups "modwsgi" group.
>>> To unsubscribe from this group and stop receiving emails from it, send
>>> an email to modwsgi+unsubscr...@googlegroups.com.
>>> To post to this group, send email to modwsgi@googlegroups.com.
>>> Visit this group at https://groups.google.com/group/modwsgi.
>>> For more options, visit https://groups.google.com/d/optout.
>>>
>>>
>>>
>>> --
>>> You received this message because you are subscribed to a topic in the
>>> Google Groups "modwsgi" group.
>>> To unsubscribe from this topic, visit
>>> https://groups.google.com/d/topic/modwsgi/wyo2bJP0Cfc/unsubscribe.
>>> To unsubscribe from this group and all its topics, send an email to
>>> modwsgi+unsubscr...@googlegroups.com.
>>> To post to this group, send email to modwsgi@googlegroups.com.
>>> Visit this group at https://groups.google.com/group/modwsgi.
>>> For more options, visit https://groups.google.com/d/optout.
>>>
>>
>>
>> --
>> You received this message because you are subscribed to the Google Groups
>> "modwsgi" group.
>> To unsubscribe from this group and stop receiving emails from it, send an
>> email to modwsgi+unsubscr...@googlegroups.com.
>> To post to this group, send email to modwsgi@googlegroups.com.
>> Visit this group at https://groups.google.com/group/modwsgi.
>> For more options, visit https://groups.google.com/d/optout.
>>
>>
>>
>> --
>> You received this message because you are subscribed to a topic in the
>> Google Groups "modwsgi" group.
>> To unsubscribe from this topic, visit
>> https://groups.google.com/d/topic/modwsgi/wyo2bJP0Cfc/unsubscribe.
>> To unsubscribe from this group and all its topics, send an email to
>> modwsgi+unsubscr...@googlegroups.com.
>> To post to this group, send email to modwsgi@googlegroups.com.
>> Visit this group at https://groups.google.com/group/modwsgi.
>> For more options, visit https://groups.google.com/d/optout.
>>
>
>
> --
> You received this message because you are subscribed to the Google Groups
> "modwsgi" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to modwsgi+unsubscr...@googlegroups.com.
> To post to this group, send email to modwsgi@googlegroups.com.
> Visit this group at https://groups.google.com/group/modwsgi.
> For more options, visit https://groups.google.com/d/optout.
>
>
> --
> You received this message because you are subscribed to a topic in the
> Google Groups "modwsgi" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/d/topic/modwsgi/wyo2bJP0Cfc/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to
> modwsgi+unsubscr...@googlegroups.com.
> To post to this group, send email to modwsgi@googlegroups.com.
> Visit this group at https://groups.google.com/group/modwsgi.
> For more options, visit https://groups.google.com/d/optout.
>

-- 
You received this message because you are subscribed to the Google Groups 
"modwsgi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to modwsgi+unsubscr...@googlegroups.com.
To post to this group, send email to modwsgi@googlegroups.com.
Visit this group at https://groups.google.com/group/modwsgi.
For more options, visit https://groups.google.com/d/optout.

Reply via email to