使用Python开发REST API(Sanic)

时间:2017-10-09 08:42:34

标签: python multithreading rest sanic

from sanic import Sanic
from sanic import response


app = Sanic(__name__)

@app.route('/v1/ok', methods=['GET'])
async def post_handler(request):
    return response.text("hey all good")

if __name__ == '__main__':
        app.run(host="0.0.0.0", port=8001, debug=True)

我正在尝试使用sanic

在python中编写REST API

以下是我的结论:

我尝试使用wrk使用50个运行30s测试的线程对此GET API进行基准测试。 机器使用AWS EC2 t2.medium,它有4GB RAM和2个CPU 使用的命令

wrk -t50 -c4000 -d30s http://XXX.XX.XXX.XXX:8001/v1/ok

基准测试结果

Running 30s test @ http://XXX.XX.XXX.XXX:8001/v1/ok
 50 threads and 4000 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency   559.30ms  117.86ms   1.99s    94.47%
    Req/Sec    41.92     44.33   361.00     86.14%
  53260 requests in 30.10s, 6.70MB read
  Socket errors: connect 1493, read 15631, write 0, timeout 4
Requests/sec:   1769.21
Transfer/sec:    228.06KB

我怀疑的是,我怎么能改进

  1. 超时的请求数。目前它是4.它应该为零。
  2. 平均延迟,约为550毫秒(太多)
  3. 在POST请求的情况下,非常非常糟糕,我正在尝试加载keras模型并进行预测。

    这是代码编写方式的问题吗?

    OR

    这是Sanic的限制吗?

    我应该尝试其他REST框架吗?

    P.S:在延迟和超时请求方面,我对瓶子的体验更加糟糕。

    import sys
    import os
    import json
    import pandas
    import numpy
    import optparse
    from keras.models import Sequential, load_model
    from keras.preprocessing import sequence
    from keras.preprocessing.text import Tokenizer
    from collections import OrderedDict
    from sanic import Sanic
    from sanic import response
    import time
    
    app = Sanic(__name__)
    
    @app.route('/v1/mal/prediction', methods=['POST'])
    async def post_handler(request):
        csv_file = 'alerts.csv'
        log_entry = request.json
        dataframe = pandas.read_csv(csv_file, engine='python', quotechar='|', header=None)
        dataset = dataframe.values
        X = dataset[:,0]
        for index, item in enumerate(X):
            reqJson = json.loads(item, object_pairs_hook=OrderedDict)
            del reqJson['timestamp']
            del reqJson['headers']
            del reqJson['source']
            del reqJson['route']
            del reqJson['responsePayload']
            X[index] = json.dumps(reqJson, separators=(',', ':'))
    
        tokenizer = Tokenizer(filters='\t\n', char_level=True)
        tokenizer.fit_on_texts(X)
        seq = tokenizer.texts_to_sequences([log_entry])
        max_log_length = 1024
        log_entry_processed = sequence.pad_sequences(seq, maxlen=max_log_length)
        model = load_model('model.h5')
        model.load_weights('weights.h5')
        model.compile(loss = 'binary_crossentropy', optimizer = 'adam', metrics = ['accuracy'])
        prediction = model.predict(log_entry_processed)
        return response.text(prediction[0])
    
    if __name__ == '__main__':
            app.run(host="0.0.0.0", port=8000, debug=True)
    

    请建议更好的方法来改善API响应时间并减少超时请求?

2 个答案:

答案 0 :(得分:3)

禁用debug并将workers设置为实例中的CPU数量(t2.med为2):

app.run(host="0.0.0.0", port=8001, workers=2)

答案 1 :(得分:1)

这里的游戏有点晚了,但是我相信为了使其真正异步,您需要添加await调用。否则,您只是在调用阻塞函数。