所以我决定今天使用Django REST Framework开发我的REST API。我发送的请求是一个GET请求,它基本上从数据库中检索最新的50个帖子并以JSON格式返回。
使用Apache Benchmark,统计数据为:
Server Software: nginx/1.4.6
Concurrency Level: 100
Time taken for tests: 18.394 seconds
Complete requests: 1000
Failed requests: 0
Non-2xx responses: 1000
Total transferred: 5628000 bytes
HTML transferred: 5447000 bytes
Requests per second: 54.36 [#/sec] (mean)
Time per request: 1839.442 [ms] (mean)
Time per request: 18.394 [ms] (mean, across all concurrent requests)
Transfer rate: 298.79 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 17 1137 1899.3 31 12366
Processing: 25 189 314.2 31 1418
Waiting: 24 184 309.4 29 1415
Total: 44 1326 1846.3 888 12407
Percentage of the requests served within a certain time (ms)
50% 888
66% 1178
75% 1775
80% 2286
90% 3434
95% 4576
98% 7859
99% 7922
100% 12407 (longest request)
这显然非常缓慢......但我不确定如何改善这一点。
PS:我对开发服务器非常陌生,并希望从中吸取教训。在上面的GET请求中,我没有在服务器端进行任何类型的线程。它只是做的就是:
user_id = str(request.QUERY_PARAMS.get("user_id", None))
cur = connection.cursor()
cur.execute("SELECT * FROM get_posts(%s)", [user_id]) # This is a Function in the SQL database
return Response(convertToDict(cursor))
我想提高GET请求的速度,那么我可以做些什么才能让它更快?
答案 0 :(得分:2)
好吧,看到一个原始的SQL查询(这是另一个节目)我有点惊讶,但你可以做各种各样的事情。
<强> TL; DR 强>
进行性能测试非常棒,定期对这些结果进行基准测试和记录是一种很好的做法,但基准测试可能很难做到:您必须考虑软件和硬件 - 测试结果将在很大程度上取决于这两件事的互动。尽力为这些东西复制你的生产环境并尝试不同的配置(你是{{3}},对吗?)以确定合适的。
旁注:我对AB并不是非常熟悉,但看起来你也会根据看似不是预期行为的输出返回HTML。
要做的第一件事就是以深思熟虑的方式评估你所做的事情。
使用诸如django-debug-toolbar
之类的东西来查看是否存在一些查询瓶颈 - 许多链接在一起的查询,长时间运行的查询等。如果您需要更精细,您的数据库可能具有记录工具来记录长查询。
假设您的数据非常规范化(在正常形式的意义上),这可能是引入非规范化的地方,因此您不必遍历尽可能多的关系。
你也可以引入原始SQL(但你似乎已经这样做了。)
您应该努力确保将业务逻辑放在请求和响应周期的正确部分。很多时候,为了让它正常工作,你把事情放在适当的地方,也许你最初的决定是找到它的限制。
您似乎正在做一些非常简单的事情:获取表格中的最后50个条目。如果您正在计算是否包含帖子,您应该将其留给数据库 - 它应该在处理要检索的数据时处理所有逻辑。
在您使用它时,请尝试进行更多性能测试,并查看代码的哪些区域落后。也许你可以做的事情可以改善你的代码(虽然是其他人可读和可理解的),并给你一个性能提升。列表推导,生成器,利用prefetch_和select_related,注意懒惰地评估查询 - 所有这些都值得实现,因为它们的功能已被充分记录和理解。也就是说,请务必仔细记录这些决定,以备将来的自己和其他人使用。
由于它与Django REST框架有关,我对视图代码的实现并不熟悉,我可能会坚持使用它附带的JSON序列化程序。
另一个有用的技巧是执行诸如实施12factor策略(但最有可能使用pagination)之类的事情,这样数据才会以小块形式传输到客户端。这将严重依赖于用例。
这是一个很好的介绍:
您可以使用REST Framework将数据保存在服务器的RAM中,以便Django快速访问。
通常,哪种缓存最有效将取决于数据本身。可能的情况是,使用搜索引擎来存储您经常查询的文档将是最有用的。但是,一个好的开始是cache。您可以阅读有关从各种来源实现缓存的所有信息,但是使用Django搜索的好地方是Redis。
速度也可以与硬件有关。您应该考虑软件的要求及其依赖性。做一些测试,搜索并尝试适合您的方法。在问题上投入更多硬件会导致边际收益严重下降。
答案 1 :(得分:1)
你可以发布你的get_posts(user_id)方法??。
提高绩效的步骤
对get_posts()方法进行改进。您需要确保对数据库的查询数量最少。尝试使用一个.filter获取结果,并使用select_related,prefetch相关以减少数据库调用。 https://docs.djangoproject.com/en/1.8/ref/models/querysets/#prefetch-related
如果需要,可以将.extra用于.filter,通过该属性可以向模型实例添加无法通过单个查询完成的其他属性https://docs.djangoproject.com/en/1.8/ref/models/querysets/#extra
对get_posts()进行这些更改,并查看您的GET请求如何响应。如果它仍然滞后,您可以选择缓存。
大部分时间消耗将用于数据库调用。如果优化get_posts(),您可能会对性能
感到满意