Optimización y Despliegue en Producción de Odoo
Primero mide el comportamiento real: tiempo de respuesta, consultas, CPU, memoria e índices. El prefetch del ORM evita muchas consultas repetidas; un bucle sobre un recordset no implica automáticamente un problema N+1.
1. ORM y cálculos #
Usa search_read cuando necesitas resultados serializados y search_fetch cuando necesitas recordsets con campos precargados. Agrupa escrituras y creaciones, sin prometer una única consulta SQL: herencias, campos calculados, mensajes y validaciones pueden generar trabajo adicional.
1books = env['library.book'].search([('state', '=', 'draft')]) 2books.write({'state': 'available'})
Añade índices a consultas justificadas por mediciones. store=True hace buscable y agrupable un cálculo almacenado, a cambio de escrituras y recomputaciones. También puede definirse una búsqueda específica para campos no almacenados. Ninguna de estas opciones mejora siempre el rendimiento.
2. Configuración de producción #
Este escenario usa Nginx como contenedor en la misma red de Compose. Utiliza un proyecto y volúmenes distintos a los de desarrollo. Sustituye dominio y rutas de certificados por valores reales antes de arrancar.
Fichero config/odoo.conf:
1[options] 2addons_path = /mnt/extra-addons 3data_dir = /var/lib/odoo 4http_interface = 0.0.0.0 5proxy_mode = True 6db_name = curso_odoo 7dbfilter = ^curso_odoo$ 8list_db = False 9workers = 5 10max_cron_threads = 1 11gevent_port = 8072 12; 2 GiB por proceso: dimensionar para la RAM disponible 13limit_memory_soft = 2147483648 14; 2.5 GiB por proceso 15limit_memory_hard = 2684354560 16limit_time_cpu = 60 17limit_time_real = 120
Define además admin_passwd con una contraseña maestra propia o un hash generado por Odoo, en la configuración privada del despliegue. No uses un hash inventado ni publiques secretos. proxy_mode solo debe habilitarse detrás de un proxy de confianza; los puertos de Odoo no se publican directamente.
La fórmula orientativa (CPU * 2) + 1 no basta: ajusta workers por memoria, carga y mediciones. Los límites son por proceso. Los comentarios del INI van en líneas independientes para no interferir con la conversión de números.
Fichero compose.yaml:
1services: 2 web: 3 image: odoo:20.0 4 depends_on: 5 db: 6 condition: service_healthy 7 environment: 8 HOST: db 9 USER: odoo 10 PASSWORD: ${ODOO_DB_PASSWORD:?Define ODOO_DB_PASSWORD} 11 volumes: 12 - odoo-web-data:/var/lib/odoo 13 - ./config/odoo.conf:/etc/odoo/odoo.conf:ro 14 - ./extra-addons:/mnt/extra-addons:ro 15 restart: unless-stopped 16 db: 17 image: postgres:16 18 environment: 19 POSTGRES_DB: postgres 20 POSTGRES_USER: odoo 21 POSTGRES_PASSWORD: ${ODOO_DB_PASSWORD:?Define ODOO_DB_PASSWORD} 22 healthcheck: 23 test: ["CMD-SHELL", "pg_isready -U odoo -d postgres"] 24 interval: 5s 25 timeout: 5s 26 retries: 12 27 volumes: 28 - odoo-db-data:/var/lib/postgresql/data 29 restart: unless-stopped 30 nginx: 31 image: nginx:stable 32 depends_on: 33 - web 34 ports: 35 - "80:80" 36 - "443:443" 37 volumes: 38 - ./nginx/default.conf:/etc/nginx/conf.d/default.conf:ro 39 - ./certs:/etc/nginx/certs:ro 40 restart: unless-stopped 41volumes: 42 odoo-web-data: 43 odoo-db-data:
El archivo sustituye el Compose de desarrollo: no mantengas su publicación de 8069. Nginx resuelve web mediante la red interna; no busca Odoo en su propio 127.0.0.1. Los certificados fullchain.pem y privkey.pem deben existir en certs y tener renovación configurada fuera de este ejemplo.
Fichero nginx/default.conf:
1map $http_upgrade $connection_upgrade { 2 default upgrade; 3 '' close; 4} 5upstream odoo { server web:8069; } 6upstream odoochat { server web:8072; } 7server { 8 listen 80; 9 server_name erp.example.com; 10 return 301 https://$host$request_uri; 11} 12server { 13 listen 443 ssl; 14 server_name erp.example.com; 15 ssl_certificate /etc/nginx/certs/fullchain.pem; 16 ssl_certificate_key /etc/nginx/certs/privkey.pem; 17 client_max_body_size 100M; 18 proxy_read_timeout 720s; 19 proxy_set_header Host $host; 20 proxy_set_header X-Real-IP $remote_addr; 21 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 22 proxy_set_header X-Forwarded-Proto $scheme; 23 location / { 24 proxy_pass http://odoo; 25 } 26 location /websocket { 27 proxy_pass http://odoochat; 28 proxy_http_version 1.1; 29 proxy_set_header Upgrade $http_upgrade; 30 proxy_set_header Connection $connection_upgrade; 31 proxy_set_header Host $host; 32 proxy_set_header X-Real-IP $remote_addr; 33 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 34 proxy_set_header X-Forwarded-Proto $scheme; 35 } 36}
Comprueba nginx -t, HTTPS, carga de assets, descargas y conexión WebSocket. Vigila errores HTTP, tiempos y memoria. Guarda copias consistentes de PostgreSQL y filestore y ensaya una restauración.
3. Actualizaciones y migraciones #
-u modulo actualiza un addon instalado. post_init_hook se ejecuta tras instalar, no es un script de actualización. Los cambios de datos o identificadores requieren scripts de upgrade versionados, probados sobre una copia. Una migración entre versiones mayores requiere adaptar código y datos; revisa la disponibilidad de OpenUpgrade para las versiones concretas antes de prometer una ruta de migración.