gRPC va DRF | Qo'llanma

Bu maqolada gRPC va Django REST Framework haqida gaplashamiz.
26th June 2025
Kirish
Zamonaviy dasturlashda turli xil servislar orasida ma'lumot almashish juda muhim. Bugungi kunda biz gRPC va Django REST Framework (DRF) haqida gaplashamiz. Bu texnologiyalar qanday ishlashini, qachon ishlatishni va real loyihalarda qanday qo'llashni o'rganamiz.
gRPC nima?
gRPC - bu Google tomonidan yaratilgan zamonaviy, tez va samarali komunikatsiya protokoli. Oddiy qilib aytganda, bu turli dasturlar orasida ma'lumot almashish uchun ishlatiladi.
gRPC ning asosiy xususiyatlari:
- Tezlik: HTTP/2 protokolini ishlatadi, shuning uchun juda tez
- Kichik hajm: Ma'lumotlarni siqib yuboradi
- Har xil tillar: Python, Java, Go, C++ va boshqa tillarda ishlaydi
- Ikki tomonlama aloqa: Bir vaqtda ham yuborish, ham qabul qilish mumkin
Nega gRPC + DRF?
Biz nima uchun bu ikki texnologiyani birga ishlatishimiz kerak?
1. Har birining kuchli tomonlari
- DRF: Web API yaratish uchun juda qulay
- gRPC: Servislar orasida tez ma'lumot almashish
2. Real loyihalarda
Katta loyihalarda turli xil servislar bo'ladi:
- Web API (DRF bilan)
- Internal servislar (gRPC bilan)
- Mobile API (DRF bilan)
- Mikroservislar (gRPC bilan)
Qachon gRPC ishlatamiz?
gRPC ishlatish kerak bo'lgan holatlar:
- Tezlik muhim: Millionlab so'rov keladi
- Mikroservislar: Ko'p kichik servislar bir-biri bilan gaplashadi
- Real-time: Jonli chat, gaming
- Katta ma'lumotlar: Rasmlar, videolar
DRF ishlatish kerak bo'lgan holatlar:
- Web API: Brauzer uchun
- Mobile API: Telefon ilovalari uchun
- Tashqi integratsiya: Boshqa kompaniyalar bilan
- Prototyping: Tez sinab ko'rish uchun
Amaliy misol: E-commerce loyihasi
Keling, real loyiha qurshimiz. Bu loyihada:
- DRF: Mijozlar uchun API
- gRPC: Ichki servislar orasida aloqa
Loyiha strukturasi
ecommerce/
├── api/ # DRF API
├── grpc_services/ # gRPC servislar
├── proto/ # Protocol Buffer fayllari
└── common/ # Umumiy kodlar
1-qadam: Muhitni tayyorlash
Kerakli kutubxonalarni o'rnatamiz:
pip install django
pip install djangorestframework
pip install grpcio
pip install grpcio-tools
pip install protobuf
Django loyihasini yaratish
django-admin startproject ecommerce
cd ecommerce
python manage.py startapp api
python manage.py startapp grpc_services
2-qadam: Protocol Buffer fayli yaratish
proto/product.proto
faylini yaratamiz:
syntax = "proto3";
package product;
// Product service
service ProductService {
rpc GetProduct(GetProductRequest) returns (ProductResponse);
rpc CreateProduct(CreateProductRequest) returns (ProductResponse);
rpc UpdateStock(UpdateStockRequest) returns (StockResponse);
}
// So'rovlar
message GetProductRequest {
int32 product_id = 1;
}
message CreateProductRequest {
string name = 1;
string description = 2;
double price = 3;
int32 stock = 4;
}
message UpdateStockRequest {
int32 product_id = 1;
int32 quantity = 2;
}
// Javoblar
message ProductResponse {
int32 id = 1;
string name = 2;
string description = 3;
double price = 4;
int32 stock = 5;
bool success = 6;
string message = 7;
}
message StockResponse {
bool success = 1;
string message = 2;
int32 new_stock = 3;
}
Python kodlarini yaratish
python -m grpc_tools.protoc -I./proto --python_out=./grpc_services --grpc_python_out=./grpc_services proto/product.proto
3-qadam: Django modellari
api/models.py
:
from django.db import models
class Product(models.Model):
name = models.CharField(max_length=200)
description = models.TextField()
price = models.DecimalField(max_digits=10, decimal_places=2)
stock = models.IntegerField(default=0)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.name
class Meta:
db_table = 'products'
4-qadam: gRPC Server yaratish
grpc_services/product_server.py
:
import grpc
from concurrent import futures
import sys
import os
# Django sozlamalarini yuklash
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'ecommerce.settings')
import django
django.setup()
from api.models import Product
from . import product_pb2
from . import product_pb2_grpc
class ProductService(product_pb2_grpc.ProductServiceServicer):
def GetProduct(self, request, context):
"""Mahsulot ma'lumotlarini olish"""
try:
product = Product.objects.get(id=request.product_id)
return product_pb2.ProductResponse(
id=product.id,
name=product.name,
description=product.description,
price=float(product.price),
stock=product.stock,
success=True,
message="Mahsulot topildi"
)
except Product.DoesNotExist:
return product_pb2.ProductResponse(
success=False,
message="Mahsulot topilmadi"
)
except Exception as e:
return product_pb2.ProductResponse(
success=False,
message=f"Xatolik: {str(e)}"
)
def CreateProduct(self, request, context):
"""Yangi mahsulot yaratish"""
try:
product = Product.objects.create(
name=request.name,
description=request.description,
price=request.price,
stock=request.stock
)
return product_pb2.ProductResponse(
id=product.id,
name=product.name,
description=product.description,
price=float(product.price),
stock=product.stock,
success=True,
message="Mahsulot yaratildi"
)
except Exception as e:
return product_pb2.ProductResponse(
success=False,
message=f"Xatolik: {str(e)}"
)
def UpdateStock(self, request, context):
"""Mahsulot sonini yangilash"""
try:
product = Product.objects.get(id=request.product_id)
product.stock += request.quantity
product.save()
return product_pb2.StockResponse(
success=True,
message="Stock yangilandi",
new_stock=product.stock
)
except Product.DoesNotExist:
return product_pb2.StockResponse(
success=False,
message="Mahsulot topilmadi"
)
except Exception as e:
return product_pb2.StockResponse(
success=False,
message=f"Xatolik: {str(e)}"
)
def serve():
"""gRPC serverni ishga tushirish"""
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
product_pb2_grpc.add_ProductServiceServicer_to_server(
ProductService(), server
)
listen_addr = '[::]:50051'
server.add_insecure_port(listen_addr)
print(f"gRPC server {listen_addr} da ishlamoqda...")
server.start()
server.wait_for_termination()
if __name__ == '__main__':
serve()
5-qadam: DRF API yaratish
api/serializers.py
:
from rest_framework import serializers
from .models import Product
class ProductSerializer(serializers.ModelSerializer):
class Meta:
model = Product
fields = '__all__'
read_only_fields = ('created_at', 'updated_at')
class ProductCreateSerializer(serializers.ModelSerializer):
class Meta:
model = Product
fields = ('name', 'description', 'price', 'stock')
def validate_price(self, value):
if value <= 0:
raise serializers.ValidationError("Narx 0 dan katta bo'lishi kerak")
return value
def validate_stock(self, value):
if value < 0:
raise serializers.ValidationError("Stock manfiy bo'lishi mumkin emas")
return value
api/views.py
:
from rest_framework import viewsets, status
from rest_framework.decorators import action
from rest_framework.response import Response
from django.shortcuts import get_object_or_404
import grpc
from .models import Product
from .serializers import ProductSerializer, ProductCreateSerializer
from .grpc_client import ProductGRPCClient
class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
def get_serializer_class(self):
if self.action == 'create':
return ProductCreateSerializer
return ProductSerializer
@action(detail=True, methods=['post'])
def update_stock(self, request, pk=None):
"""Stock yangilash (gRPC orqali)"""
product = get_object_or_404(Product, pk=pk)
quantity = request.data.get('quantity', 0)
try:
quantity = int(quantity)
except ValueError:
return Response(
{'error': 'Quantity raqam bo\'lishi kerak'},
status=status.HTTP_400_BAD_REQUEST
)
# gRPC client orqali yangilash
grpc_client = ProductGRPCClient()
result = grpc_client.update_stock(product.id, quantity)
if result['success']:
# Mahalliy ma'lumotni ham yangilash
product.refresh_from_db()
serializer = self.get_serializer(product)
return Response({
'product': serializer.data,
'message': result['message']
})
else:
return Response(
{'error': result['message']},
status=status.HTTP_400_BAD_REQUEST
)
@action(detail=False, methods=['post'])
def create_via_grpc(self, request):
"""gRPC orqali mahsulot yaratish"""
grpc_client = ProductGRPCClient()
result = grpc_client.create_product(
name=request.data.get('name', ''),
description=request.data.get('description', ''),
price=float(request.data.get('price', 0)),
stock=int(request.data.get('stock', 0))
)
if result['success']:
return Response(result['product'], status=status.HTTP_201_CREATED)
else:
return Response(
{'error': result['message']},
status=status.HTTP_400_BAD_REQUEST
)
6-qadam: gRPC Client yaratish
api/grpc_client.py
:
import grpc
import sys
import os
# gRPC fayllarini import qilish
sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'grpc_services'))
from grpc_services import product_pb2
from grpc_services import product_pb2_grpc
class ProductGRPCClient:
def __init__(self, host='localhost', port=50051):
self.host = host
self.port = port
self.channel = None
self.stub = None
def connect(self):
"""gRPC serverga ulanish"""
self.channel = grpc.insecure_channel(f'{self.host}:{self.port}')
self.stub = product_pb2_grpc.ProductServiceStub(self.channel)
def disconnect(self):
"""Ulanishni yopish"""
if self.channel:
self.channel.close()
def get_product(self, product_id):
"""Mahsulot ma'lumotlarini olish"""
try:
self.connect()
request = product_pb2.GetProductRequest(product_id=product_id)
response = self.stub.GetProduct(request)
return {
'success': response.success,
'message': response.message,
'product': {
'id': response.id,
'name': response.name,
'description': response.description,
'price': response.price,
'stock': response.stock
} if response.success else None
}
except grpc.RpcError as e:
return {
'success': False,
'message': f'gRPC xatolik: {e.details()}'
}
finally:
self.disconnect()
def create_product(self, name, description, price, stock):
"""Yangi mahsulot yaratish"""
try:
self.connect()
request = product_pb2.CreateProductRequest(
name=name,
description=description,
price=price,
stock=stock
)
response = self.stub.CreateProduct(request)
return {
'success': response.success,
'message': response.message,
'product': {
'id': response.id,
'name': response.name,
'description': response.description,
'price': response.price,
'stock': response.stock
} if response.success else None
}
except grpc.RpcError as e:
return {
'success': False,
'message': f'gRPC xatolik: {e.details()}'
}
finally:
self.disconnect()
def update_stock(self, product_id, quantity):
"""Stock yangilash"""
try:
self.connect()
request = product_pb2.UpdateStockRequest(
product_id=product_id,
quantity=quantity
)
response = self.stub.UpdateStock(request)
return {
'success': response.success,
'message': response.message,
'new_stock': response.new_stock
}
except grpc.RpcError as e:
return {
'success': False,
'message': f'gRPC xatolik: {e.details()}'
}
finally:
self.disconnect()
7-qadam: URL routing
api/urls.py
:
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import ProductViewSet
router = DefaultRouter()
router.register(r'products', ProductViewSet)
urlpatterns = [
path('api/', include(router.urls)),
]
ecommerce/urls.py
:
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('api.urls')),
]
8-qadam: Django sozlamalari
ecommerce/settings.py
ga qo'shish:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework', # DRF
'api', # Bizning API
]
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.AllowAny',
],
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 20
}
# Database
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
9-qadam: Ma'lumotlar bazasini yaratish
python manage.py makemigrations
python manage.py migrate
python manage.py createsuperuser
10-qadam: Testlash
gRPC serverni ishga tushirish
python grpc_services/product_server.py
Django serverni ishga tushirish
python manage.py runserver
API testlari
- Mahsulot yaratish (POST):
curl -X POST http://localhost:8000/api/products/ \
-H "Content-Type: application/json" \
-d '{
"name": "Laptop",
"description": "Gaming laptop",
"price": 1500.00,
"stock": 10
}'
- Stock yangilash (POST):
curl -X POST http://localhost:8000/api/products/1/update_stock/ \
-H "Content-Type: application/json" \
-d '{"quantity": 5}'
- gRPC orqali yaratish (POST):
curl -X POST http://localhost:8000/api/products/create_via_grpc/ \
-H "Content-Type: application/json" \
-d '{
"name": "Telefon",
"description": "Smartphone",
"price": 800.00,
"stock": 15
}'
Performance taqqoslash
DRF vs gRPC tezligi
Operatsiya | DRF | gRPC | Foydasi |
---|---|---|---|
1000 so'rov | 2.5s | 0.8s | 3x tez |
Ma'lumot hajmi | 1.2MB | 0.4MB | 3x kichik |
CPU foydalanish | 45% | 20% | 2x kam |
Xotira iste'moli
# DRF JSON response
{
"id": 1,
"name": "Laptop",
"description": "Gaming laptop",
"price": 1500.00,
"stock": 10,
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T10:30:00Z"
}
# Hajmi: ~180 bayt
# gRPC binary response
# Hajmi: ~45 bayt (4x kichik)
Xatoliklarni hal qilish
Keng uchraydigan xatoliklar
- gRPC server ishlamayapti
# Tekshirish
import grpc
channel = grpc.insecure_channel('localhost:50051')
try:
grpc.channel_ready_future(channel).result(timeout=10)
print("Server ishlayapti")
except grpc.FutureTimeoutError:
print("Server ishlamayapti")
- Protocol Buffer xatoliklari
# Qaytadan yaratish
python -m grpc_tools.protoc -I./proto --python_out=./grpc_services --grpc_python_out=./grpc_services proto/product.proto
- Import xatoliklari
# PYTHONPATH sozlash
import sys
sys.path.append('/path/to/your/project')
Xavfsizlik
gRPC xavfsizligi
# SSL sertifikat bilan
credentials = grpc.ssl_channel_credentials(
root_certificates=None,
private_key=None,
certificate_chain=None
)
channel = grpc.secure_channel('localhost:50051', credentials)
DRF xavfsizligi
# settings.py
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.TokenAuthentication',
],
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
],
}
Monitoring va Logging
gRPC monitoring
import logging
# Logging sozlash
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
class ProductService(product_pb2_grpc.ProductServiceServicer):
def GetProduct(self, request, context):
logging.info(f"GetProduct so'rovi: {request.product_id}")
# ... kod
DRF monitoring
# middleware.py
import time
import logging
class RequestLoggingMiddleware:
def __init__(self, get_response):
self.get_response = get_response
self.logger = logging.getLogger(__name__)
def __call__(self, request):
start_time = time.time()
response = self.get_response(request)
duration = time.time() - start_time
self.logger.info(
f"{request.method} {request.path} - "
f"{response.status_code} - {duration:.2f}s"
)
return response
Deployment
Docker bilan
Dockerfile
:
FROM python:3.9
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
EXPOSE 8000 50051
# Script yaratish
COPY start.sh .
RUN chmod +x start.sh
CMD ["./start.sh"]
start.sh
:
#!/bin/bash
# Django migratsiyalar
python manage.py migrate
# gRPC serverni background da ishga tushirish
python grpc_services/product_server.py &
# Django serverni ishga tushirish
python manage.py runserver 0.0.0.0:8000
docker-compose.yml
:
version: '3.8'
services:
web:
build: .
ports:
- "8000:8000"
- "50051:50051"
volumes:
- .:/app
environment:
- DEBUG=1
Mikroservislar arxitekturasi
┌─────────────────┐ ┌─────────────────┐
│ Web Client │ │ Mobile Client │
└─────────┬───────┘ └─────────┬───────┘
│ │
└──────────┬───────────┘
│
┌────────▼────────┐
│ API Gateway │
└────────┬────────┘
│
┌────────────┼────────────┐
│ │ │
┌───────▼──────┐ ┌───▼────┐ ┌────▼─────┐
│ User Service │ │ Product│ │ Order │
│ (gRPC) │ │Service │ │ Service │
└──────────────┘ │(gRPC) │ │ (gRPC) │
└────────┘ └──────────┘
Xulosa
gRPC va DRF ni birga ishlatish katta loyihalarda juda foydali:
Asosiy faydalar:
- Tezlik: gRPC 3x tez
- Hajm: 4x kichik ma'lumot
- Moslashuvchanlik: Har xil vazifalar uchun mos vosita
- Kengaytirilish: Mikroservislar uchun tayyor
Ishlatish bo'yicha tavsiyalar:
- Kichik loyihalar: Faqat DRF
- O'rta loyihalar: DRF + ba'zi gRPC servislar
- Katta loyihalar: Ko'p gRPC servislar + DRF API Gateway
Agar siz yuqori tezlikda ishlaydigan va samarali ma'lumot almashish tizimiga muhtoj bo'lsangiz, gRPC + DRF kombinatsiyasi juda foydali bo'lishi mumkin. Maqolada keltirilgan kod misollaridan foydalangan holda, siz o'z tizimingizda gRPC va DRF'ni birlashtirishni o'rganishingiz mumkin.
p.s) Postni oxirigacha yetib keldganingiz uchun rahmat! Sizga gRPC va DRF bilan ishlashda omad tilayman. Xatoliklar va takliflar bo'lsa, izoh qoldiring. Happy coding! 😊
Qo'shimcha resurslar

Telegram Kanalimizga Qo'shiling
Yangi postlarni o'tkazib yubormaslik uchun telegram kanaliga obuna bo'ling!
@DavronbekDev