Python 我的金字塔应用程序中的严重缺陷

Python 我的金字塔应用程序中的严重缺陷,python,database,pyramid,Python,Database,Pyramid,我刚刚发现我的金字塔应用程序有一个很大的问题。mongo脚手架暗示事件处理程序也应该用于处理数据库连接。其思想是,当新请求传入时,连接到数据库,当页面呈现时断开连接。 这就是我在我的\uuuu init.py\uuuu def connectDatabase(event): mongo = MongoDB() con = mongo.connectDatabase() db = con[Cfg_MongoDB_Database] event.request.con

我刚刚发现我的金字塔应用程序有一个很大的问题。mongo脚手架暗示事件处理程序也应该用于处理数据库连接。其思想是,当新请求传入时,连接到数据库,当页面呈现时断开连接。 这就是我在我的
\uuuu init.py\uuuu

def connectDatabase(event):
    mongo = MongoDB()
    con = mongo.connectDatabase()
    db = con[Cfg_MongoDB_Database]
    event.request.con = con
    event.request.db = db
    redis = Redis()
    con = redis.connectDatabase()
    event.request.redis = con
    log.debug('newrequest')

def closeConnection(event):
    mongo = MongoDB()
    mongo.closeConnection(event.request.con) 
    log.debug('newresponse')   

def main(global_config, **settings):
    config = Configurator(settings=settings, root_factory=Dashboard)
    authentication = AuthTktAuthenticationPolicy(Cfg_Auth_Key, hashalg='sha512',\
        include_ip=False, timeout=3600*24*7, max_age=3600*24*7, reissue_time=3600)
    authorization = ACLAuthorizationPolicy()
    config.set_authentication_policy(authentication)
    config.set_authorization_policy(authorization)
    config.add_static_view('includes', 'includes', cache_max_age=3600)
    config.add_renderer(".html", "pyramid.mako_templating.renderer_factory")  
    config.add_route('dash', '/')
    config.add_subscriber(connectDatabase, NewRequest)
    config.add_subscriber(closeConnection, NewResponse)
    log.debug('main')
    config.scan()
    return config.make_wsgi_app()
然而,我在连接到数据库的方法中加入了一些记录器,发现该方法被调用了10多次,如果我在
add\u static\u view
中禁用缓存超过100次。这意味着对于每个css、image、js,都会建立新的连接。这是巨大的开销!!!该网站需要300毫秒才能连接到数据库100次

/Users/jan/Documents/Test2/test2/data.py changed; reloading...
-------------------- Restarting --------------------
2013-02-01 18:32:48,351 DEBUG [test2.tools][MainThread] main
Starting server in PID 12374.
serving on http://127.0.0.1:6543
2013-02-01 18:34:14,451 DEBUG [test2.tools][Dummy-2] newrequest
2013-02-01 18:34:14,582 DEBUG [test2.tools][Dummy-2] newresponse
2013-02-01 18:34:14,952 DEBUG [test2.tools][Dummy-3] newrequest
2013-02-01 18:34:14,953 DEBUG [test2.tools][Dummy-3] newresponse
2013-02-01 18:34:17,459 DEBUG [test2.tools][Dummy-4] newrequest
2013-02-01 18:34:17,474 DEBUG [test2.tools][Dummy-4] newresponse
2013-02-01 18:34:17,482 DEBUG [test2.tools][Dummy-5] newrequest
2013-02-01 18:34:17,497 DEBUG [test2.tools][Dummy-5] newresponse
2013-02-01 18:34:19,158 DEBUG [test2.tools][Dummy-2] newrequest
2013-02-01 18:34:19,159 DEBUG [test2.tools][Dummy-2] newresponse

因此,目前的解决方案是将连接移动到模型。但我怎么知道我什么时候可以关闭连接呢?有谁能为我的问题提供更好、更优雅的解决方案吗?

pymongo内置了连接池

使用连接池不应在每个请求上创建新连接


另外,我不认为您的金字塔应用程序应该在生产中提供静态媒体服务,正是因为这个原因,apache、nginx经过优化以提供文件,您的请求不必经过您的应用程序,建议在金字塔中使用请求属性,而不是
NewRequest
事件。正如您所注意到的,该事件是为每个请求(包括静态请求)触发的。请求属性是惰性的,只有在需要时才进行计算,您可以指定在请求的生命周期内缓存(具体化)它们。我在下面链接了一个示例,演示了如何添加
request.db

下面是一些应该适合您的更新代码

def main(global_config, **settings):
    # ...

    db_url = urlparse(settings['mongo_uri'])
    config.registry.db = pymongo.Connection(
        host=db_url.hostname,
        port=db_url.port,
    )

    def add_db(request):
        db = config.registry.db[db_url.path[1:]]
        if db_url.username and db_url.password:
            db.authenticate(db_url.username, db_url.password)
        return db

    config.add_request_method(add_db, 'db', reify=True)

就让它开着吧。它可以正常工作。在生产中,pyramid不应该为您的静态媒体服务,我意识到这并不能解决您的全部问题,尽管…,pymongo已经构建了连接池是的,我将在生产中使用apache+mod_wsgi。不管怎样,我觉得建立新的连接有点开销。你们认为如何在wsgi中间件中建立连接并将其与environ传递?坏主意?还有,当我处理完连接后,如何将其返回到池中?我使用apachebenchmark对200个请求和50个并发性进行了测试。Auto_Start_Request=False配置with Start_Request()产生了最好的结果。但是现在我只想通过某种wsgi中间件使用一个连接实例进行测试。你知道怎么做到吗?