Django StreamingHttpResponse передает потоки локально, но не в производстве
Я размещаю этот вопрос после долгих исследований, но не получил ни одного решения, которое бы мне помогло. Я не знаю, что я делаю неправильно, так как я новичок в Django
Ниже приведена моя кодовая база для stream.py
import json
from django.http import StreamingHttpResponse
from decimal import Decimal
class DecimalEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, Decimal):
return str(obj) # or float(obj)
return super(DecimalEncoder, self).default(obj)
class StreamResponseMixin:
def stream_response(self, queryset, serializer_class, gen_message_func=None):
def generate_stream():
for item in queryset:
serializer = serializer_class(item)
yield self.gen_message(serializer.data, gen_message_func)
response = StreamingHttpResponse(generate_stream(), content_type='text/event-stream')
response['X-Accel-Buffering'] = 'no' # Disable buffering in nginx
response['Cache-Control'] = 'no-cache' # Ensure clients don't cache the data
response['Transfer-Encoding'] = 'chunked'
return response
def gen_message(self, data, gen_message_func=None):
if gen_message_func:
return gen_message_func(data)
return '{}\n'.format(json.dumps(data, cls=DecimalEncoder)) # Default behavior if no custom message generator is provided
Views.py
class PackageViewSet(viewsets.ModelViewSet, StreamResponseMixin):
queryset = Package.objects.all().order_by('-created_at')
def get_serializer_class(self):
if self.action in ['list', 'modified']:
return PackageListSerializer
return PackageDetailSerializer
def get_queryset(self):
user = self.request.user
package_queryset = Package.objects.all().order_by('-created_at')
package_queryset = package_queryset.select_related('customer', 'creator').prefetch_related(
Prefetch('products', queryset=Product.objects.all()),
)
try:
customer = Customer.objects.get(user=user)
package_queryset = package_queryset.filter(customer=customer)
except ObjectDoesNotExist:
pass
return package_queryset
@action(detail=False, methods=['GET'], url_path='stream-packages')
def get_stream(self, *args, **kwargs):
packages = self.get_queryset().iterator(chunk_size=50)
return self.stream_response(queryset=packages, serializer_class=PackageListSerializer)
nginx.conf
server {
listen 443 ssl;
server_name abc.api.ai;
ssl_certificate /etc/letsencrypt/live/abc.api.ai/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/abc.api.ai/privkey.pem;
location / {
if ($internal_ips = 0) {
return 403;
}
proxy_pass http://abc-backend-staging:8000;
include proxy.conf;
}
location /api/packages/stream-packages/ {
proxy_pass http://abc-backend-staging:8000;
include proxy.conf;
proxy_http_version 1.1;
proxy_set_header Connection "";
chunked_transfer_encoding on;
proxy_buffering off;
proxy_request_buffering off;
}
}
proxy.conf, который включен в nginx.conf
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto "https";
entrypoint.sh, поскольку мое приложение развертывается через контейнер docker
exec poetry run uvicorn myapplication.asgi:application --host 0.0.0.0 --port 8000
Я не знаю, чего мне не хватает, хотя на localhost он работает, но не в production.
Я пробовал различные решения по настройке Nginx, размещенные на Github, StackOverflow и официальном форуме Django, но ни одно из них не сработало в моем случае. Однако в большинстве случаев решением была установка "proxy_buffering off", но и она не сработала в моем случае.
Я столкнулся с той же проблемой, что и здесь, но предоставленное решение не работает в моем случае
Дополнительно для некоторых конечных точек API он отображает данные после получения всех за один раз, а для некоторых даже не отправляет их, поскольку конечные точки содержат больше данных по сравнению с другими.
Сейчас я чувствую себя подавленным после того, как потратил несколько дней на решение этой проблемы. Любая помощь будет очень признательна.
Спасибо!