python - 如何提高 REST API 的性能?

标签 python django rest server django-rest-framework

所以我决定今天对我使用 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 请求的速度,那么我能做些什么来让它更快呢?

最佳答案

好吧,看到原始 SQL 查询(这是另一个节目)我有点惊讶,但你可以做各种各样的事情。

TL;DR

前期

进行性能测试很棒,定期进行基准测试并随着时间的推移记录这些结果是一种很好的做法,但是要正确执行基准测试可能会很棘手:您必须将软件和硬件考虑在内 - 您的测试结果将在很大程度上取决于它们之间的交互两件事情。尽力为这些东西复制您的生产环境并尝试不同的配置(您是 12factor,对吗?)以确定合适的配置。

旁注:我对 AB 不是很熟悉,但看起来您也在根据似乎不是预期行为的输出返回 HTML。

解决问题

首先要做的是以深思熟虑的方式评估您所做的事情。

  • 检查查询

  • 使用像 django-debug-toolbar 这样的东西看看你是否有一些查询瓶颈 - 许多链接在一起的查询,长时间运行的查询等。如果你需要更细化,你的数据库可能有日志功能来记录长查询。

    假设您的数据非常规范化(在正常形式的意义上),这可能是引入非规范化的地方,因此您不必遍历尽可能多的关系。

    您还可以引入原始 SQL(但您似乎已经这样做了)。
  • 检查您的业务逻辑

  • 您应该努力确保您的业务逻辑被放置在请求、响应周期的正确部分。很多时候你把东西放在地方只是为了让它工作,也许你最初的决定是找到它的限制。

    看起来您正在做一些非常简单的事情:获取表中的最后 50 个条目。如果您正在计算是否包含帖子,您可能应该将其留给数据库 - 它应该在涉及检索哪些数据时处理所有逻辑。
  • 检查支持代码

  • 当你这样做的时候,试着做更多的性能测试,看看你的代码有哪些地方落后了。也许您可以做一些事情来改进您的代码(同时使其他人易于阅读和理解)并给您带来性能提升。列表推导、生成器、利用 prefetch_ 和 select_related、注意延迟评估查询 - 所有这些都值得实现,因为它们的功能有很好的文档和理解。也就是说,一定要为你 future 的自己和可能的其他人仔细记录这些决定。

    我不太熟悉 View 代码的实现,因为它与 Django REST 框架相关,我可能会坚持使用它附带的 JSON 序列化程序。
  • 变通方法

  • 另一个有用的技巧是做一些事情,比如实现 pagination策略(但最有可能使用 REST Framework),因此数据只会以小 block 的形式传输到客户端。这将在很大程度上取决于用例。

    这是一个很好的介绍:

    用软件解决问题

    您可以使用 cache将数据保存在服务器的 RAM 中,以便 Django 快速访问它。

    通常,哪种缓存效果最好取决于数据本身。使用搜索引擎存储您经常查询的文档可能是最有用的。但是,一个好的开始是Redis .您可以从各种来源阅读有关实现缓存的所有信息,但使用 Django 进行搜索的好地方是 Django Packages。 .

    用硬件解决问题

    速度也可能与硬件有关。您应该考虑软件的要求及其依赖项。进行一些测试,四处搜索并尝试适合您的方法。在一个问题上投入更多的硬件会导致边际 yield 严重递减。

    关于python - 如何提高 REST API 的性能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32389142/

    相关文章:

    python - seaborn 更改聚类图可视化选项,无需重做聚类

    javascript - 表分页 [Bootstrap - Django]

    Django:如何通过自定义 Django_Admin 动态过滤外键选择

    django - {{ services|pprint|safe }} 中的 '|' 在 django 中意味着什么?

    node.js - 如何为 REST API 构建 Mongo 数据库

    python - "' 测试模块错误导入”是什么意思?

    python - 如何在 "Check iO"游戏中使用 tests.py 文件在本地测试代码

    python - 根据距离和出现频率选择一个项目(从一组项目中)

    php - 使用 HTTP DELETE 方法时数据访问的 RESTful 问题

    java - 如何使用带有 JSON 数据的 HTTPURLConnection 发送 POST 请求