vLLM ومحركات الاستدلال مفتوحة المصدر
نشر vLLM في الإنتاج
4 دقيقة للقراءة
الانتقال من التطوير إلى الإنتاج يتطلب تكويناً دقيقاً للموثوقية والأداء وقابلية التوسع.
نشر Docker
إعداد Docker الأساسي
# Dockerfile لإنتاج vLLM
FROM vllm/vllm-openai:latest
# تعيين متغيرات البيئة
ENV VLLM_WORKER_MULTIPROC_METHOD=spawn
ENV CUDA_VISIBLE_DEVICES=0,1,2,3
# فحص الصحة
HEALTHCHECK \
CMD curl -f http://localhost:8000/health || exit 1
# الأمر الافتراضي
CMD ["--model", "meta-llama/Llama-3.3-70B-Instruct", \
"--tensor-parallel-size", "4", \
"--port", "8000"]
Docker Compose لـ Multi-GPU
# docker-compose.yml
version: '3.8'
services:
vllm:
image: vllm/vllm-openai:latest
container_name: vllm-server
ports:
- "8000:8000"
volumes:
- ~/.cache/huggingface:/root/.cache/huggingface
environment:
- HUGGING_FACE_HUB_TOKEN=${HF_TOKEN}
- CUDA_VISIBLE_DEVICES=0,1,2,3
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: 4
capabilities: [gpu]
command: >
--model meta-llama/Llama-3.3-70B-Instruct
--tensor-parallel-size 4
--gpu-memory-utilization 0.9
--max-model-len 32768
--enable-prefix-caching
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 120s
restart: unless-stopped
نشر Kubernetes
النشر الأساسي
# vllm-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: vllm-server
labels:
app: vllm
spec:
replicas: 1 # التوسع مع HPA
selector:
matchLabels:
app: vllm
template:
metadata:
labels:
app: vllm
spec:
containers:
- name: vllm
image: vllm/vllm-openai:latest
ports:
- containerPort: 8000
args:
- "--model"
- "meta-llama/Llama-3.3-70B-Instruct"
- "--tensor-parallel-size"
- "4"
- "--gpu-memory-utilization"
- "0.9"
- "--port"
- "8000"
resources:
limits:
nvidia.com/gpu: 4
memory: "128Gi"
requests:
nvidia.com/gpu: 4
memory: "64Gi"
env:
- name: HUGGING_FACE_HUB_TOKEN
valueFrom:
secretKeyRef:
name: hf-token
key: token
volumeMounts:
- name: model-cache
mountPath: /root/.cache/huggingface
livenessProbe:
httpGet:
path: /health
port: 8000
initialDelaySeconds: 120
periodSeconds: 30
readinessProbe:
httpGet:
path: /health
port: 8000
initialDelaySeconds: 60
periodSeconds: 10
volumes:
- name: model-cache
persistentVolumeClaim:
claimName: model-cache-pvc
nodeSelector:
nvidia.com/gpu.product: "NVIDIA-A100-SXM4-80GB"
tolerations:
- key: "nvidia.com/gpu"
operator: "Exists"
effect: "NoSchedule"
---
apiVersion: v1
kind: Service
metadata:
name: vllm-service
spec:
selector:
app: vllm
ports:
- port: 8000
targetPort: 8000
type: ClusterIP
مقياس الحاوية الأفقي التلقائي
# vllm-hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: vllm-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: vllm-server
minReplicas: 1
maxReplicas: 4
metrics:
- type: Pods
pods:
metric:
name: vllm_num_requests_waiting
target:
type: AverageValue
averageValue: "10" # التوسع عند الطابور > 10
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 80
behavior:
scaleUp:
stabilizationWindowSeconds: 60
policies:
- type: Pods
value: 1
periodSeconds: 60
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Pods
value: 1
periodSeconds: 120
تكوين الإنتاج
إعدادات الخادم المحسنة
# سكريبت تشغيل الإنتاج
#!/bin/bash
export CUDA_VISIBLE_DEVICES=0,1,2,3
export VLLM_WORKER_MULTIPROC_METHOD=spawn
export VLLM_LOGGING_LEVEL=INFO
vllm serve meta-llama/Llama-3.3-70B-Instruct \
# التوازي
--tensor-parallel-size 4 \
# تحسين الذاكرة
--gpu-memory-utilization 0.92 \
--max-model-len 32768 \
--enable-prefix-caching \
# الجدولة
--enable-chunked-prefill \
--max-num-seqs 256 \
--max-num-batched-tokens 8192 \
# التكميم (اختياري)
--quantization fp8 \
# إعدادات الخادم
--port 8000 \
--host 0.0.0.0 \
--api-key "${VLLM_API_KEY}" \
# التسجيل
--disable-log-requests \ # تقليل I/O
--disable-log-stats # أو تمكين للمراقبة
موازنة الحمل
# nginx.conf لموازنة حمل vLLM
upstream vllm_cluster {
least_conn; # التوجيه إلى الخادم الأقل انشغالاً
server vllm-1:8000 weight=1;
server vllm-2:8000 weight=1;
server vllm-3:8000 weight=1;
keepalive 32;
}
server {
listen 80;
location /v1 {
proxy_pass http://vllm_cluster;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
# دعم البث
proxy_buffering off;
proxy_cache off;
# المهلات للتوليد الطويل
proxy_read_timeout 300s;
proxy_send_timeout 300s;
}
location /health {
proxy_pass http://vllm_cluster/health;
}
}
النشر متعدد العقد
للنماذج الأكبر من سعة العقدة الواحدة:
# العقدة 0 (رأس Ray)
ray start --head --port=6379
# العقدة 1-N (عمال Ray)
ray start --address='head-node-ip:6379'
# تشغيل vLLM عبر المجموعة
vllm serve meta-llama/Llama-3.1-405B-Instruct \
--tensor-parallel-size 8 \
--pipeline-parallel-size 2 \
--distributed-executor-backend ray
# Kubernetes متعدد العقد مع Ray
apiVersion: ray.io/v1
kind: RayCluster
metadata:
name: vllm-cluster
spec:
rayVersion: '2.9.0'
headGroupSpec:
rayStartParams:
dashboard-host: '0.0.0.0'
template:
spec:
containers:
- name: ray-head
image: vllm/vllm-openai:latest
resources:
limits:
nvidia.com/gpu: 8
workerGroupSpecs:
- replicas: 1
rayStartParams: {}
template:
spec:
containers:
- name: ray-worker
image: vllm/vllm-openai:latest
resources:
limits:
nvidia.com/gpu: 8
المراقبة وفحوصات الصحة
# نقطة نهاية فحص صحة مخصصة
import httpx
import asyncio
async def check_vllm_health(base_url: str) -> dict:
async with httpx.AsyncClient() as client:
# الصحة الأساسية
health = await client.get(f"{base_url}/health")
# المقاييس التفصيلية
metrics = await client.get(f"{base_url}/metrics")
# تحليل المقاييس الرئيسية
return {
"healthy": health.status_code == 200,
"num_requests_running": parse_metric(metrics, "vllm_num_requests_running"),
"num_requests_waiting": parse_metric(metrics, "vllm_num_requests_waiting"),
"gpu_cache_usage": parse_metric(metrics, "vllm_gpu_cache_usage_perc"),
}
نشر الإنتاج يتطلب موازنة الأداء والتكلفة والموثوقية. ابدأ بشكل محافظ واضبط بناءً على أنماط الحمل الفعلية.
التالي، سنستكشف محركات الاستدلال البديلة ومتى نختارها. :::