0

因为我并不真正了解 Ladon、Webservices 和 Apache 使用的底层策略或协议(我在 Windows Apache 服务器上使用 Ladon 和 Python 以及 mod_wsgi.so - 切换到 Ubuntu 系统)

我想知道这是否可以一次为 python 加载一些资源,以便公开的方法使用 python 代码中的这些资源,而不必在考虑/向 Web 服务提供新查询时再次加载这些资源?

如果可能的话,您是否有任何关于如何实现这一目标的线索,或者如果没有任何解决方法?

通常我从需要太多时间来加载(I/O)的文件中加载一些巨大的字典,并且在接收每个新的 ladon 查询时加载它,WS 太慢了,我想告诉 Ladon:“加载这个当 apache 启动时,并在 Apache 运行期间将其作为字典提供给我的所有 python Web 服务/代码”。我不会修改这些数据,所以我只需要能够读取/访问它们。

最好的祝福

第一次编辑:如果这有帮助,看起来像在我的 Ubuntu 上(我已经从我的 Win 配置切换到 Ubuntu 以更“标准”,希望我这样做是对的),Apache2 设置为 prefork 模式而不是 MPM,(如Jakob Simon-Gaarde 建议)阅读自:

@: sudo /usr/sbin/apache2 -l
Compiled in modules:
  core.c
  mod_log_config.c
  mod_logio.c
  prefork.c
  http_core.c
  mod_so.c
@: sudo /usr/sbin/apache2 -l | grep MPM
@:

我要检查如何做到这一点,也许我还在这里放了一些简化的代码,因为现在即使有你有用的答案,我也没有办法(我可以在这里做任何事情:/)

安装 MPM 模式时,在此处找到如何操作:$ sudo apt-get install apache2-mpm-worker

最后编辑

这是我的 WS 代码的骨架:

MODEL_DIR = "/home/mydata.file"

import sys
import codecs
import glob
import os
import re

import numpy

from ladon.ladonizer import ladonize
from ladon.types.ladontype import LadonType
from ladon.compat import PORTABLE_STRING

class Singleton(type): 
    _instances = {} 
    def __call__(cls, *args, **kwargs): 
        if cls not in cls._instances: 
            cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs) 
        return cls._instances[cls] 

class LDtest(object):
    __metaclass__ = Singleton
    modeldir = MODEL_DIR
    def __init__(self):
        self.load()

    def load(self):
        modeldir = LDtest.modeldir
        self.data = mywrapperfordata.mywrapperfordata(modeldir)
        b = datetime.datetime.now()
        self.features = self.mywrapperfordata.load() # loading is wrapped here
        c = datetime.datetime.now()
        print("loading: %s done." % (c-b))

    def letsdoit(self, myinput):
        return [] # actually main logic ie complex stuff involving accessing to self.features

    @ladonize(PORTABLE_STRING, [ PORTABLE_STRING ], rtype = [ PORTABLE_STRING ] )
    def ws(self, myinput):
        result = self.letsdoit(myinput)
        return result

import datetime
a = datetime.datetime.now()
myLDtest = LDtest()
b = datetime.datetime.now()
print("LDtest: %s" % (b-a))

关于加载时间:来自我的 apache2 日志:-注意模块 1 是必需的,并且由模块 2 导入,并且还作为单独的 Web 服务提供。看起来单例没有构建或不够快?

[Tue Jul 09 11:09:11 2013] [notice] caught SIGTERM, shutting down
[Tue Jul 09 11:09:12 2013] [notice] Apache/2.2.16 (Debian) mod_wsgi/3.3 Python/2.6.6 configured -- resuming normal operations
[Tue Jul 09 11:09:50 2013] [error] Module 4: 0:00:02.885693.
[Tue Jul 09 11:09:51 2013] [error] Module 0: 0:00:03.061020
[Tue Jul 09 11:09:51 2013] [error] Module 1: 0:00:00.026059.
[Tue Jul 09 11:09:51 2013] [error] Module 1: 0:00:00.012517.
[Tue Jul 09 11:09:51 2013] [error] Module 2: 0:00:00.012678.
[Tue Jul 09 11:09:51 2013] [error] Module (dbload): 0:00:00.402387 (22030)
[Tue Jul 09 11:09:54 2013] [error] Module 3: 0:00:00.000036.
[Tue Jul 09 11:13:00 2013] [error] Module 0: 0:00:03.055841
[Tue Jul 09 11:13:01 2013] [error] Module 1: 0:00:00.026215.
[Tue Jul 09 11:13:01 2013] [error] Module 1: 0:00:00.012600.
[Tue Jul 09 11:13:01 2013] [error] Module 2: 0:00:00.012643.
[Tue Jul 09 11:13:01 2013] [error] Module (dbload): 0:00:00.322444 (22030)
[Tue Jul 09 11:13:03 2013] [error] Module 3: 0:00:00.000035.
4

2 回答 2

2

mod_wsgi 在启动时启动一个或多个 Python 进程并让它们运行以处理请求。如果你加载一个模块或设置一个全局变量,当你处理下一个请求时它们仍然存在 - 但是,每个 Python 进程都有自己单独的内存块,所以如果你将 mod_wsgi 配置为启动 8 个进程并加载一个 1G数据集,最终您将使用 8G 内存。也许您应该考虑使用数据库?

编辑:谢谢 Graham :-) 因此,只有一个进程和多个线程,您可以在所有工作线程之间共享一份庞大的字典。

于 2012-09-05T16:48:42.127 回答
1

我们在所有网络项目的工作中都广泛使用 Ladon,并且我有能力开发我的私人项目(我是 Ladon 开发人员)并获得报酬 ;-) 我们的一些服务消耗大量资源,例如,我们有一个文本转语音服务,可以将每种支持的语言大约 1Gb 的数据加载到内存中,还有一个单词预测服务,可以为每种支持的语言加载大约 100Mb 的数据。

mod_wsgi 很好——我们也使用它——你需要做的是确保你的 apache 服务器被编译为 mpm-worker ( http://httpd.apache.org/docs/2.2/mod/worker.html )。在此配置中,您的服务在多线程环境而不是多进程环境中运行。效果是每个服务器进程只启动一个解释器,然后在共享资源的几个底层线程中运行您的服务。需要注意的是,您必须确保您的服务不会踩到自己的脚趾,这意味着您必须使用 mutex.acquire()/mutex.release() 保护服务类实例之间共享的全局变量和类静态变量.

除此之外,作为框架的 Ladon 是为多线程环境构建的。

最好的问候雅各布西蒙-加德

于 2012-09-06T21:01:34.737 回答