Django REST Framework - медлительность POST, когда размер тела превышает 1024 символа - PullRequest
0 голосов
/ 08 ноября 2018

Я использую DRF. Я обнаружил, что получение POST с более чем 1024 символами влечет за собой штраф ~ 1 секунда, в то время как любое меньшее, чем это, эффективно бесплатно. Я упростил это в этом тривиальном примере:

# views.py
import time
from rest_framework.decorators import api_view
from django.http import HttpResponse

@api_view(['POST'])
def test_endpoint(request):

    t = time.time()
    data = request.body
    total_time = time.time() - t

    print('got post data:', round(total_time, 3))
    return HttpResponse('body size:{} time:{}'.format(len(data), round(total_time, 3)))


# url.py
urlpatterns = [
    url(r'^test_endpoint', test_endpoint),
]

Вы можете видеть, что все , которое я делаю, читает request.body и измеряет время, необходимое для этого. Затем я отвечаю тем же временем и значением request.body (чтобы доказать, что я к нему обращался).

Затем я выполняю эти локоны:

$ time curl -X POST http://127.0.0.1:8000/test_endpoint -d 0123456782345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567901234567890123456789012345678901234567
body size:1024 time:0.0
real    0m0.045s
user    0m0.006s
sys 0m0.009s
$ time curl -X POST http://127.0.0.1:8000/test_endpoint -d 01234567823456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345679012345678901234567890123456789012345678
body size:1025 time:0.999
real    0m1.020s
user    0m0.006s
sys 0m0.006s

Вы можете видеть, что у второго есть один дополнительный символ, и это приводит к штрафу ~ 1 секунды до готовности request.body.

Почему это? Как я могу предотвратить это?

Подробнее

Я сделал это как можно более ванильно. Я создал новый проект с django-admin startproject helloworld_project .. Я положил код выше в него. И запустить его локально с python manage.py runserver. У меня нет веб-сервера перед ним; Я обращаюсь к нему напрямую через браузер. Это все, что я делаю.

Кроме того, я делаю это на Django==1.11. Эта проблема, кажется, уходит на Django==2.0. Я не могу легко перейти на 2.0. Есть ли решение этой проблемы на 1.11?

1 Ответ

0 голосов
/ 09 ноября 2018

Давайте углубимся и посмотрим, где настоящая медлительность.

Эта функция вызывается из body property.

def read(self, *args, **kwargs):
    self._read_started = True
    try:
        import time
        t = time.time()
        data = self._stream.read(*args, **kwargs)  # HERE(!)
        total_time = time.time() - t
        print('TOTAL TIME: ', total_time)
        return data
    except IOError as e:
        six.reraise(UnreadablePostError, UnreadablePostError(*e.args), sys.exc_info()[2])

Для 1024 символов: TOTAL TIME: 3.123283386230469e-05

Для 1025 символов: TOTAL TIME: 0.991084098815918


Хм ... Эта проблема исчезла в Django 2.0, давайте посмотрим заметки о выпуске :

Запросы и ответы

Веб-сервер runserver поддерживает HTTP 1.1.

HTTP 1.1 Поддерживает chunked передач , в то время как HTTP 1.0 нет. Я думаю, что это может объяснить медленное поведение.


Есть ли решение этой проблемы для 1.11?

По умолчанию runserver Я считаю, что ответ Нет . Но вы не будете использовать его в производстве, верно? Любой другой рабочий сервер, например gunicorn, uWSGI, поддерживает HTTP 1.1.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...