On a pretty regular frequency, one of the instances will stop
responding to requests. (The site stays up because there is more than
one instance running.)
Does anybody have any suggestions on how to debug the process that is
still running? I'm not sure if it is something in my business logic
causing the problem or if there is something wrong with TG/Cherrypy.
The process is still listening on the port I started it on, a tcp
connection can be made, but no response is delivered and there is no
debugging information printed.
Thanks
Dennis
mydrawings.com
"""Base class for CherryPy filters."""
class BaseFilter(object):
"""
Base class for filters. Derive new filter classes from this, then
override some of the methods to add some side-effects.
"""
def on_start_resource(self):
"""Called before any request processing has been done"""
pass
def before_request_body(self):
"""Called after the request header has been read/parsed"""
pass
def before_main(self):
""" Called after the request body has been read/parsed"""
pass
def before_finalize(self):
"""Called before final output processing"""
pass
def before_error_response(self):
"""Called before _cp_on_error and/or finalizing output"""
pass
def after_error_response(self):
"""Called after _cp_on_error and finalize"""
pass
def on_end_resource(self):
"""Called after finalizing the output (status, header, and
body)"""
pass
def on_end_request(self):
"""Called when the server closes the request."""
pass
Cheers,
Simon
I tried settings for the thread_pool between 50 and 150 and had the
same results. I also tweaked the socket_queue_size setting but havent
noticed any difference. From what I read, cherrypy is pretty good at
handling load and being stable so I gather something I've done is
probably the culprit. I'm using sqlAlchemy and a few 3rd party
libraries not shipped standard with TG or python so perhaps one of
those libraries is consuming resources or something. Hard to say but
I'll keep working on it.
-Dennis
http://projects.amor.org/misc/wiki/HTTPREPL
Robert Brewer
System Architect
Amor Ministries
fuma...@amor.org
another thing you may want to check for, depending on what DB youre
using, is a deadlock condition. the 0.2 series also does an
unconditional "rollback" on connections returned to the connection
pool, which prevents a DB like postgres from keeping read locks open on
tables that were accessed within a connection.
also in moments of sheer multithreaded desperation, the threadframe
module can be invaluable in illustrating where a hang is occurring,
though it requires some instrumentation of your application:
http://www.majid.info/mylos/stories/2004/06/10/threadframe.html
digg effect.
Anyhow.. This does seem like it could be an issue and I think migrating
to 0.2 is pretty soon on slate.
My server is hyperthreaded so it isn't really two CPUs. In addition,
the physical server is hosting 3 virtual domains (Xen). Mydrawings.com
is the only domain that gets substantial traffic (We got Dugg Saturday
by the way) but the resources are indeed divided between the 3 domains.
I can't test for sure right now, but this setup could be part of the
problem with running mroe than once instance on the machine.
Anyhow, I plan to upgrade SQLAlchemy and to get a 2nd physical server
in operation but for the time being, our site is still surviving.
Here's crossing my fingers that servers don't lock up any more. (Which
they still have been doing even after the digg load has calmed a
little.)
Hmn,, suggestions?
connection = self.getconnection()
cu = connection[0].cursor()
sql_us = "SELECT id FROM user WHERE name = '%s'" % self.user
rws = cu.execute(sql_us)
user = cu.fetchone()
cu.executemany("INSERT INTO que (address,time,user_id) VALUES
(%s,%s,%s)", [(ref,tn,user[0]) for ref in href ])
cu.close()
self.resetconnection(connection[1])
Usage
conpool.getLock() #lock
conpool.getConnection()
conpool.relLock() #hub uses it own locking or is thread safe
hub.begin()
selectedURI = URI.select(URI.q.address == site)
selectedURIList = list(selectedURI)
if len(selectedURIList) == 0:
time_=time()
d = str(lines)
c = URI(address=site,data=d,time=time_)
hub.commit()
else:
c = selectedURIList[0]
hub.end()
#this goes in the model.py file
from sqlobject import *
from turbogears.database import AutoConnectHub
from sqlobject.mysql.mysqlconnection import MySQLConnection
import time
import threading
import MySQLdb
threadlocker = threading.Lock()
hub = AutoConnectHub()
def connect(threadIndex):
""" Function to create a connection at the start of the thread """
hub.threadConnection =
MySQLConnection('db','u','p','localhost',3306) #AutoConnectHub()#
def synch(func,*args):
def wrapper(*args):
try:
threadlocker.acquire()
return func(*args)
finally:
threadlocker.release()
return wrapper
class ConnectionPool:
def __init__(self, timeout=100, checkintervall=10):
self.timeout=timeout
self.lastaccess={}
self.connections={}
self.checkintervall=checkintervall
self.lastchecked=time.time()
self.lockingthread=None
def getConnection(self):
global hub
tid=threading._get_ident()
try:
con=self.connections[tid]
except KeyError:
print 'key error re-connecting'
self.connections[tid]=MySQLConnection('db','u','p','localhost',3306)
#hub.threadConnection
con = self.connections[tid]
self.lastaccess[tid]=time.time()
if (self.lastchecked + self.checkintervall) < time.time():
self.cleanUp()
return con
def getLock(self):
while not self._checklock():
#print 'in check lock'
time.sleep(0.02)
self.lockingthread=threading._get_ident()
getLock=synch(getLock)
def relLock(self):
self.lockingthread=None
def _checklock(self):
if self.lockingthread == threading._get_ident() or
self.lockingthread is None:
return True
return False
def cleanUp(self):
dellist=[]
for con in self.connections:
if self.lastaccess[con] + self.timeout < time.time():
self.connections[con].close()
#del self.lastaccess[con]
dellist.append(con)
for l in dellist:
print 'deleted connections'
del self.connections[l]
def kill(self):
tid=threading._get_ident()
dellist=[]
self.connections[tid].close()
#del self.lastaccess[tid]
dellist.append(tid)
for l in dellist:
print 'deleted connection'
del self.connections[l]
conpool = ConnectionPool()
>
> My problem with stability is back, I don't suggest parsing pdfs for
> hrefs.
That sounds expensive. You could do that as a background tasks and
cache the results somewhere...
Traceback (most recent call last):
File
"/usr/lib/python2.4/site-packages/CherryPy-2.2.1-py2.4.egg/cherrypy/_cphttptools.py",
line 105, in _run
self.main()
File
"/usr/lib/python2.4/site-packages/CherryPy-2.2.1-py2.4.egg/cherrypy/_cphttptools.py",
line 254, in main
body = page_handler(*virtual_path, **self.params)
File "<string>", line 3, in index
File
"/usr/lib/python2.4/site-packages/TurboGears-0.9a6-py2.4.egg/turbogears/controllers.py",
line 273, in expose
output = database.run_with_transaction(
File
"/usr/lib/python2.4/site-packages/TurboGears-0.9a6-py2.4.egg/turbogears/database.py",
line 220, in run_with_transaction
sqlalchemy.objectstore.clear()
AttributeError: 'module' object has no attribute 'objectstore'
I simply installed SA I think .2 adn TG did not run the next day. I
tried removing all .pyc. I also tg-admin sql and deleting the old
database and created a new blank one. The performance was decent
something like 1000 inserts a second for a name table. When I took the
code out of my model.py file TG exploded (thats just a coincidence
perhaps though). Does installing SQLAlchemy break Turbogears?
Seriously this is weird how could TG know about SQLAlchemy unless
something happens during easy install?
I registered a metadata but that was it. Somebody hack my machine?