使用 Python (Sanic) 开发 REST API
Developing REST APIs using Python (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 APIs
这是我的结论:
我尝试使用 wrk 和 50 个线程 运行 30 秒测试来对这个 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
我的疑问是,我该如何改进
- 超时的请求数。目前是4,应该是0。
- 平均延迟,约为 550 毫秒(太多)
在 POST 请求的情况下,它非常非常糟糕,我正在尝试加载 keras 模型并进行预测。
代码写法有问题吗?
或
这是Sanic的限制吗?
我应该尝试另一个 REST 框架吗?
P.S:我使用 Flask 的体验在延迟和超时请求方面更差。
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 响应时间和减少超时请求的更好方法?
禁用 debug
并将 workers
设置为实例中 CPU 的数量(t2.med 为 2):
app.run(host="0.0.0.0", port=8001, workers=2)
这里的游戏有点晚了,但我相信为了让它真正异步,您需要添加 await
调用。否则你只是在调用阻塞函数。
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 APIs这是我的结论:
我尝试使用 wrk 和 50 个线程 运行 30 秒测试来对这个 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
我的疑问是,我该如何改进
- 超时的请求数。目前是4,应该是0。
- 平均延迟,约为 550 毫秒(太多)
在 POST 请求的情况下,它非常非常糟糕,我正在尝试加载 keras 模型并进行预测。
代码写法有问题吗?
或
这是Sanic的限制吗?
我应该尝试另一个 REST 框架吗?
P.S:我使用 Flask 的体验在延迟和超时请求方面更差。
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 响应时间和减少超时请求的更好方法?
禁用 debug
并将 workers
设置为实例中 CPU 的数量(t2.med 为 2):
app.run(host="0.0.0.0", port=8001, workers=2)
这里的游戏有点晚了,但我相信为了让它真正异步,您需要添加 await
调用。否则你只是在调用阻塞函数。