Python微型Web服务始终挂起

时间:2016-11-10 06:02:41

标签: python web-services io wsgi bottle

我构建了一个微型Web服务,但我发现它很多。挂起我的意思是所有请求都会超时,当它挂起时,我可以看到进程在服务器中正常运行,只使用大约15MB内存。我认为发布这是一个非常有趣的问题,代码非常简单,请告诉我我做错了什么。

app = Bottle()
# static routing
@app.route('/')
def server_static_home():
    return static_file('index.html', root='client/')

@app.route('/<filename>')
def server_static(filename):
    return static_file(filename, root='client/')

@app.get('/api/data')
def getData():
    data = {}
    arrayToReturn = []
    with open("data.txt", "r") as dataFile:
        entryArray = json.load(dataFile)
        for entry in entryArray:
            if not entry['deleted']:
                arrayToReturn.append(entry)
        data["array"] = arrayToReturn

    return data

@app.put('/api/data')
def changeEntry():

    jsonObj = request.json
    with open("data.txt", "r+") as dataFile:
        entryArray = json.load(dataFile)
        for entry in entryArray:
            if entry['id'] == jsonObj['id']:
                entry['val'] = jsonObj['val']
        dataFile.seek(0)
        json.dump(entryArray, dataFile, indent=4)
        dataFile.truncate()

    return {"success":True}

run_simple('0.0.0.0', 80, app, use_reloader=True)

基本上mydomain.com是路由到我的index.html并加载必要的JS,CSS文件,这就是静态路由部分正在做的事情。加载页面后,会向GET触发ajax /api/data请求以加载数据,当我修改数据时,它会向Put发出另一个ajax /api/data请求以修改数据。

如何重现

重现挂起非常容易,我只需要访问mydomain.com并快速刷新页面10-30次,然后就会停止响应。但我无法在本地重现这一点,我刷新速度如何,data.txt在我的本地机器上是一样的。

更新

事实证明,读取/写入文件不是问题,但尝试写入损坏的管道时出现问题。发送请求的客户端在接收所有数据之前关闭连接。我现在正在寻找解决方案......

2 个答案:

答案 0 :(得分:3)

您似乎正在尝试使用每个data.txt请求打开并阅读相同的PUT文件。最终,您将遇到此体系结构的并发问题,因为您将有多个请求尝试打开并写入同一文件。

最好的解决方案是将数据保存到数据库(类似于MySQL,Postgres,Mongodb),而不是写入磁盘上的平面文件。

但是,如果您必须写入平面文件,那么您应该为每个请求写入不同的文件,其中文件的名称可以是jsonObj['id'],这样可以避免多个请求尝试的问题同时读/写同一个文件。

答案 1 :(得分:1)

读取和写入您的data.txt文件将成为加尔文提及的竞争条件的受害者。 python中的数据库非常简单,尤其是像SqlAlchemy这样的库。但是如果你坚持,你也可以使用全局字典和锁,假设你的web服务器没有作为多个进程运行。像

这样的东西
entryArray = {}
mylock = threading.Lock()
@app.put('/api/data')
def changeEntry():

    jsonObj = request.json
    with mylock.lock:
        for entry in entryArray:
           if entry['id'] == jsonObj['id']:
              entry['val'] = jsonObj['val']